Merge changes to make Lumiera installable

This commit is contained in:
Fischlurch 2011-03-07 03:31:19 +01:00
commit ecb7d58a4f
205 changed files with 9951 additions and 2540 deletions

5
.gitignore vendored
View file

@ -10,7 +10,7 @@
optcache
Makefile.in
build/*
bin/*
target/*
autom4te.cache/*
scripts/*
configure
@ -18,6 +18,7 @@ config.log
aclocal.m4
autom4te.cache
semantic.cache
tests/,*
wiki/backups/*
doc/devel/draw/*.png
doc/devel/uml/fig128309.png
m4/*

168
AUTHORS
View file

@ -1,58 +1,134 @@
Lumiera Authors and Credits
===========================
Version: 0.pre.0.1
Date: 2/2011
Cinelerra(2) Authors
====================
hv=Jack Crossfire <broadcast@earthling.net>
j6t=Johannes Sixt <johannes.sixt@telecom.at>
minmax=Andraz Tori <Andraz.tori1@guest.arnes.si>
herman=Herman Robak <herman@skolelinux.no>
baver=Richard Baverstock <baver@thebeever.com>
pere=Petter Reinholdtsen <pere@hungry.com>
tfheen=Tollef Fog Heen <tollef@add.no>
andreask=Andreas Kielb <andreaskielb@web.de>
theraz=Tyler Geddes <tgeddes@wgeddes.com>
dyce=Gergely Erdelyi <dyce@rovidzar.hu>
dreamlx=David Arendt <admin@prnet.org>
ga=Gustavo Iniguez <ga@kutxa.homeunix.org>
memenk=Michael Eric Menk <meklev@osys.grm.hia.no>
benjif=Benjamin Flaming <cinelerra@solobanjo.com>
cobra=Kevin Brosius <cobra@compuserve.com>
taraba=Mark Taraba <m_taraba@yahoo.com>
nate=Nathan Kurz <nate@verse.com>
mammique=Camille Harang <mammique@garbure.org>
kbielefe=Karl Bielefeldt <uhauufo02@sneakemail.com>
alexf=Alex Ferrer <alex@ftconsult.com>
pmdumuid=Pierre Dumuid <pierre.dumuid@adelaide.edu.au>
giskard=Riccardo Setti <giskard@autistici.org>
jstewart=Joe Stewart <jstewart@lurhq.com>
doudou=Sylvain Joyeux <doudou@melix.net>
rafael2k=Rafael Diniz <rafael@riseup.net>
nicolasm=Nicolas Maufrais <e.conti@gmx.net>
'`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Architecture and Design,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
graphical user interface, JOEL HOLDSWORTH
, CLAY BARNES
processing layer , HERMANN VOSSELER
backend , CHRISTIAN THÄTER
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Involved in Lumiera development
===============================
cehteh=Christian Thaeter <ct@pipapo.org>
ichthyo=Hermann Vosseler <Ichthyostega@web.de>
plouj=Michael Ploujnikov <ploujj@gmail.com>
'`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Programming,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rendering engine, HERMANN VOSSELER
backend, CHRISTIAN THÄTER
GTK-GUI, JOEL HOLDSWORTH
, STEFAN KANGAS
library, HERMANN VOSSELER
, CHRISTIAN THÄTER
, ANTON YAKOVLEV
, SIMEON VÖLKEL
testsuite, CHRISTIAN THÄTER
, NICHOLAS SINNOTT-ARMSTRONG
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Programming Documentation,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
, MICHAEL PLOUJNIKOV
, ODIN HØRTHE OMDAL
, SIMON LARCHER
, SIMEON VÖLKEL
, MANO STIENEN
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Used Software and Libraries,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
boost libraries,
gavl libraries,
gtk+ toolkit,
lua,
nobug,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Builddrone,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
idea and implementation, CHRISTIAN THÄTER
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//'`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ,Testing
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ,
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Workflow design,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
concept , NIKOLA DUPER
, BRIAN RYTEL
, MIKE PROVOST
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Server Administration,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
, CHRISTIAN THÄTER
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cinelerra
---------
Lumiera is an offspring of the Cinelerra video editor. +
It started out as a partial rewrite of Cinelerra in 2007
and turned into a complete rewrite and redesign in Spring 2008
'`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Lumiera project feels especially obliged to,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cinelerra's original Author, ADAM WILLIAMS / aka. "Jack Crossfire" / aka "HV"
Cinelerra-CV , all the numerous contributors
, of the "Community Version"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
_______________________________________________________________
Further Credits
---------------
Parts of the Proc-Layer Implementation are heavily inspired by
The Loki Library
Copyright (c) 2001 by Andrei Alexandrescu
Loki is governed by a MIT-License.
See: http://loki-lib.sourceforge.net
and the book:
Alexandrescu, Andrei.
"Modern C++ Design: Generic Programming and Design
Patterns Applied". Copyright (c) 2001. Addison-Wesley.
ISBN 0201704315
Loki Copyright Notice:
Permission to use, copy, modify, distribute and sell this software for any
.The Loki Library
[quote]
__________________________________________________________________________
Copyright (c) 2001 by *Andrei Alexandrescu* +
.Loki Copyright Notice
* Loki is governed by a MIT-License. See: http://loki-lib.sourceforge.net
* Permission to use, copy, modify, distribute and sell this software for any
purpose is hereby granted without fee, provided that the above copyright
notice appear in all copies and that both that copyright notice and this
permission notice appear in supporting documentation.
The author makes no representations about the suitability of this software
for any purpose. It is provided "as is" without express or implied warranty.
.the ``Loki Book''
[verse]
Alexandrescu, Andrei.
"Modern C++ Design: Generic Programming and Design Patterns Applied".
Copyright (c) 2001. Addison-Wesley.
ISBN 0201704315
_____________________________________________________________________________

239
INSTALL
View file

@ -1,49 +1,82 @@
Running / Installing Lumiera Prototype
======================================
Date: 2/2011
From:
http://www.pipapo.org/pipawiki/Lumiera/NewbiesTutorials
Lumiera uses a fairly standard build system. There are no special quirks.
The build system will tell you about missing library dependencies. You can
build, run the +check+ target for the Testsuite and finally install (as root).
But you don't need to install, because the generated +target+ folder is set up
to be fully relocatable. You can invoke the executables right away, or copy the
whole +target+ folder structure at any location you like. The executables
will always use the direcly accompanying libraries in the +modules+ subdirectory.
The following text is taken from our
link:http://www.pipapo.org/pipawiki/Lumiera/NewbiesTutorials[Newbies Tutorial]
to help beginners getting started with Lumiera development.
Newbies Tutorials
Building Lumiera from source
----------------------------
Currently, after building the application, you can try out the Lumiera GUI
and you can run the testsuite.
This page contains some tutorials for beginners that want to help to the
developers of Lumiera.
For building Lumiera, besides the GNU C/C++ compiler (Version 4.X), you'll need:
Trying the Lumiera GUI from Joel
* http://git-scm.com/[git]
* http://www.gnu.org/software/libtool/[libtool]
* http://www.boost.org/[Boost libraries]
* http://gmerlin.sourceforge.net/[GAVL library]
* *NoBug* (see below)
You need to have:
* libboost
* libtool
* git
* libgavl
* nobug(see below)
For Ubuntu Hardy also:
TIP: Generally speaking, when you want to build software, you need the _development_ version
of the packages, containing the headers and pre-built libraries to link against. Usually,
these packages are named `-devel` or `-dev`
.Notes for Ubuntu:
* libgdl-1-dev
* libgtkmm-2.4-dev
* libxv-dev
For most Debian based systems, e.g. Ubuntu Intrepid and Jaunty, you can install these dependencies with:
------------------------------------------------------------
sudo apt-get install build-essential autoconf libboost-dev libboost-program-options-dev libboost-regex-dev \
libtool libgavl-dev libglade2-dev libgdl-1-dev libgtkmm-2.4-dev libxv-dev scons valgrind librsvg2-dev git-core
------------------------------------------------------------
Optionally, you may also want to install:
* gtk2-engines
also check http://gnuradio.org/trac/wiki/UbuntuInstall#InstallationOptions to
see that all your installations options are met.
Installing nobug from git
Build directory
~~~~~~~~~~~~~~~
You need a directory for checking out the sources and running the build. This could be a temp directory,
or some "workspace" directory below your home directory. We'll call it _workspace directory_ from now on.
Create a temp directory where you can have the sourcecode of the libraries you
will use as well as lumieras branches you want to try. Example ~/temp. cd to
that directory and run:
Lumiera specific libraries
~~~~~~~~~~~~~~~~~~~~~~~~~~
Now that you have your basic build system setup, Lumiera needs a few more special support libraries.
Currently you need to build those from source and install them, so the Lumiera build process can
pick them up.
WARNING: Note that the following procedures will try to install files into your base system below `/usr/local`.
To do so, you'll need administrative permissions for the machine you're working on. These additions might interfere
with other libraries installed by your package manager (if you get into trouble updating your system later on,
sometimes you need to remove these manually built librararies).
Installing NoBug
^^^^^^^^^^^^^^^^
*NoBug* is an instrumentation and diagnostics library. +
Go into the mentioned _workspace direcory_ (maybe create a new directory). First, let's get the NoBug source code:
------------------------------------------------------------
git clone git://git.pipapo.org/nobug
------------------------------------------------------------
This will create a (sub)directory called nobug with sourcecode in your current directory. +
Compile NoBug with the following commands
This will create a directory called nobug with sourcecode in your current
directory.
------------------------------------------------------------
cd nobug
autoreconf -i
mkdir build
@ -51,11 +84,78 @@ cd build
../configure
make
make install
------------------------------------------------------------
Getting the Lumiera source code
Installing GDL
^^^^^^^^^^^^^^
The *GNOME Docking library* is generally available through your package manager, but
we contributed some improvements, which are only available in the very recent development
versions of GDL. Thus, for now we created a special package, which doesn't interfere with
an existing (older) installation of GDL.
In the temp directory
Ubuntu 9.04 note: intltool-update is not patched, you must add /usr/share/intltool-debian/ to get the gdl-package to configure correctly (JSC).
------------------------------------------------------------
git clone git://git.lumiera.org/gdl-package
cd gdl-package
./configure
make
sudo make install
------------------------------------------------------------
For more detailed instructions on how to build gdl (also how to build it into a debian package) see
http://lists.lumiera.org/pipermail/lumiera/2009-April/000891.html[this message on the Lumiera Mailinglist].
check library linkage
^^^^^^^^^^^^^^^^^^^^^
The compile will warn you to add various directories to /etc/ld.so.conf and then run ldconfig. This
will allow your dynamic liker to pick up the newly built libraries later when you try to start Lumiera.
If you don't want to reconfigure your system and add `/usr/local/lib` to the mentioned linker configuration,
you may alternatively just add the directories to your LD_LIBRARY_PATH environment variable.
Either way, check that all libraries are accessible and ok:
------------------------------------------------------------
sudo ldconfig -v | grep 'gdl-lum\|nobug'
------------------------------------------------------------
and you should get a list of the libraries, part of which should look like this:
------------------------------------------------------------
libnobug.so.0 -> /usr/local/lib/libnobug.so.0.0.0
libnobugmt.so.0 -> /usr/local/lib/libnobugmt.so.0.0.0
libgdl-lum.so.0 -> /usr/local/lib/libgdl-lum.so.0.0.0
------------------------------------------------------------
or similar. If any if this libs are not listed, investigate why before continuing.
Building Lumiera
~~~~~~~~~~~~~~~~
Lumiera has two maintained (and equivalent) build systems: *scons* and *autotools*. You can pick the one you
feel more comfortable with.
When trying to build a development version of Lumiera, it might well be that at times one of the builds doesn't work temporarily. It is always a good idea to check the current build stats from our *builddrone*, which automatically builds the latest version from master repository. +
Please have a look at this http://lumiera.org/builddrone/table.html[current build stats]-page.
Next, after having built and installed the prerequisite libraries, go into the _workspace directory_ to retrieve the Lumiera source code and build it.
* to retrieve the sourcecode with git and then build with *scons*:
+
(see available build options by issuing `scons -h` )
+
-----------------
git clone git://git.lumiera.org/LUMIERA
cd LUMIERA
scons
-----------------
+
* alternatively, if you prefer building with autotools (*note*: currently broken as of 3/11):
+
-----------------
git clone git://git.lumiera.org/LUMIERA
cd LUMIERA
autoreconf -fi
@ -63,40 +163,75 @@ mkdir build
cd build
../configure
make
-----------------
maybe run the testsuite by
maybe build and run the testsuite by issuing `scons check` or `make check`
make check
This will take some time.
This will take some time. After it has finished:
./lumiera
Invoking Lumiera
~~~~~~~~~~~~~~~~
NOTE: Currently *only the SCons build creates a relocatable package which can
also be installed*.
After the build has finished successfully, you should be able to start Lumiera.
Currently, this will bring up the GUI, without any further functionality
The +target+ directory generated by the SCons build is fully relocatable -- you can
invoke the executables found there right away and you can copy it at any location you
want, provided you keep the relative location of the contained sub-folders intact.
If you want to include the Lumiera executable into the search path, then just use
a symlink, don't _copy_ the isolated +lumiera+ executable into some +bin+ directory.
Thus
-------------------
target/lumiera
-------------------
should bring up something like (screenshot from 1/2009):
image:http://www.pipapo.org/pipawiki/Lumiera/GuiBrainstorming?action=AttachFile&do=get&target=screenshot090124-resources.jpg[]
_(for autotools build: issue `./lumiera` from within the `build` subdirectory)_
Installing Lumiera
~~~~~~~~~~~~~~~~~~
As of 2/2011, please use the SCons build for that.
Letting aside the fact that you can't do anything useful with the Lumiera in the current stage of development --
you have multiple options for installing Lumiera
* just copy the taget folder somewhere and create a symlink to the +lumiera+ exe
* invoke +scons install INSTALLDIR=... PREFIX=...+
* as root, invoke +scons instal+ to place files at the standard locations below +/usr/local+
* if you're on Debian, you can pull a debian package from +git://git.lumiera.org/lumiera/debian+
This is a source package, you can either use +dpkg_buildpackage+ or +git-buildpackage+ and
then install the generated binary deb with +dpkg -i+
[NewbiesTut]
Contributing
------------
Nothing is easier, follow the basic instructions at http://www.kernel.org/pub/
software/scm/git/docs/gittutorial.html, notably the
Nothing is easier, follow the http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html[the basic instructions],
notably the following parts:
------------------------------------------------------------
$ git config --global user.name "Your Name Comes Here"
$ git config --global user.email you@yourdomain.example.com
parts.
Then you are ready to go, you can edit and commit the lumiera code locally in
your cloned repository. Please do small commits which fix/improve only one
single thing and use meaningful commit messages. Check that you didn't broke
anything
* by running 'make check'.
Finally you can push your changes to the lumiera server to the 'mob'
repository:
$ git push git://git.lumiera.org/lumiera/mob master:refs/heads/YOURNAME
This creates a new branch 'YOURNAME' on the mob repository. Then you notify the
other devs on the mailinglist and they may merge your code into the mainline.
------------------------------------------------------------
Then you are ready to go, you can edit and commit the lumiera code locally in your cloned repository. Please do small commits which fix/improve only one single thing and use meaningful commit messages.
Check that you didn't break anything, by running the testsuite (see above)
Finally you can push your changes to the lumiera server to the 'mob' repository:
------------------------------------------------------------
$ git push git://git.lumiera.org/lumiera/mob master:refs/heads/YOURNAME
------------------------------------------------------------
This creates a new branch 'YOURNAME' on the mob repository. Then you notify the other devs on the mailinglist and they may merge your code into the mainline.

86
README
View file

@ -1,45 +1,73 @@
====================================
Lumiera -- the video NLE for Linux
====================================
Lumiera is a nonlinear video editing and compositing tool.
It understands some of the common multimedia formats
(quicktime, avi, ogg) and audio/video compression
codecs (divx, xvid, mpeg1/2/4, ...).
*************************************************************
Lumiera is a nonlinear video editing and compositing tool.
It understands some of the common multimedia formats
(quicktime, avi, ogg) and audio/video compression
codecs (divx, xvid, mpeg1/2/4, ...)
It features non-destructive editing, compositing tools,
a selection of effects plugins, processing in RGB, YUV
and RGB-float colormodels and the ability to mix media
with differing sizes and framerates.
It features non-destructive editing, compositing tools,
a selection of effects plugins, processing in RGB, YUV
and RGB-float colormodels and the ability to mix media
with differing sizes and framerates.
For more information about Lumiera visit http://lumiera.org/
For more information about Cinelerra visit http://cinelerra.org/
More Informations at http://lumiera.org/[Lumiera.org]
****************************************************************
Lumiera pre-Alpha Versions
--------------------------
----------------------------
"Lumiera" prototype code
----------------------------
**This source tree doesn't yet contain a working video editing application** +
Rather, it contains the framework and technology core of the envisioned Application ``Lumiera''.
**This source tree doesn't yet contain a working video editing application**
Rather, it contains the initial framework and core modules of the lower and
middle layer of the envisioned new Application "Lumiera".
As of 7/2007, we start here with some backend and render engine modules
As of _7/2007_::
we start here with the backend and render engine modules
together with some unit tests. You should find a wiki with detailed
design considerations and developer documentation and a UML model
(usable with BOUML 2.29) in the sibling directories.
As of 2/2008 the project has been separated completely from its
ancestor "Cinelerra". The Community, which is largely identical to the
Cinelerra-CV community, chose the new project name "Lumiera". The
basic project infrastructure is up and running, and work on the new
codebase is going on continuously. We can show nothing but a running
test suite for now.
As of _2/2008_::
the project has been separated completely from his ancestor ``Cinelerra''
The Community, which is largely identical to the Cinelerra-CV community, choose the
new project name ``Lumiera''. The basic project infrastructure is up and running,
and work on the new codebase is going on continuosely. We can show nothing but
a running test suite for some time to come.
As of _1/2011_::
the project has created and documented a fairly consistent design,
partially already coded up -- starting from the technical foundations and working up.
The code base is approaching 100k LOC. Roughly half of this is testcode.
The Application can be installed and started to bring up an GTK GUI outline,
but the GUI is very preliminary and not connected to core functionality.
The video processing pipeline is still not complete.
See the http://issues.lumiera.org/roadmap[Project roadmap]
Build Requirements
------------------
----------------------------
Installation
----------------------------
For building Lumiera, you'll need:
- GNU C/C++ compiler (Version > 4.3)
- Git Version management system
- http://www.boost.org/[Boost libraries]
- http://gmerlin.sourceforge.net/[GAVL library]
- http://lumiera.org/nobug_manual.html[NoBug library]
- GTK\--
- Cairo and Glade libraries
- X libraries
- http://scons.org[SCons] or Autotools build system
See the online documentation at http://lumiera.org/Lumiera/NewbiesTutorials
or the local Copy of this page in the file INSTALL
Debian Package
--------------
[verse]
Hermann Vosseler (aka Ichthyo) maintains a *Debian* packaging of the source tree,
which can be pulled from +git://git.lumiera.org/lumiera/debian+
It can be built by +git-buildpackage+
See INSTALL file

View file

@ -22,26 +22,40 @@
#####################################################################
#-----------------------------------Configuration
OPTIONSCACHEFILE = 'optcache'
CUSTOPTIONSFILE = 'custom-options'
SRCDIR = 'src'
BINDIR = 'bin'
LIBDIR = '.libs'
PLUGDIR = '.libs'
TESTDIR = 'tests'
ICONDIR = 'icons'
VERSION = '0.1+pre.01'
TOOLDIR = './admin/scons'
SCRIPTDIR = './admin'
#-----------------------------------Configuration
# NOTE: scons -h for help.
# Read more about the SCons build system at: http://www.scons.org
# Basically, this script just /defines/ the components and how they
# fit together. SCons will derive the necessary build steps.
#-----------------------------------Configuration
TARGDIR = 'target'
VERSION = '0.pre.01'
TOOLDIR = './admin/scons' # SCons plugins
SCRIPTDIR = './admin'
OPTCACHE = 'optcache'
CUSTOPTFILE = 'custom-options'
# these are accessible via env.path.xxxx
srcIcon = 'icons'
srcConf = 'data/config'
buildExe = '#$TARGDIR'
buildLib = '#$TARGDIR/modules'
buildPlug = '#$TARGDIR/modules'
buildIcon = '#$TARGDIR/gui/icons'
buildUIRes = '#$TARGDIR/'
buildConf = '#$TARGDIR/config'
installExe = '#$DESTDIR/lib/lumiera'
installLib = '#$DESTDIR/lib/lumiera/modules'
installPlug = '#$DESTDIR/lib/lumiera/modules'
installIcon = '#$DESTDIR/share/lumiera/icons'
installUIRes = '#$DESTDIR/share/lumiera/'
installConf = '#$DESTDIR/lib/lumiera/config'
localDefinitions = locals()
#-----------------------------------Configuration
import os
import sys
@ -55,10 +69,10 @@ from LumieraEnvironment import *
#####################################################################
def setupBasicEnvironment():
def setupBasicEnvironment(localDefinitions):
""" define cmdline options, build type decisions
"""
EnsurePythonVersion(2,3)
EnsurePythonVersion(2,4)
EnsureSConsVersion(1,0)
Decider('MD5-timestamp') # detect changed files by timestamp, then do a MD5
@ -66,26 +80,20 @@ def setupBasicEnvironment():
vars = defineCmdlineVariables()
env = LumieraEnvironment(variables=vars
,toolpath = [TOOLDIR]
,tools = ["default", "BuilderGCH", "BuilderDoxygen"]
)
env.Tool("ToolDistCC")
env.Tool("ToolCCache")
,pathConfig = extract_localPathDefs(localDefinitions) # e.g. buildExe -> env.path.buildExe
,TARGDIR = TARGDIR
,DESTDIR = '$INSTALLDIR/$PREFIX'
,VERSION = VERSION
)
handleVerboseMessages(env)
env.Append ( CCCOM=' -std=gnu99')
env.Append ( SHCCCOM=' -std=gnu99') # workaround for a bug: CCCOM currently doesn't honour CFLAGS, only CCFLAGS
env.Replace( VERSION=VERSION
, SRCDIR=SRCDIR
, BINDIR=BINDIR
, LIBDIR=LIBDIR
, PLUGDIR=PLUGDIR
, ICONDIR=ICONDIR
, CPPPATH=["#"+SRCDIR] # used to find includes, "#" means always absolute to build-root
, CPPDEFINES=['-DLUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines
env.Replace( CPPPATH =["#src"] # used to find includes, "#" means always absolute to build-root
, CPPDEFINES=['LUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines
, CCFLAGS='-Wall -Wextra '
, CFLAGS='-std=gnu99'
)
RegisterIcon_Builder(env)
handleNoBugSwitches(env)
env.Append(CPPDEFINES = '_GNU_SOURCE')
@ -96,13 +104,13 @@ def setupBasicEnvironment():
appendVal(env,'DEBUG', 'CCFLAGS', val=' -ggdb')
# setup search path for Lumiera plugins
appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR/:./.libs\\"'
,'LUMIERA_PLUGIN_PATH=\\"$DESTDIR/lib/lumiera/:./.libs\\"')
appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR/:ORIGIN/modules\\"'
,'LUMIERA_PLUGIN_PATH=\\"ORIGIN/modules\\"')
appendCppDefine(env,'PKGDATADIR','LUMIERA_CONFIG_PATH=\\"$PKGLIBDIR/:.\\"'
,'LUMIERA_CONFIG_PATH=\\"$DESTDIR/share/lumiera/:.\\"')
prepareOptionsHelp(vars,env)
vars.Save(OPTIONSCACHEFILE, env)
vars.Save(OPTCACHE, env)
return env
def appendCppDefine(env,var,cppVar, elseVal=''):
@ -148,7 +156,7 @@ def defineCmdlineVariables():
you may define custom variable settings in a separate file.
Commandline will override both.
"""
vars = Variables([OPTIONSCACHEFILE, CUSTOPTIONSFILE])
vars = Variables([OPTCACHE, CUSTOPTFILE])
vars.AddVariables(
('ARCHFLAGS', 'Set architecture-specific compilation flags (passed literally to gcc)','')
,('CC', 'Set the C compiler to use.', 'gcc')
@ -164,11 +172,10 @@ def defineCmdlineVariables():
# ,BoolVariable('OPENGL', 'Include support for OpenGL preview rendering', False)
# ,EnumVariable('DIST_TARGET', 'Build target architecture', 'auto',
# allowed_values=('auto', 'i386', 'i686', 'x86_64' ), ignorecase=2)
,PathVariable('DESTDIR', 'Installation dir prefix', '/usr/local')
,PathVariable('PKGLIBDIR', 'Installation dir for plugins, defaults to DESTDIR/lib/lumiera', '',PathVariable.PathAccept)
,PathVariable('PKGDATADIR', 'Installation dir for default config, usually DESTDIR/share/lumiera', '',PathVariable.PathAccept)
,PathVariable('SRCTAR', 'Create source tarball prior to compiling', '..', PathVariable.PathAccept)
,PathVariable('DOCTAR', 'Create tarball with developer documentation', '..', PathVariable.PathAccept)
,PathVariable('PREFIX', 'Installation dir prefix', 'usr/local', PathVariable.PathAccept)
,PathVariable('INSTALLDIR', 'Root output directory for install. Final installation will happen in INSTALLDIR/PREFIX/... ', '/', PathVariable.PathIsDir)
,PathVariable('PKGLIBDIR', 'Installation dir for plugins, defaults to PREFIX/lib/lumiera/modules', '',PathVariable.PathAccept)
,PathVariable('PKGDATADIR', 'Installation dir for default config, usually PREFIX/share/lumiera', '',PathVariable.PathAccept)
)
return vars
@ -187,10 +194,8 @@ Special Targets:
testcode: additionally compile the Testsuite
check : build and run the Testsuite
doc : generate documentation (Doxygen)
all : build and testcode and doc
install : install created artifacts at PREFIX
src.tar : create source tarball
doc.tar : create developer doc tarball
tar : create all tarballs
Configuration Options:
"""
@ -238,15 +243,19 @@ def configurePlatform(env):
conf.env.mergeConf('nobugmt')
if not conf.CheckCXXHeader('tr1/memory'):
problems.append('We rely on the std::tr1 proposed standard extension for shared_ptr.')
problems.append('We rely on the std::tr1 standard C++ extension for shared_ptr.')
if not conf.CheckCXXHeader('boost/config.hpp'):
problems.append('We need the C++ boost-lib.')
problems.append('We need the C++ boost-libraries.')
else:
if not conf.CheckCXXHeader('boost/shared_ptr.hpp'):
problems.append('We need boost::shared_ptr (shared_ptr.hpp).')
if not conf.CheckCXXHeader('boost/scoped_ptr.hpp'):
problems.append('We need boost::scoped_ptr (scoped_ptr.hpp).')
if not conf.CheckCXXHeader('boost/format.hpp'):
problems.append('We need boost::format (header).')
if not conf.CheckLibWithHeader('boost_program_options-mt','boost/program_options.hpp','C++'):
problems.append('We need boost::program_options (including binary lib for linking).')
if not conf.CheckLibWithHeader('boost_filesystem-mt','boost/filesystem.hpp','C++'):
problems.append('We need the boost::filesystem (including binary lib for linking).')
if not conf.CheckLibWithHeader('boost_regex-mt','boost/regex.hpp','C++'):
problems.append('We need the boost regular expression lib (incl. binary lib for linking).')
@ -263,16 +272,16 @@ def configurePlatform(env):
conf.env.mergeConf('gavl')
if not conf.CheckPkgConfig('gtkmm-2.4', 2.8):
problems.append('Unable to configure GTK--, exiting.')
problems.append('Unable to configure GTK--')
if not conf.CheckPkgConfig('glibmm-2.4', '2.16'):
problems.append('Unable to configure Lib glib--, exiting.')
problems.append('Unable to configure Lib glib--')
if not conf.CheckPkgConfig('gthread-2.0', '2.12.4'):
problems.append('Need gthread support lib for glib-- based thread handling.')
if not conf.CheckPkgConfig('cairomm-1.0', 0.6):
problems.append('Unable to configure Cairo--, exiting.')
problems.append('Unable to configure Cairo--')
verGDL = '2.27.1'
if not conf.CheckPkgConfig('gdl-lum', verGDL, alias='gdl'):
@ -308,19 +317,11 @@ def configurePlatform(env):
def definePackagingTargets(env, artifacts):
def defineSetupTargets(env, artifacts):
""" build operations and targets to be done /before/ compiling.
things like creating a source tarball or preparing a version header.
"""
t = Tarball(env,location='$SRCTAR',dirs='$SRCDIR')
artifacts['src.tar'] = t
env.Alias('src.tar', t)
env.Alias('tar', t)
t = Tarball(env,location='$DOCTAR',suffix='-doc',dirs='admin doc wiki uml tests')
artifacts['doc.tar'] = t
env.Alias('doc.tar', t)
env.Alias('tar', t)
pass ## currently none
@ -331,50 +332,51 @@ def defineBuildTargets(env, artifacts):
"""
# use PCH to speed up building // disabled for now due to strange failures
# env['GCH'] = ( env.PrecompiledHeader('$SRCDIR/pre.hpp')
# + env.PrecompiledHeader('$SRCDIR/pre_a.hpp')
# env['GCH'] = ( env.PrecompiledHeader('src/pre.hpp')
# + env.PrecompiledHeader('src/pre_a.hpp')
# )
lApp = env.SharedLibrary('$LIBDIR/lumieracommon', srcSubtree(env,'$SRCDIR/common'))
lBack = env.SharedLibrary('$LIBDIR/lumierabackend', srcSubtree(env,'$SRCDIR/backend'))
lProc = env.SharedLibrary('$LIBDIR/lumieraproc', srcSubtree(env,'$SRCDIR/proc'))
lLib = env.SharedLibrary('$LIBDIR/lumiera', srcSubtree(env,'$SRCDIR/lib'))
lLib = env.SharedLibrary('lumiera', srcSubtree(env,'src/lib'), install=True)
lApp = env.SharedLibrary('lumieracommon', srcSubtree(env,'src/common'), install=True, LIBS=lLib)
lBack = env.SharedLibrary('lumierabackend', srcSubtree(env,'src/backend'),install=True)
lProc = env.SharedLibrary('lumieraproc', srcSubtree(env,'src/proc'), install=True)
core = lLib+lApp+lBack+lProc
artifacts['lumiera'] = env.Program('$BINDIR/lumiera', ['$SRCDIR/lumiera/main.cpp'], LIBS=core)
artifacts['corelib'] = lLib+lApp
artifacts['corelib'] = core
artifacts['support'] = lLib
artifacts['lumiera'] = ( env.Program('lumiera', ['src/lumiera/main.cpp'], LIBS=core, install=True)
+ env.ConfigData(env.path.srcConf+'setup.ini', targetDir='$ORIGIN')
+ env.ConfigData(env.path.srcConf+'dummy_lumiera.ini')
)
# building Lumiera Plugins
envPlu = env.Clone()
envPlu.Append(CPPDEFINES='LUMIERA_PLUGIN')
artifacts['plugins'] = [] # currently none
# render and install Icons
vector_icon_dir = env.subst('$ICONDIR/svg')
prerendered_icon_dir = env.subst('$ICONDIR/prerendered')
artifacts['icons'] = ( [env.IconRender(f) for f in scanSubtree(vector_icon_dir, ['*.svg'])]
+ [env.IconCopy(f) for f in scanSubtree(prerendered_icon_dir, ['*.png'])]
vector_icon_dir = env.path.srcIcon+'svg'
prerendered_icon_dir = env.path.srcIcon+'prerendered'
artifacts['icons'] = ( [env.IconRender(f) for f in scanSubtree(vector_icon_dir, ['*.svg'])]
+ [env.IconResource(f) for f in scanSubtree(prerendered_icon_dir, ['*.png'])]
)
# the Lumiera GTK GUI
envGtk = env.Clone()
envGtk.mergeConf(['gtkmm-2.4','gthread-2.0','cairomm-1.0','gdl','xv','xext','sm'])
envGtk.Append(CPPDEFINES='LUMIERA_PLUGIN', LIBS=core)
envGtk.Append(LIBS=core)
objgui = srcSubtree(envGtk,'$SRCDIR/gui')
guimodule = envGtk.LoadableModule('$LIBDIR/gtk_gui', objgui, SHLIBPREFIX='', SHLIBSUFFIX='.lum')
objgui = srcSubtree(envGtk,'src/gui', appendCPP='LUMIERA_PLUGIN')
guimodule = envGtk.LumieraPlugin('gtk_gui', objgui, install=True)
artifacts['gui'] = ( guimodule
+ env.Install('$BINDIR', env.Glob('$SRCDIR/gui/*.rc'))
+ [env.GuiResource(f) for f in env.Glob('src/gui/*.rc')]
+ artifacts['icons']
)
# call subdir SConscript(s) for independent components
SConscript(dirs=[SRCDIR+'/tool'], exports='env artifacts core')
SConscript(dirs=[TESTDIR], exports='env envPlu artifacts core')
SConscript(dirs=['src/tool'], exports='env artifacts core')
SConscript(dirs=['tests'], exports='env artifacts core')
@ -382,31 +384,34 @@ def definePostBuildTargets(env, artifacts):
""" define further actions after the core build (e.g. Documentaion).
define alias targets to trigger the installing.
"""
ib = env.Alias('install-bin', '$DESTDIR/bin')
il = env.Alias('install-lib', '$DESTDIR/lib')
env.Alias('install', [ib, il])
build = env.Alias('build', artifacts['lumiera']+artifacts['gui']+artifacts['plugins']+artifacts['tools'])
allbu = env.Alias('allbuild', build+artifacts['testsuite'])
env.Default('build')
build = env.Alias('build', ( artifacts['lumiera']
+ artifacts['plugins']
+ artifacts['tools']
+ artifacts['gui']
))
# additional files to be cleaned when cleaning 'build'
env.Clean ('build', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log' ])
env.Clean ('build', [ '$SRCDIR/pre.gch' ])
env.Clean ('build', [ 'src/pre.gch' ])
doxydoc = artifacts['doxydoc'] = env.Doxygen('doc/devel/Doxyfile')
env.Alias ('doc', doxydoc)
env.Clean ('doc', doxydoc + ['doc/devel/,doxylog','doc/devel/warnings.txt'])
env.Alias ('all', build+artifacts['testsuite']+doxydoc)
env.Default('build')
# SCons default target
def defineInstallTargets(env, artifacts):
""" define some artifacts to be installed into target locations.
""" define additional artifacts to be installed into target locations.
@note: we use customised SCons builders defining install targets
for all executables automatically. see LumieraEnvironment.py
"""
env.Install(dir = '$DESTDIR/bin', source=artifacts['lumiera'])
env.Install(dir = '$DESTDIR/lib', source=artifacts['corelib'])
env.Install(dir = '$DESTDIR/lib', source=artifacts['plugins'])
env.Install(dir = '$DESTDIR/bin', source=artifacts['tools'])
env.SymLink('$DESTDIR/bin/lumiera',env.path.installExe+'lumiera','../lib/lumiera/lumiera')
# env.Install(dir = '$DESTDIR/share/doc/lumiera$VERSION/devel', source=artifacts['doxydoc'])
env.Install(dir = '$DESTDIR/share/doc/lumiera$VERSION/devel', source=artifacts['doxydoc'])
env.Alias('install', artifacts['gui'])
env.Alias('install', '$DESTDIR')
#####################################################################
@ -416,8 +421,7 @@ def defineInstallTargets(env, artifacts):
### === MAIN === ####################################################
env = setupBasicEnvironment()
env = setupBasicEnvironment(localDefinitions)
if not (isCleanupOperation(env) or isHelpRequest()):
env = configurePlatform(env)
@ -430,10 +434,8 @@ artifacts = {}
# 'gui' : the GTK UI (plugin)
# 'plugins' : plugin shared lib
# 'tools' : small tool applications (e.g mpegtoc)
# 'src,tar' : source tree as tarball (without doc)
# 'doc.tar' : uml model, wiki, dev docu (no src)
definePackagingTargets(env, artifacts)
defineSetupTargets(env, artifacts)
defineBuildTargets(env, artifacts)
definePostBuildTargets(env, artifacts)
defineInstallTargets(env, artifacts)

View file

@ -31,6 +31,31 @@ inkscapePath = "/usr/bin/inkscape"
rsvgPath = "./rsvg-convert"
artworkLayerPrefix = "artwork:"
#
# 2/2011 some notes by Ichthyo
# The purpose of this python script is
# - to parse a SVG
# - to invoke Inkscape to render this SVG into a raster image (icon)
#
# For the actual call into Incscape we rely on an executable 'rsvg-convert',
# which is built during the Lumiera build process.
#
# Judging from the code and the actual SVGs, this seems to work as follows:
# The SVG contains a design to be rendered into raster images of various sizes.
# These sizes are determined by special rectangles, which act as bounding box and
# are placed on a special 'plate' layer, which is a child layer of the main
# 'artwork:' layer. The grid of the SVG is setup such as to result in pixel sizes
# suitable for icon generation. The actual size of the generated icons are then
# parsed from the height and width attributes of the mentioned bounding box
# rectangles.
#
# The parser seems to be rather simplistic; the sizes and positions need to be
# integral numbers. In one instance we had a float number in the y coordinate,
# which resulted in an invalid, zero sized output icon
#
#
def createDirectory( name ):
try:
if os.path.isfile(name):

View file

@ -217,8 +217,8 @@ def generate(env):
'Doxygen': doxyfile_builder,
})
env.AppendUnique(
DOXYGEN = 'doxygen',
env.Replace(
DOXYGEN = 'doxygen'
)

View file

@ -28,6 +28,7 @@ import fnmatch
import re
import tarfile
from SCons import Util
from SCons.Action import Action
@ -48,11 +49,12 @@ def isHelpRequest():
def srcSubtree(env,tree,isShared=True,builder=None, **args):
def srcSubtree(env,tree,isShared=True,builder=None,appendCPP=None, **args):
""" convenience wrapper: scans the given subtree, which is
relative to the current SConscript, find all source files and
declare them as Static or SharedObjects for compilation
"""
if appendCPP: env.Append(CPPDEFINES=appendCPP)
root = env.subst(tree) # expand Construction Vars
if not builder:
if isShared:
@ -98,7 +100,7 @@ def findSrcTrees(location, patterns=SRCPATTERNS):
After having initially expanded the given location with #globRootdirs, each
directory is examined depth first, until encountering a directory containing
source files, which then yields a result. Especially, this can be used to traverse
an organisational directory structure and find out all possible source trees of
an organisational directory structure and find out all possible source trees
to be built into packages, plugins, individual tool executables etc.
@return: the relative path names of all source root dirs found (generator function).
"""
@ -137,24 +139,31 @@ def filterNodes(nlist, removeName=None):
def getDirname(dir):
""" extract directory name without leading path """
def getDirname(dir, basePrefix=None):
""" extract directory name without leading path,
or without the explicitly given basePrefix
"""
dir = os.path.realpath(dir)
if not os.path.isdir(dir):
dir,_ = os.path.split(dir)
_, name = os.path.split(dir)
if basePrefix:
basePrefix = os.path.realpath(basePrefix)
if str(dir).startswith(basePrefix):
name = str(dir)[len(basePrefix):]
else:
_, name = os.path.split(dir)
return name
def createPlugins(env, dir):
def createPlugins(env, dir, **kw):
""" investigate the given source directory to identify all contained source trees.
@return: a list of build nodes defining a plugin for each of these source trees.
"""
return [env.LoadableModule( '#$PLUGDIR/%s' % getDirname(tree)
, srcSubtree(env, tree)
, SHLIBPREFIX='', SHLIBSUFFIX='.lum'
)
return [env.LumieraPlugin( getDirname(tree)
, srcSubtree(env, tree, appendCPP='LUMIERA_PLUGIN')
, **kw
)
for tree in findSrcTrees(dir)
]
@ -196,114 +205,39 @@ def checkCommandOption(env, optID, val=None, cmdName=None):
def RegisterIcon_Builder(env):
""" Registers Custom Builders for generating and installing Icons.
Additionally you need to build the tool (rsvg-convert.c)
used to generate png from the svg source using librsvg.
class Record(dict):
""" a set of properties with record style access.
Record is a dictionary, but the elements can be accessed
conveniently as if they where object fields
"""
import render_icon as renderer # load Joel's python script for invoking the rsvg-convert (SVG render)
renderer.rsvgPath = env.subst("$BINDIR/rsvg-convert")
def invokeRenderer(target, source, env):
source = str(source[0])
targetdir = env.subst("$BINDIR")
renderer.main([source,targetdir])
return 0
def __init__(self, defaults=None, **props):
if defaults:
defaults.update(props)
props = defaults
dict.__init__(self,props)
def createIconTargets(target,source,env):
""" parse the SVG to get the target file names """
source = str(source[0])
targetdir = os.path.basename(str(target[0]))
targetfiles = renderer.getTargetNames(source) # parse SVG
return (["$BINDIR/%s" % name for name in targetfiles], source)
def __getattr__(self,key):
if key=='__get__' or key=='__set__':
raise AttributeError
return self.setdefault(key)
def IconCopy(env, source):
"""Copy icon to corresponding icon dir. """
subdir = getDirname(source)
return env.Install("$BINDIR/%s" % subdir, source)
buildIcon = env.Builder( action = Action(invokeRenderer, "rendering Icon: $SOURCE --> $TARGETS")
, single_source = True
, emitter = createIconTargets
)
env.Append(BUILDERS = {'IconRender' : buildIcon})
env.AddMethod(IconCopy)
def __setattr__(self,key,val):
self[key] = val
def Tarball(env,location,dirs,suffix=''):
""" Custom Command: create Tarball of some subdirs
location: where to create the tar (may optionally include filename.tar.gz)
suffix: (optional) suffix to include in the tar name
dirs: directories to include in the tar
This is a bit of a hack, because we want to be able to include arbitrary directories,
without creating new dependencies on those dirs. Esp. we want to tar the source tree
prior to compiling. Solution is
- use the Command-Builder, but pass all target specifications as custom build vars
- create a pseudo-target located in the parent directory (not built by default)
def extract_localPathDefs (localDefs):
""" extracts the directory configuration values.
For sake of simplicity, paths and directories are defined
immediately as global variables in the SConstruct. This helper
extracts from the given dict the variables matching some magical
pattern and returns them wrapped into a Record for convenient access
"""
targetID = '../extern-tar%s' % suffix
versionID = env['VERSION']
defaultName = 'lumiera%s_%s' % (suffix, versionID)
nameprefix = 'lumiera-%s/' % (versionID)
location = env.subst(location)
dirs = env.subst(dirs)
return env.Command(targetID,None, createTarball,
location=location, defaultName=defaultName, dirs=dirs, nameprefix=nameprefix)
def createTarball(target,source,env):
""" helper, builds the tar using the python2.3 tarfile lib.
This allows us to prefix all paths, thus moving the tree
into a virtual subdirectory containing the Version number,
as needed by common packaging systems.
"""
name = getTarName( location = env['location']
, defaultName = env['defaultName'])
targetspec = env['dirs']
nameprefix = env['nameprefix'] or ''
print 'Running: tar -czf %s %s ...' % (name,targetspec)
if os.path.isfile(name):
os.remove(name)
tar = tarfile.open(name,'w:gz')
for name in targetspec.split():
tar.add(name,nameprefix+name)
tar.close()
#
# old version using shell command:
#
# cmd = 'tar -czf %s %s' % (name,targetspec)
# print 'running ', cmd, ' ... '
# pipe = os.popen (cmd)
# return pipe.close ()
def getTarName(location, defaultName):
""" create a suitable name for the tarball.
- if location contains a name (*.tar.gz) then use this
- otherwise append the defaultName to the specified dir
"""
spec = os.path.abspath(location)
(head,tail) = os.path.split(spec)
if not os.path.isdir(head):
print 'Target dir "%s" for Tar doesn\'t exist.' % head
Exit(1)
mat = re.match(r'([\w\.\-\+:\~]+)\.((tar)|(tar\.gz)|(tgz))', tail)
if mat:
name = mat.group(1)
ext = '.'+mat.group(2)
else:
ext = '.tar.gz'
if os.path.isdir(spec):
head = spec
name = defaultName
else:
name = tail
return os.path.join(head,name+ext)
def relevantPathDefs (mapping):
for (k,v) in mapping.items():
if (k.startswith('src') or k.startswith('build') or k.startswith('install')) and Util.is_String(v):
v = v.strip()
if not v.endswith('/'): v += '/'
yield (k,v)
return dict(relevantPathDefs(localDefs))

View file

@ -22,6 +22,9 @@
#####################################################################
import os
from os import path
import SCons
import SCons.SConf
from SCons.Environment import Environment
@ -35,9 +38,16 @@ class LumieraEnvironment(Environment):
This allows us to carry structured config data without
using global vars. Idea inspired by Ardour.
"""
def __init__(self,*args,**kw):
Environment.__init__ (self,*args,**kw)
def __init__(self, pathConfig, **kw):
Environment.__init__ (self,**kw)
self.path = Record (pathConfig)
self.libInfo = {}
self.Tool("BuilderGCH")
self.Tool("BuilderDoxygen")
self.Tool("ToolDistCC")
self.Tool("ToolCCache")
register_LumieraResourceBuilder(self)
register_LumieraCustomBuilders(self)
def Configure (self, *args, **kw):
kw['env'] = self
@ -73,7 +83,7 @@ class LumieraEnvironment(Environment):
print "Problems configuring the Library %s (>= %s)" % (libID,minVersion)
return False
self.libInfo[libID] = libInfo = LumieraEnvironment()
self.libInfo[libID] = libInfo = Environment()
libInfo["ENV"]["PKG_CONFIG_PATH"] = os.environ.get("PKG_CONFIG_PATH")
libInfo.ParseConfig ('pkg-config --cflags --libs '+ libID )
if alias:
@ -102,3 +112,259 @@ class LumieraConfigContext(ConfigBase):
return self.env.addLibInfo (libID, minVersion, alias)
###############################################################################
####### Lumiera custom tools and builders #####################################
def register_LumieraResourceBuilder(env):
""" Registers Custom Builders for generating and installing Icons.
Additionally you need to build the tool (rsvg-convert.c)
used to generate png from the svg source using librsvg.
"""
import render_icon as renderer # load Joel's python script for invoking the rsvg-convert (SVG render)
renderer.rsvgPath = env.subst("$TARGDIR/rsvg-convert")
def invokeRenderer(target, source, env):
source = str(source[0])
targetdir = env.subst(env.path.buildIcon)
if targetdir.startswith('#'): targetdir = targetdir[1:]
renderer.main([source,targetdir])
return 0
def createIconTargets(target,source,env):
""" parse the SVG to get the target file names """
source = str(source[0])
targetdir = env.path.buildIcon
targetfiles = renderer.getTargetNames(source) # parse SVG
# additionally create an installation task for each Icon to be generated
installLocation = env.path.installIcon
generateTargets = []
for icon in targetfiles:
icon = targetdir+icon
subdir = getDirname(str(icon))
env.Install (installLocation+subdir, icon)
generateTargets.append(icon)
return (generateTargets, source)
def IconResource(env, source):
"""Copy icon pixmap to corresponding icon dir. """
subdir = getDirname(str(source))
toBuild = env.path.buildIcon+subdir
toInstall = env.path.installIcon+subdir
env.Install (toInstall, source)
return env.Install(toBuild, source)
def GuiResource(env, source):
subdir = getDirname(str(source))
toBuild = env.path.buildUIRes+subdir
toInstall = env.path.installUIRes+subdir
env.Install (toInstall, source)
return env.Install(toBuild, source)
def ConfigData(env, source, targetDir=None):
""" install (copy) configuration- and metadata.
target dir is either the install location configured (in SConstruct),
or an explicitly given absolute or relative path segment, which might refer
to the location of the executable through the $ORIGIN token
"""
subdir = getDirname(str(source), env.path.srcConf) # removes source location path prefix
if targetDir:
if path.isabs(targetDir):
toBuild = toInstall = path.join(targetDir,subdir)
else:
if targetDir.startswith('$ORIGIN'):
targetDir = targetDir[len('$ORIGIN'):]
toBuild = path.join(env.path.buildExe, targetDir, subdir)
toInstall = path.join(env.path.installExe, targetDir, subdir)
else:
toBuild = path.join(env.path.buildConf, targetDir, subdir)
toInstall = path.join(env.path.installConf, targetDir, subdir)
else:
toBuild = path.join(env.path.buildConf,subdir)
toInstall = path.join(env.path.installConf,subdir)
env.Install (toInstall, source)
return env.Install(toBuild, source)
buildIcon = env.Builder( action = Action(invokeRenderer, "rendering Icon: $SOURCE --> $TARGETS")
, single_source = True
, emitter = createIconTargets
)
env.Append(BUILDERS = {'IconRender' : buildIcon})
env.AddMethod(IconResource)
env.AddMethod(GuiResource)
env.AddMethod(ConfigData)
class WrappedStandardExeBuilder(SCons.Util.Proxy):
""" Helper to add customisations and default configurations to SCons standard builders.
The original builder object is wrapped and most calls are simply forwarded to this
wrapped object by Python magic. But some calls are intecepted in order to inject
suitalbe default configuration based on the project setup.
"""
def __init__(self, originalBuilder):
SCons.Util.Proxy.__init__ (self, originalBuilder)
def __nonzero__(self): return True
def __call__(self, env, target=None, source=None, **kw):
""" when the builder gets invoked from the SConscript...
create a clone environment for specific configuration
and then pass on the call to the wrapped original builder.
Automatically define installation targets for build results.
@note only returning the build targets, not the install targets
"""
customisedEnv = self.getCustomEnvironment(env, target=target, **kw) # defined in subclasses
buildTarget = self.buildLocation(customisedEnv, target)
buildTarget = self.invokeOriginalBuilder(customisedEnv, buildTarget, source, **kw)
self.installTarget(customisedEnv, buildTarget, **kw)
return buildTarget
def invokeOriginalBuilder(self, env, target, source, **kw):
return self.get().__call__ (env, target, source, **kw)
def buildLocation(self, env, target):
""" prefix project output directory """
prefix = self.getBuildDestination(env)
return list(prefix+str(name) for name in target)
def installTarget(self, env, buildTarget, **kw):
""" create an additional installation target
for the generated executable artifact
"""
indeedInstall = lambda p: p and p.get('install')
if indeedInstall(kw):
return env.Install (dir = self.getInstallDestination(env), source=buildTarget)
else:
return []
class LumieraExeBuilder(WrappedStandardExeBuilder):
def getCustomEnvironment(self, lumiEnv, **kw):
""" augments the built-in Program() builder to add a fixed rpath based on $ORIGIN
That is: after searching LD_LIBRARY_PATH, but before the standard linker search,
the directory relative to the position of the executable ($ORIGIN) is searched.
This search path is active not only for the executable, but for all libraries
it is linked with.
@note: enabling the new ELF dynamic tags. This causes a DT_RUNPATH to be set,
which results in LD_LIBRARY_PATH being searched *before* the RPATH
"""
custEnv = lumiEnv.Clone()
custEnv.Append( LINKFLAGS = "-Wl,-rpath=\\$$ORIGIN/modules,--enable-new-dtags" )
return custEnv
def getBuildDestination(self, lumiEnv): return lumiEnv.path.buildExe
def getInstallDestination(self, lumiEnv): return lumiEnv.path.installExe
class LumieraModuleBuilder(WrappedStandardExeBuilder):
def getCustomEnvironment(self, lumiEnv, target, **kw):
""" augments the built-in SharedLibrary() builder to add some tweaks missing in SCons 1.0,
like setting a SONAME proper instead of just passing the relative pathname to the linker
"""
custEnv = lumiEnv.Clone()
custEnv.Append(LINKFLAGS = "-Wl,-soname="+self.defineSoname(target,**kw))
return custEnv
def getBuildDestination(self, lumiEnv): return lumiEnv.path.buildLib
def getInstallDestination(self, lumiEnv): return lumiEnv.path.installLib
def defineSoname (self, target, **kw):
""" internal helper to extract or guess
a suitable library SONAME, either using an
explicit spec, falling back on the lib filename
"""
if 'soname' in kw:
soname = self.subst(kw['soname']) # explicitely defined by user
else: # else: use the library filename as DT_SONAME
if SCons.Util.is_String(target):
pathname = target.strip()
elif 1 == len(target):
pathname = str(target[0]).strip()
else:
raise SyntaxError("Lumiera Library builder requires exactly one target spec. Found target="+str(target))
assert pathname
(dirprefix, libname) = path.split(pathname)
if not libname:
raise ValueError("Library name missing. Only got a directory: "+pathname)
soname = "${SHLIBPREFIX}%s$SHLIBSUFFIX" % libname
assert soname
return soname
class LumieraPluginBuilder(LumieraModuleBuilder):
def getCustomEnvironment(self, lumiEnv, target, **kw):
""" in addition to the ModuleBuilder, define the Lumiera plugin suffix
"""
custEnv = LumieraModuleBuilder.getCustomEnvironment(self, lumiEnv, target, **kw)
custEnv.Append (CPPDEFINES='LUMIERA_PLUGIN')
custEnv.Replace(SHLIBPREFIX='', SHLIBSUFFIX='.lum')
return custEnv
def getBuildDestination(self, lumiEnv): return lumiEnv.path.buildPlug
def getInstallDestination(self, lumiEnv): return lumiEnv.path.installPlug
def register_LumieraCustomBuilders (lumiEnv):
""" install the customised builder versions tightly integrated with our buildsystem.
Especially, these builders automatically add the build and installation locations
and set the RPATH and SONAME in a way to allow a relocatable Lumiera directory structure
"""
programBuilder = LumieraExeBuilder (lumiEnv['BUILDERS']['Program'])
libraryBuilder = LumieraModuleBuilder (lumiEnv['BUILDERS']['SharedLibrary'])
smoduleBuilder = LumieraModuleBuilder (lumiEnv['BUILDERS']['LoadableModule'])
lpluginBuilder = LumieraPluginBuilder (lumiEnv['BUILDERS']['LoadableModule'])
lumiEnv['BUILDERS']['Program'] = programBuilder
lumiEnv['BUILDERS']['SharedLibrary'] = libraryBuilder
lumiEnv['BUILDERS']['LoadableModule'] = smoduleBuilder
lumiEnv['BUILDERS']['LumieraPlugin'] = lpluginBuilder
def SymLink(env, target, source, linktext=None):
""" use python to create a symlink
"""
def makeLink(target,source,env):
if linktext:
dest = linktext
else:
dest = str(source[0])
link = str(target[0])
os.symlink(dest, link)
if linktext: srcSpec=linktext
else: srcSpec='$SOURCE'
action = Action(makeLink, "Install link: $TARGET -> "+srcSpec)
env.Command (target,source, action)
# adding SymLink direclty as method on the environment object
# Probably that should better be a real builder, but I couldn't figure out
# how to get the linktext through literally, which is necessary for relative links.
# Judging from the sourcecode of SCons.Builder.BuilderBase, there seems to be no way
# to set the executor_kw, which are passed through to the action object.
lumiEnv.AddMethod(SymLink)

View file

@ -12,6 +12,7 @@
#
LOGFILE=,valgrind.log
SUPPRESS=vgsuppression
MODULEDIR=modules
VALGRINDFLAGS=${VALGRINDFLAGS:---leak-check=yes --show-reachable=yes --demangle=yes}
EXECUTABLE=$1
@ -24,6 +25,9 @@ fi
PATHPREFIX=${EXECUTABLE%/*}
SUPPRESS="$PATHPREFIX/$SUPPRESS"
# need to set a library search path, because valgrind doesn't handle DT_RUNPATH and $ORIGIN properly
export LD_LIBRARY_PATH=$PATHPREFIX/$MODULEDIR:$LD_LIBRARY_PATH
if [[ -x $SUPPRESS ]]; then
if [[ $SUPPRESS -nt $SUPPRESS.supp ]]; then
echo 'generating valgrind supression file...'
@ -37,6 +41,7 @@ else
echo 'no suppression.'
fi
echo "running......$@"
valgrind $VALGRINDFLAGS --log-file=$LOGFILE.%p $SUPPRESSIONFLAG $@ &

View file

@ -1 +0,0 @@
../.libs

View file

@ -1 +0,0 @@
Lumiera executable(s) and libraries will be built here

1
data/DIR_INFO Normal file
View file

@ -0,0 +1 @@
Additional configuration, icons, graphics etc. to be installed with Lumiera

1
data/config/DIR_INFO Normal file
View file

@ -0,0 +1 @@
Lumiera configuration files

View file

@ -0,0 +1,4 @@
# This is an dummy Lumiera config file
#
# Actually Lumiera can't yet load any extended config, as of 1/2011
#

22
data/config/setup.ini Normal file
View file

@ -0,0 +1,22 @@
###########################################################
# ### Lumiera installation and platform configuration ###
#
# (file located relative to the Lumiera executable)
#
[Lumiera]
# Setup of the Lumiera video editor main application.
# $ORIGIN denotes the directory of the executable.
#
gui = gtk_gui.lum
modulepath = $ORIGIN/modules
configpath = $ORIGIN/../../share/lumiera/config:$ORIGIN/config:~/.lumiera # unused currently (2/2011)
title = Lumiera
version = 0.pre.01
website = http://www.lumiera.org
authors = Joel Holdsworth|Christian Thäter|Hermann Voßeler|[Other Authors Here]
[Gui]
stylesheet = lumiera_ui.rc
iconpath = $ORIGIN/../../share/lumiera/icons:$ORIGIN/gui/icons:~/.lumiera/icons
resourcepath = $ORIGIN/../../share/lumiera/gui:$ORIGIN/gui

View file

@ -126,7 +126,7 @@ Joel Conclusions:
Timeline like this:
image::http://www.kenstone2.net/fcp_homepage/images_fcp_5_new_martin/07_fc_studio_new_martin.jpg[]
image::http://www.kenstone6.net/fcp_homepage/images_fcp_5_new_martin/07_fc_studio_new_martin.jpg[]
Tracks
''''''''''

View file

@ -7,10 +7,10 @@ for the core of a Non-Linear Editing software. One of the key aspect of Lumiera
is the strong separation between the user interface and the processing core.
Lumiera as a software will come along with a GTK GUI but that does not make this
exclusive, any other GUI could be written as well as scripts to drive the core.
This is made possible by the above-mentioned quality of Lumiera being considered
as two strictly separate parts. Lumiera as a processing core will be able to do
anything possibly conceivable, therefore it may be used to do any task on video
(and audio?), even unrelated to video editing.
This is made possible by the above-mentioned quality of Lumiera being built against
clearly defined interfaces, strictly separating model and presentation. Lumiera
as a processing core will be able to do anything possibly conceivable, therefore it
may be used to do any task on video (and audio?), even unrelated to video editing.
.Workflow
****
@ -30,9 +30,9 @@ link:gui/index.html[Graphical User Interface]
User interfaces are basically handled like plugins, consequently it is possible
to interface with Lumiera through scripts. It is also possible to create
specialized GUIs. The interface is the closest component to the user, it is
specialised GUIs. The interface is the closest component to the user, it is
purely visual. There the user manipulates, organizes, loads, configures all
sorts of datas, especially MObjects (media objects) and Assets. These elements
sorts of data, especially MObjects (media objects) and Assets. These elements
are contained within a structure called the Session.
The Processing Layer

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -158,7 +158,7 @@
width="16"
height="16"
x="124"
y="76.009514" />
y="76" />
<rect
y="60"
x="60"

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -2,7 +2,7 @@
THREADWRAPPER.hpp - thin convenience wrapper for starting lumiera threads
Copyright (C) Lumiera.org
2008 - 2010 Hermann Vosseler <Ichthyostega@web.de>
2008, 2010 Hermann Vosseler <Ichthyostega@web.de>
Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or

View file

@ -34,10 +34,13 @@ extern "C" {
#include "common/plugin.h"
}
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include "include/configfacade.hpp" //////////TODO: temp hack to force configfacade.o to be linked in
using util::cStr;
using lib::Literal;
@ -75,7 +78,8 @@ namespace lumiera {
* client codes POV it just behaves like intended).
*/
AppState::AppState()
: subsystems_(0)
: setup_(LUMIERA_LOCATION_OF_BOOTSTRAP_INI)
, subsystems_(0)
, emergency_(false)
, core_up_ (false)
{ }
@ -93,6 +97,13 @@ namespace lumiera {
string
AppState::fetchSetupValue (Literal key)
{
return setup_.get(key).as<string>();
}
@ -100,8 +111,8 @@ namespace lumiera {
#define _THROW_IF \
if (lumiera_error_peek()) \
throw error::Fatal (lumiera_error());
maybeThrow<error::Fatal> ("internal failure while initialising the "\
"Lumiera application framework");
@ -186,8 +197,6 @@ namespace lumiera {
AppState::abort (lumiera::Error& problem)
{
INFO (common, "Address of Config Facade = %p", &lumiera::Config::instance()); //////////TODO: a temp hack to force configfacade.cpp to be linked into lumiera exe.
ERROR (common, "Aborting Lumiera after unhandled error: %s", cStr(problem.what()));
log_and_clear_unexpected_errorstate();

View file

@ -21,7 +21,7 @@
*/
/** @file appstate.hpp
** Registering and managing some application-global services.
** Registering and managing primary application-global services.
** This can be considered the "main" object of the Lumiera application
** Besides encapsulating the logic for starting up the fundamental parts
** of the application, there is a mechanism for registering \em subsystems
@ -30,6 +30,7 @@
** callbacks) and provides the top-level catch-all error handling.
**
** @see LifecycleHook
** @see BasicSetup
** @see Subsys
** @see main.cpp
** @see logging.h
@ -42,6 +43,7 @@
#include "lib/symbol.hpp"
#include "common/option.hpp"
#include "common/subsys.hpp"
#include "common/basic-setup.hpp"
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
@ -60,6 +62,7 @@ namespace lumiera {
/**
* The Lumiera Application state and basic initialisation.
* Singleton to hold global flags directing the overall application behaviour,
* for triggering lifecycle events and performing early initialisation tasks.
* AppState services are available already from static initialisation code.
@ -87,6 +90,10 @@ namespace lumiera {
void init (lumiera::Option& options);
/** access basic application setup values (from \c setup.ini) */
string fetchSetupValue (lib::Literal key);
/** building on the state determined by #evaluate, decide if the given Subsys
* needs to be pulled up and, if necessary, register the Subsys and its
* prerequisites to be maintained throughout the application's lifetime. */
@ -123,6 +130,8 @@ namespace lumiera {
private:
typedef scoped_ptr<SubsystemRunner> PSub;
BasicSetup setup_;
PSub subsystems_;
bool emergency_;

114
src/common/basic-setup.cpp Normal file
View file

@ -0,0 +1,114 @@
/*
BasicSetup - elementary self-configuration of the application
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "common/basic-setup.hpp"
#include "lib/searchpath.hpp"
#include "lib/error.hpp"
#include "lib/util.hpp"
extern "C" {
#include <unistd.h>
}
#include <boost/filesystem.hpp>
#include <iostream>
#include <fstream>
namespace lumiera {
using std::string;
using std::ifstream;
namespace fsys = boost::filesystem;
namespace opt = boost::program_options;
namespace { // details of the bootstrap process...
// Helper to locate a module using a search path spec
using lib::resolveModulePath;
/** use the general mechanism for resolving a search path
* to get the absolute path of the \c setup.ini */
string
resolve (fsys::path iniSpec)
{
string file = iniSpec.leaf();
string searchpath = iniSpec.branch_path().string();
return resolveModulePath (file, searchpath);
}
}//(End) implementation details
/**
* Creating the BasicSetup object performs the
* initial self-configuration of the Lumiera Application.
* For this, the \c setup.ini file is located relative to the
* current application executable, read in and parsed into a
* map of setup variables.
*/
BasicSetup::BasicSetup (string bootstrapIni)
: syntax("Lumiera installation and platform configuration")
, settings()
{
syntax.add_options()
("Lumiera.gui", opt::value<string>(),
"name of the Lumiera GUI plugin to load")
("Lumiera.modulepath", opt::value<string>(),
"search path for loadable modules. "
"May us $ORIGIN to refer to the EXE location")
("Lumiera.configpath", opt::value<string>(),
"search path for extended configuration. "
"Extended Config system not yet implemented "
"Ignored as of 2/2011")
("Lumiera.title", opt::value<string>(),
"title of the Lumiera Application, e.g. for windows")
("Lumiera.version", opt::value<string>(),
"Application version string")
("Lumiera.website", opt::value<string>(),
"URL of the Lumiera website")
("Lumiera.authors", opt::value<string>(),
"names of Lumiera authors, for 'about' dialog. Separated by '|'")
("Gui.stylesheet", opt::value<string>(),
"name of the GTK stylesheet to use. Will be searched in resource path")
("Gui.iconpath", opt::value<string>(),
"search path for icons")
("Gui.resourcepath", opt::value<string>(),
"general search path for UI resources")
;
ifstream configIn (resolve(bootstrapIni).c_str());
opt::parsed_options parsed = opt::parse_config_file (configIn, syntax);
opt::store (parsed, settings);
opt::notify(settings);
}
} // namespace lumiera

103
src/common/basic-setup.hpp Normal file
View file

@ -0,0 +1,103 @@
/*
BASIC-SETUP.hpp - elementary self-configuration of the application
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef COMMON_BASIC_SETUP_H
#define COMMON_BASIC_SETUP_H
#include "lib/error.hpp"
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include <boost/program_options.hpp>
#include <boost/noncopyable.hpp>
#include <string>
/** "bootstrapIni" : the basic setup configuration to load */
#define LUMIERA_LOCATION_OF_BOOTSTRAP_INI "$ORIGIN/setup.ini"
namespace lumiera {
using std::string;
namespace opt = boost::program_options;
/**
* Represents the elementary self-configuration
* of a running Lumiera application instance.
* This basic setup is tied to the location of the
* Lumiera executable; from there the initial configuration
* locates a \c setup.ini to read in the fundamental settings.
* This is even prerequisite for loading any extension modules
* or reading in extended application configuration; usually
* this bootstrap process happens at or before the start of
* the \c main() function. Any failure leads to immediate
* termination of the application.
*
* \par WIP 2011 -- preliminary configuration solution
* The full-blown Configuration subsystem is just drafted
* and way from being usable. Thus we'll use this basic
* configuration as a replacement for the time being.
*
* @see configfacade.hpp
* @see AppState
*/
class BasicSetup
: boost::noncopyable
{
opt::options_description syntax;
opt::variables_map settings;
public:
BasicSetup (string bootstrapIni);
string
operator[] (lib::Literal key) const
{
return get (key).as<string>();
}
opt::variable_value const&
get (lib::Literal key) const
{
string keyID (key);
__ensure_hasKey(keyID);
return settings[keyID];
}
private:
void
__ensure_hasKey (string const& key) const
{
if (!util::contains (settings, key))
throw error::Logic ("Key \""+key+"\" not found in setup.ini");
}
};
} // namespace lumiera
#endif

View file

@ -94,11 +94,8 @@ typedef lumiera_config* LumieraConfig;
LUMIERA_CONFIG_TYPE(bool, int)
// * does only initialize the variables, so that they get valid values, but does not allocate them as they will be allocated before as they are singleton.
// * lumiera_config_init (const char* searchpath) searchpath is a builtin-default, can be changed via configure and can be appended and overridden by using a flag, e.g. {{{ --config-path-append="" }}} or {{{ --config-path="" }}}
/**
* Initialize the configuration subsystem.
* Initialise the configuration subsystem.
* @param path search path for config files.
* Must be called only once
*/
@ -106,7 +103,6 @@ int
lumiera_config_init (const char* path);
// * frees all space allocated by the ConfigLoader.
/**
* Destroys the configuration subsystem.

View file

@ -59,7 +59,7 @@ lumiera_configentry_destroy (LumieraConfigitem self)
struct lumiera_configitem_vtable lumiera_configentry_funcs =
{
.new = lumiera_configentry_new,
.newitem = lumiera_configentry_new,
.destroy = lumiera_configentry_destroy
};

View file

@ -23,31 +23,39 @@
#include "include/logging.h"
#include "include/lifecycle.h"
#include "include/configfacade.hpp"
extern "C" { // TODO: can't include "lumiera/config.h" from C++ code, because it uses an identifier "new"
/** Initialise the configuration subsystem.
* Must be called exactly once prior to any use
* @param path search path for config files.
*/
int lumiera_config_init (const char* path);
/** Destroys the configuration subsystem.
* Subsequent calls are no-op. */
void
lumiera_config_destroy ();
#include "include/config-facade.h"
#include "common/appstate.hpp"
#include "lib/searchpath.hpp"
#include "lib/util.hpp"
extern "C" {
#include "common/config.h"
}
#ifndef LUMIERA_CONFIG_PATH
#error LUMIERA_CONFIG_PATH not defined
#endif
/** key to fetch the search path for extended configuration.
* Will corresponding value is defined in the basic setup.ini
* and will be fed to the (planned) full-blown config system
* after the basic application bootstrap was successful.
*/
#define KEY_CONFIG_PATH "Lumiera.configpath"
/** Similarly, this key is used to fetch the configured default
* plugin/module search path from the basic setup.ini
* This patch is used by the plugin-loader to discover
* lumiera plugins and extensions.
*/
#define KEY_PLUGIN_PATH "Lumiera.modulepath"
namespace lumiera {
using util::cStr;
using util::isnil;
using lib::Literal;
namespace {
@ -58,7 +66,7 @@ namespace lumiera {
Config::instance();
}
LifecycleHook trigger__ (ON_BASIC_INIT, &pull_up_ConfigSystem);
LifecycleHook trigger__ (ON_BASIC_INIT, &pull_up_ConfigSystem);
}
@ -70,28 +78,63 @@ namespace lumiera {
Config::Config ()
{
lumiera_config_init (LUMIERA_CONFIG_PATH);
string extendedConfigSearchPath = AppState::instance().fetchSetupValue (KEY_CONFIG_PATH);
lumiera_config_init (cStr(extendedConfigSearchPath));
INFO (config, "Config system ready.");
TODO ("wire Config facade to config interface");
}
Config::~Config()
{
lumiera_config_destroy();
TRACE (common, "config system closed.");
TRACE (config, "config system closed.");
}
const string
Config::get (string const& key)
/** @note because the full-blown Config system isn't implemented yet
* we retrieve the contents of setup.ini as a preliminary solution
*/
string
Config::get (lib::Literal key)
{
UNIMPLEMENTED ("config facade access to config value");
return string("warwohlnix");
string value = AppState::instance().fetchSetupValue (key);
if (isnil (value))
throw error::Config ("Configuration value for key=\""+key+"\" is missing");
return value;
}
} // namespace lumiera
extern "C" { /* ==== implementation C interface for accessing setup.ini ======= */
using std::string;
using lumiera::Config;
using lib::SearchPathSplitter;
using util::isnil;
using util::cStr;
const char*
lumiera_get_plugin_path_default ()
{
static string pathSpec;
if (isnil (pathSpec))
{
pathSpec += "plugin.path="; // syntax expected by lumiera_config_setdefault
// fetch plugin search path from setup.ini and expand any $ORIGIN token
SearchPathSplitter pathElement(Config::get (KEY_PLUGIN_PATH));
while (pathElement)
pathSpec += pathElement.next() +":";
}
return cStr(pathSpec);
}
}

View file

@ -109,8 +109,8 @@ lumiera_configitem_new (const char* line)
lumiera_configitem_parse (&tmp, line);
LumieraConfigitem self = tmp.vtable && tmp.vtable->new
? tmp.vtable->new (&tmp)
LumieraConfigitem self = tmp.vtable && tmp.vtable->newitem
? tmp.vtable->newitem (&tmp)
: lumiera_configitem_move (lumiera_malloc (sizeof (*self)), &tmp);
return self;

View file

@ -90,7 +90,7 @@ struct lumiera_configitem_vtable;
struct lumiera_configitem_vtable
{
LumieraConfigitem (*new)(LumieraConfigitem);
LumieraConfigitem (*newitem)(LumieraConfigitem);
LumieraConfigitem (*destroy)(LumieraConfigitem);
};

View file

@ -33,7 +33,7 @@ typedef boost::program_options::variables_map VarMap;
namespace op = boost::program_options;
using util::VectS;
using lib::VectS;
using util::cStr;
@ -50,7 +50,7 @@ namespace lumiera {
* \endcode
* @todo describe the actual options
*/
Option::Option (util::Cmdline& cmdline)
Option::Option (lib::Cmdline& cmdline)
: syntax("Lumiera, the non linear video editor. Supported parameters"),
parameters()
{

View file

@ -37,13 +37,13 @@ namespace lumiera {
using std::string;
using std::ostream;
using util::VectS;
using lib::VectS;
/**
* Support for selecting and configuring testcases
* via commandline arguments. A preconfigured wrapper
* Frontend for handling the Lumiera application
* commandline arguments. A preconfigured wrapper
* around boost::program_options, with the ability
* to tolerate unknown options. The commandline
* to be parsed is taken wrapped into a Cmdline
@ -51,10 +51,11 @@ namespace lumiera {
* vector will contain only the remaining
* unrecognised parts.
*/
class Option : private boost::noncopyable
class Option
: boost::noncopyable
{
public:
Option (util::Cmdline& cmdline);
Option (lib::Cmdline& cmdline);
const string getSessName();
const VectS getScripts();

View file

@ -19,6 +19,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file plugin.c
** Plugin loader implementation.
*/
#include "include/logging.h"
#include "lib/safeclib.h"
#include "lib/tmpbuf.h"
@ -26,6 +33,7 @@
#include "lib/recmutex.h"
#include "lib/error.h"
#include "include/config-facade.h"
#include "common/interfaceregistry.h"
#include "common/config.h"
#include "common/plugin.h"
@ -34,23 +42,15 @@
#include <nobug.h>
#ifndef LUMIERA_PLUGIN_PATH
#error please define the plugin search path as -DLUMIERA_PLUGIN_PATH, e.g. as $INSTALL_PREFIX/lib/lumiera
#endif
/**
* @file
* Plugin loader.
*/
/* just some declarations */
extern PSplay lumiera_pluginregistry;
static char* init_exts_globs (void);
/* TODO default plugin path should be set by the build system */
/* errors */
LUMIERA_ERROR_DEFINE(PLUGIN_INIT, "Initialization error");
LUMIERA_ERROR_DEFINE(PLUGIN_INIT, "Initialisation error");
LUMIERA_ERROR_DEFINE(PLUGIN_OPEN, "Could not open plugin");
LUMIERA_ERROR_DEFINE(PLUGIN_WTF, "Not a Lumiera plugin");
LUMIERA_ERROR_DEFINE(PLUGIN_REGISTER, "Could not register plugin");
@ -61,7 +61,7 @@ LUMIERA_ERROR_DEFINE(PLUGIN_VERSION, "Plugin Version unsupported");
/**
* Supported (and planned) plugin types and their file extensions
* This maps filename extensions to implementations (of the respective _load_NAME and _unload_NAME functions)
* So far we only support platform dynamic libraries, later we may add plugins implemented in lua
* So far we only support platform dynamic libraries, later we may add plugins implemented in Lua
* and c source modules which get compiled on the fly.
*/
#define LUMIERA_PLUGIN_TYPES \
@ -115,7 +115,8 @@ struct lumiera_plugin_struct
/* time when the refcounter dropped to 0 last time */
time_t last;
/* when loading plugins en masse we do not want to fail completely if one doesnt cooperate, instead we record local errors here */
/** bulk loading plugins must not fail entirely, just because one
* plugin doesn't comply. Thus we're recording local errors here */
lumiera_err error;
/* the 'plugin' interface itself */
@ -198,9 +199,12 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin),
REQUIRE (callback_load);
REQUIRE (callback_register);
lumiera_config_setdefault ("plugin.path ="LUMIERA_PLUGIN_PATH);
// Note: because the full-blown Config system isn't implemented yet,
// as a temporary solution we fetch this basic configuration
// from the setup.ini used to bootstrap the application
lumiera_config_setdefault (lumiera_get_plugin_path_default());
/* construct glob trail {.so,.c,.foo} ... */
/* construct glob trail {.so,.lum,.lua} ... */
static char* exts_globs = NULL;
if (!exts_globs)
exts_globs = init_exts_globs ();
@ -375,7 +379,7 @@ static char* init_exts_globs (void)
++itr;
}
exts_globs[exts_sz-2] = '}';
TRACE (pluginloader_dbg, "initialized extension glob to '%s'", exts_globs);
TRACE (pluginloader_dbg, "initialised extension glob to '%s'", exts_globs);
return exts_globs;
}

View file

@ -112,6 +112,9 @@ gtk_gui_la_SOURCES = \
$(lumigui_srcdir)/widgets/timecode-widget.hpp \
$(lumigui_srcdir)/widgets/timeline-widget.cpp \
$(lumigui_srcdir)/widgets/timeline-widget.hpp \
$(lumigui_srcdir)/widgets/timeline/basic-draw-strategy.cpp \
$(lumigui_srcdir)/widgets/timeline/basic-draw-strategy.hpp \
$(lumigui_srcdir)/widgets/timeline/draw-strategy.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-body.cpp \
@ -120,6 +123,8 @@ gtk_gui_la_SOURCES = \
$(lumigui_srcdir)/widgets/timeline/timeline-clip-track.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-clip.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-clip.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-entity.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-entity.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-group-track.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-group-track.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-header-container.cpp \

View file

@ -25,8 +25,8 @@
namespace gui {
namespace controller {
Controller::Controller(model::Project &model_project) :
project(model_project)
Controller::Controller(model::Project &modelProject) :
project(modelProject)
{
}

View file

@ -40,7 +40,7 @@ namespace controller {
class Controller
{
public:
Controller(model::Project &model_project);
Controller(model::Project &modelProject);
PlaybackController& get_playback_controller();

View file

@ -32,12 +32,12 @@ namespace dialogs {
/**
* The space in pixels to pad the border of Lumiera dialog boxes.
**/
*/
static const int BorderPadding = 8;
/**
* The spacing for VBoxes and HBoxes in Lumiera dialogs.
**/
*/
static const int BoxSpacing = 6;
} // namespace dialogs

View file

@ -30,8 +30,8 @@ using namespace Glib;
namespace gui {
namespace dialogs {
NameChooser::NameChooser(Window &parent, const Glib::ustring title,
const Glib::ustring default_name) :
NameChooser::NameChooser(Window &parent, cuString title,
cuString default_name) :
Dialog::Dialog(title, parent, true),
caption(_("Name:"))
{
@ -60,7 +60,7 @@ NameChooser::NameChooser(Window &parent, const Glib::ustring title,
show_all_children();
}
const Glib::ustring NameChooser::get_name() const
cuString NameChooser::get_name() const
{
return name.get_text();
}

View file

@ -45,16 +45,16 @@ public:
* @param title The string for the title of this dialog.
* @param default_name The name that will be shown by default in the
* edit box of the dialog.
**/
NameChooser(Gtk::Window &parent, const Glib::ustring title,
const Glib::ustring default_name);
*/
NameChooser(Gtk::Window &parent, cuString title,
cuString default_name);
/**
* Gets the current name of the chosen in the dialog.
* @return Returns the name currently typed into the edit box of the
* dialog.
**/
const Glib::ustring get_name() const;
*/
cuString get_name() const;
private:
Gtk::HBox hBox;

108
src/gui/gtk-base.hpp Normal file
View file

@ -0,0 +1,108 @@
/*
GTK-BASE.hpp - GTK includes and basic definitions
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file gtk-base.hpp
** A set of basic GTK includes.
** There are some tricky point to consider when including the
** basic GTKmm headers. Especially, GTK tries to shadow the ERROR macro
** from Microsoft Windows. Unfortunately this breaks the ERROR macro from NoBug;
** thus we need to include NoBug \em after GTK
**
** Besides, this header defines the basic NLS. Most parts of the GUI rely either
** directly on this header, or through the inclusion of gtk-lumiera.hpp
**
** @see GtkLumiera
*/
#ifndef GUI_GTK_BASE_H
#define GUI_GTK_BASE_H
//--------------------tricky special Include sequence
#include <locale>
#include <gtkmm.h>
#include <nobug.h>
//--------------------tricky special Include sequence
#include "lib/error.hpp"
#include "lib/util.hpp"
#include "lib/lumitime.hpp"
#ifdef ENABLE_NLS
# include <libintl.h>
# define _(String) gettext (String)
# define gettext_noop(String) String
# define N_(String) gettext_noop (String)
#else
# define _(String) (String)
# define N_(String) String
# define textdomain(Domain)
# define bindtextdomain(Package, Directory)
#endif
/* ======= Namespace Definitions ======= */
/** Lumiera GTK GUI implementation root. */
namespace gui {
typedef Glib::ustring uString;
typedef const uString cuString;
/** Dialog box classes. */
namespace dialogs {}
/** The Lumiera GTK-GUI uses a thin proxy layer data model
* on top of the actual "high-level-model", which lives in the
* Proc-Layer below. GUI operations interact with these proxy model
* entities, which in turn forward the calls to the actual objects
* in the Proc-Layer, through the Command system (which enables UNDO).
*
* @todo: as of 1/2011 this connection between the GUI proxy model and
* the Proc-Layer model needs to be set up. Currently, the GUI model
* entities are just created standalone and thus dysfunctional.
*/
namespace model {}
/** The namespace of all video output implementations. */
namespace output {}
/** Docking panel classes. */
namespace panels {}
/** Lumiera custom widgets. */
namespace widgets {}
/** The workspace window and it's helper classes. */
namespace workspace {}
/** GUI helpers, utility functions and classes. */
namespace util {}
}// namespace gui
#endif

View file

@ -1,5 +1,5 @@
/*
gtk-lumiera.cpp - The entry point for the GTK GUI application
GtkLumiera - The Lumiera GUI Application Object
Copyright (C) Lumiera.org
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
@ -20,115 +20,130 @@
* *****************************************************/
#include <gtkmm.h>
#include <nobug.h>
#ifdef ENABLE_NLS
# include <libintl.h>
#endif
#include "gtk-lumiera.hpp"
#include "window-manager.hpp"
#include "workspace/workspace-window.hpp"
#include "model/project.hpp"
#include "controller/controller.hpp"
extern "C" {
#include "common/interface.h"
}
NOBUG_CPP_DEFINE_FLAG(gui);
using namespace Gtk;
using namespace Glib;
using namespace gui;
using namespace gui::workspace;
using namespace gui::model;
using namespace gui::controller;
using namespace std;
GtkLumiera the_application;
#include "gui/gtk-lumiera.hpp"
#include "gui/window-manager.hpp"
#include "gui/workspace/workspace-window.hpp"
#include "gui/controller/controller.hpp"
#include "gui/model/project.hpp"
#include "lib/singleton.hpp"
#include "lib/symbol.hpp"
#include "include/config-facade.h"
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <vector>
namespace gui {
using namespace Gtk;
using namespace Glib;
using namespace gui::model;
using namespace gui::workspace;
using namespace gui::controller;
using boost::algorithm::is_any_of;
using boost::algorithm::split;
using lumiera::Config;
using lib::Literal;
typedef std::vector<uString> UVector;
namespace {
/** storage for the Main Application object */
lib::Singleton<GtkLumiera> theApplicationInstance;
Literal KEY_TITLE = "Lumiera.title";
Literal KEY_VERSION = "Lumiera.version";
Literal KEY_WEBSITE = "Lumiera.website";
Literal KEY_AUTHORS = "Lumiera.authors";
Literal KEY_STYLESHEET = "Gui.stylesheet";
Literal KEY_UIRES_PATH = "Gui.resourcepath";
Literal KEY_ICON_PATH = "Gui.iconpath";
}
GtkLumiera&
GtkLumiera::application()
{
return theApplicationInstance();
}
void
GtkLumiera::main(int argc, char *argv[])
GtkLumiera::main (int argc, char *argv[])
{
Glib::thread_init();
Main kit(argc, argv);
Glib::set_application_name(get_app_title());
Glib::set_application_name (getAppTitle());
Project project;
Controller controller(project);
windowManager.init();
windowManager.set_theme("lumiera_ui.rc");
windowManager.new_window(project, controller);
kit.run();
windowManagerInstance_.init (Config::get (KEY_ICON_PATH), Config::get (KEY_UIRES_PATH));
windowManagerInstance_.setTheme (Config::get (KEY_STYLESHEET));
windowManagerInstance_.newWindow (project, controller);
kit.run(); // GTK event loop
}
WindowManager&
GtkLumiera::get_window_manager()
GtkLumiera::windowManager()
{
return windowManager;
return windowManagerInstance_;
}
Glib::ustring
GtkLumiera::get_home_data_path()
cuString
GtkLumiera::getAppTitle()
{
const ustring app_name("lumiera");
const ustring path(Glib::get_home_dir());
return ustring::compose("%1/.%2", path, app_name);
return Config::get (KEY_TITLE);
}
const Glib::ustring
GtkLumiera::get_app_title()
cuString
GtkLumiera::getAppVersion()
{
return "Lumiera";
return Config::get (KEY_VERSION);
}
const Glib::ustring
GtkLumiera::get_app_version()
cuString
GtkLumiera::getCopyright()
{
return "0.1-dev";
return _("© 2012 The Lumiera Team");
}
const Glib::ustring GtkLumiera::get_app_copyright()
cuString
GtkLumiera::getLumieraWebsite()
{
return _("© 2008 The Lumiera Team");
return Config::get (KEY_WEBSITE);
}
const Glib::ustring GtkLumiera::get_app_website()
{
return "http://www.lumiera.org";
}
const std::vector<Glib::ustring>
GtkLumiera::get_app_authors()
const UVector
GtkLumiera::getLumieraAuthors()
{
const gchar* app_authors[] = {
"Joel Holdsworth",
"Christian Thaeter",
"Hermann Vosseler",
"[Other Authors Here]"};
string authors = Config::get (KEY_AUTHORS);
UVector authorsList;
const int count = sizeof(app_authors) / sizeof(gchar*);
std::vector<Glib::ustring> list(count);
for(int i = 0; i < count; i++)
list[i] = app_authors[i];
return list;
split (authorsList, authors, is_any_of (",|"));
return authorsList;
}
GtkLumiera&
application()
{
return the_application;
}
} // namespace gui

View file

@ -1,5 +1,5 @@
/*
gtk-lumiera.hpp - Application wide global definitions
GTK-LUMIERA.hpp - The Lumiera GUI Application Object
Copyright (C) Lumiera.org
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
@ -19,143 +19,84 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file gtk-lumiera.hpp
** This file contains application wide global definitions
** user actions.
** @see gtk-lumiera.cpp
** The main application object.
** Invoking the GtkLumiera::main() function brings up the GUI; this
** function will block in the GTK event thread until the Application gets
** closed by user interaction or by triggering a shutdown via the GuiNotificationFacade.
** GtkLumiera is a singleton and owns the central WindowManager instance used for
** opening all windows and registering and loading icons and resources.
**
** \par configuration and resource search
** The GUI object retrieves the necessary configuration values from lumiera::Config,
** the config facade in the application core. Currently as of 2/2011 these values are
** loaded from setup.ini, because the full-blown config system is not yet implemented.
** Amongst others, this configuration defines a <i>search path</i> for icons and a
** separate search path for resources. These path specs may use the token \c $ORIGIN
** to refer to the installation directory of the currently executing program.
** This allows for a relocatable Lumiera installation bundle.
**
** @see guistart.cpp the plugin to pull up this GUI
** @see gui::GuiFacade access point for starting the GUI
** @see gui::GuiNotification interface for communication with the gui from the lower layers
** @see lumiera::Config
** @see lumiera::BasicSetup definition of the acceptable configuration values
** @see lumiera::AppState general Lumiera application main
**
*/
#ifndef GTK_LUMIERA_HPP
#define GTK_LUMIERA_HPP
#ifndef GUI_GTK_LUMIERA_H
#define GUI_GTK_LUMIERA_H
#include <locale>
#include <gtkmm.h>
#include <nobug.h> // need to include this after gtkmm.h, because types.h from GTK tries to shaddow the ERROR macro from windows, which kills NoBug's ERROR macro
#include "gui/gtk-base.hpp"
#include "gui/window-manager.hpp"
#include <boost/noncopyable.hpp>
#include <vector>
#include <boost/utility.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "lib/util.hpp"
#include "lib/lumitime.hpp"
#include "window-manager.hpp"
extern "C" {
#include <gavl/gavltime.h>
}
//NOBUG_DECLARE_FLAG(gui);
#ifdef ENABLE_NLS
# include <libintl.h>
# define _(String) gettext (String)
# define gettext_noop(String) String
# define N_(String) gettext_noop (String)
#else
# define _(String) (String)
# define N_(String) String
# define textdomain(Domain)
# define bindtextdomain(Package, Directory)
#endif
/**
* Lumiera GTK GUI implementation root.
*/
namespace gui {
/* ===== The Application Class ===== */
/* ====== The Application Class ====== */
/**
* The main application class.
*/
class GtkLumiera : private boost::noncopyable
{
public:
void main(int argc, char *argv[]);
WindowManager& get_window_manager();
static Glib::ustring get_home_data_path();
/**
* Returns the name of the application
**/
static const Glib::ustring get_app_title();
/**
* Returns the version number of the application
**/
static const Glib::ustring get_app_version();
/**
* Returns the copyright of the application
**/
static const Glib::ustring get_app_copyright();
/**
* Returns the website of the application
**/
static const Glib::ustring get_app_website();
/**
* Returns tn alphabetical list of the application's authors
**/
static const std::vector<Glib::ustring> get_app_authors();
protected:
/**
* The application window manager object
**/
WindowManager windowManager;
};
/**
* Returns a reference to the global application object
*/
GtkLumiera& application();
/* ===== Namespace Definitions ===== */
/**
* The namespace of all dialog box classes.
*/
namespace dialogs {}
/**
* The namespace of data model classes.
*/
namespace model {}
/**
* The namespace of all video output implementations.
*/
namespace output {}
/**
* The namespace of all docking panel classes.
*/
namespace panels {}
/**
* The namespace of all Lumiera custom widgets.
*/
namespace widgets {}
/**
* The namespace of the workspace window, and it's helper classes.
*/
namespace workspace {}
/**
* The namespace of utility functions and classes.
*/
namespace util {}
} // namespace gui
#endif // GTK_LUMIERA_HPP
class GtkLumiera
: boost::noncopyable
{
/** Central application window manager instance */
WindowManager windowManagerInstance_;
public:
/** access the the global application object */
static GtkLumiera& application();
void main(int argc, char *argv[]);
WindowManager& windowManager();
/** the name of the application */
static cuString getAppTitle();
static cuString getAppVersion();
static cuString getCopyright();
static cuString getLumieraWebsite();
/** alphabetical list of the application's authors */
static const std::vector<uString> getLumieraAuthors();
};
}// namespace gui
#endif

View file

@ -3,8 +3,8 @@
Copyright (C) Lumiera.org
2007-2008, Joel Holdsworth <joel@airwebreathe.org.uk>
2009, Hermann Vosseler <Ichthyostega@web.de>
Christian Thaeter <ct@pipapo.org>
Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -110,7 +110,8 @@ namespace gui {
int argc =0;
char *argv[] = {}; // dummy command line for GTK
gui::application().main(argc, argv); // execute the GTK Event Loop
// execute the GTK Event Loop____________
GtkLumiera::application().main(argc, argv);
if (!lumiera_error_peek())
return; // all went well, normal shutdown
@ -199,7 +200,7 @@ extern "C" { /* ================== define an lumieraorg_Gui instance ===========
return
"Copyright (C) Lumiera.org\n"
"2007-2008, Joel Holdsworth <joel@airwebreathe.org.uk>\n"
" Christian Thaeter <ct@pipapo.org>\n"
"2009, Christian Thaeter <ct@pipapo.org>\n"
" Hermann Vosseler <Ichthyostega@web.de>";
}
)

View file

@ -22,22 +22,39 @@
#include "clip-track.hpp"
#include "clip.hpp"
#include <boost/shared_ptr.hpp>
namespace gui {
namespace model {
ClipTrack::ClipTrack()
{
}
std::string
ClipTrack::print_track()
{
std::ostringstream os;
os << "ClipTrack\t\"" << get_name() << "\"";
return os.str();
}
ClipTrack::ClipTrack()
{
// TEST CODE: add a clip to the track
boost::shared_ptr<model::Clip> modelClip(new model::Clip());
modelClip->setName("Clip Name");
clips.push_back(modelClip);
// END TEST CODE
}
std::string
ClipTrack::print_track()
{
std::ostringstream os;
os << "ClipTrack\t\"" << get_name() << "\"";
return os.str();
}
lumiera::observable_list< boost::shared_ptr<Clip> >&
ClipTrack::getClipList()
{
return clips;
}
} // namespace model
} // namespace gui

View file

@ -29,24 +29,38 @@
#define CLIP_TRACK_HPP
#include "track.hpp"
#include "lib/observable-list.hpp"
namespace gui {
namespace model {
class Clip;
class ClipTrack : public Track
{
public:
ClipTrack();
std::string print_track();
private:
std::vector<Clip*> clips;
};
class Clip;
class ClipTrack : public Track
{
public:
/**
* Constructor
*/
ClipTrack();
/**
* Gets a string representation of the track that is suitable for debugging
*/
std::string
print_track();
/**
* Gets the list of clips associated with this track.
*/
lumiera::observable_list< boost::shared_ptr<Clip> >&
getClipList(void);
private:
lumiera::observable_list< boost::shared_ptr<Clip> > clips;
};
} // namespace timeline
} // namespace gui

View file

@ -1,6 +1,6 @@
/*
clip.cpp - Implementation of the Clip object
Copyright (C) Lumiera.org
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
@ -25,10 +25,61 @@
namespace gui {
namespace model {
Clip::Clip()
{
}
Clip::Clip()
: begin(1000000),
end(2000000)
{ }
gavl_time_t
Clip::getBegin() const
{
return begin;
}
gavl_time_t
Clip::getEnd() const
{
return end;
}
const std::string
Clip::getName() const
{
return name;
}
bool
Clip::isPlayingAt(lumiera::Time position) const
{
return (begin <= position && end >= position);
}
void
Clip::setBegin(gavl_time_t begin)
{
this->begin = begin;
// TODO: emit signal
}
void
Clip::setEnd(gavl_time_t end)
{
this->end = end;
// TODO: emit signal
}
void
Clip::setName(const std::string &name)
{
this->name = name;
nameChangedSignal.emit(name);
}
sigc::signal<void, std::string>
Clip::signalNameChanged() const
{
return nameChangedSignal;
}
} // namespace model
} // namespace gui

View file

@ -23,21 +23,103 @@
** This file contains the definition of the Clip object
*/
#include <string>
#include "gui/gtk-lumiera.hpp"
#include "lib/lumitime.hpp"
// TODO: Remove once we get real measure of duration.
// This is here *only* for purposes of testing the GUI.
extern "C" {
#include <stdint.h>
#include <gavl/gavltime.h>
}
using Cairo::Pattern;
#ifndef CLIP_HPP
#define CLIP_HPP
namespace gui {
namespace model {
class Clip
{
public:
/**
* Constructor
**/
Clip();
class Clip
{
public:
/**
* Constructor
*/
Clip();
};
/**
* Gets the begin time of this clip.
*/
gavl_time_t
getBegin() const;
/**
* Gets the end time of this clip.
*/
gavl_time_t
getEnd() const;
/**
* Gets the name of this clip.
*/
const std::string
getName() const;
/**
* Check whether or not the clip will be playing during the given time.
*/
bool
isPlayingAt(lumiera::Time position) const;
/**
* Sets the begin time of this clip.
* @param[in] begin The new begin time to set this clip to.
*/
void
setBegin(gavl_time_t begin);
/**
* Sets the end time of this clip.
* @param[in] end The new end time to set this clip to.
*/
void
setEnd(gavl_time_t end);
/**
* Sets the name of this clip.
* @param[in] name The new name to set this clip to.
*/
void
setName(const std::string &name);
/**
* A signal which fires when the name changes.
* @return Returns the signal. The signal sends the new name for the clip.
*/
sigc::signal<void, std::string>
signalNameChanged() const;
private:
/**
* The name of this clip.
*/
std::string name;
/**
* A signal which fires when the name changes.
*/
sigc::signal<void, std::string> nameChangedSignal;
// TODO: Use a good measure of duration, probably TimeSpan.
// These are here *only* for purposes of testing the GUI.
gavl_time_t begin;
gavl_time_t end;
};
} // namespace model
} // namespace gui

View file

@ -33,20 +33,20 @@ namespace model {
/**
* A class representation of a grouping of tracks.
**/
*/
class GroupTrack : public ParentTrack
{
public:
/**
* Constructor
**/
*/
GroupTrack();
/**
* Produces a human readable debug string representation of this
* track.
* @return Returns the human readable string.
**/
*/
std::string print_track();
};

View file

@ -25,11 +25,15 @@
** are also track parents. This class wraps proc layer data
*/
#ifndef PARENT_TRACK_HPP
#define PARENT_TRACK_HPP
#include "track.hpp"
#include "lib/observable-list.hpp"
#ifndef PARENT_TRACK_HPP
#define PARENT_TRACK_HPP
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
namespace gui {
namespace model {
@ -37,7 +41,7 @@ namespace model {
/**
* ParentTrack is the abstract base class of all tracks that can parent
* children.
**/
*/
class ParentTrack :
public Track,
public boost::enable_shared_from_this<ParentTrack>
@ -45,20 +49,20 @@ class ParentTrack :
protected:
/**
* Constructor
**/
*/
ParentTrack();
public:
/**
* Gets a read-only reference to the the list of child tracks.
**/
*/
const std::list< boost::shared_ptr<Track> >&
get_child_tracks() const;
/**
* Gets read-write access to the list of child tracks.
**/
*/
lumiera::observable_list< boost::shared_ptr<Track> >&
get_child_track_list();
@ -66,7 +70,7 @@ public:
* Returns true if this track can own any child tracks.
* @return Returns true because all classed derrived from ParentTrack
* can.
**/
*/
bool can_host_children() const;
/**
@ -74,7 +78,7 @@ public:
* track.
* @param The model track to try and remove.
* @return Returns true if the track was successfully removed.
**/
*/
bool remove_descendant_track(const boost::shared_ptr<Track> track);
/**
@ -83,14 +87,14 @@ public:
* @param child The child track to find the parent of.
* @return Returns the parent track if one was found, or an empty
* shared_ptr if none was found.
**/
*/
boost::shared_ptr<ParentTrack>
find_descendant_track_parent(boost::shared_ptr<Track> child);
protected:
/**
* The internal list of child tracks of this parent.
**/
*/
lumiera::observable_list< boost::shared_ptr<Track> > tracks;
};

View file

@ -50,7 +50,7 @@ Project::get_sequences()
}
void
Project::add_new_sequence(Glib::ustring name)
Project::add_new_sequence(uString name)
{
shared_ptr<Sequence> sequence(new Sequence());
sequence->set_name(name);

View file

@ -43,7 +43,7 @@ public:
lumiera::observable_list< boost::shared_ptr<Sequence> >&
get_sequences();
void add_new_sequence(Glib::ustring name);
void add_new_sequence(uString name);
private:

View file

@ -37,20 +37,20 @@ class Track;
/**
* A class representation of a sequence.
* @remarks Sequence objects are also the roots of track trees.
**/
*/
class Sequence : public ParentTrack
{
public:
/**
* Constructor
**/
*/
Sequence();
/**
* Produces a human readable debug string representation of this
* track.
* @return Returns the human readable string.
**/
*/
std::string print_track();
};

View file

@ -33,6 +33,8 @@ namespace model {
const list< shared_ptr<Track> > Track::NoChildren;
Track::Track()
: enabled(true),
locked(false)
{
}
@ -43,12 +45,38 @@ Track::get_child_tracks() const
return Track::NoChildren;
}
bool
Track::getEnabled() const
{
return enabled;
}
bool
Track::getLocked() const
{
return locked;
}
const string
Track::get_name() const
{
return name;
}
void
Track::setEnabled(bool enabled)
{
this->enabled = enabled;
enabledChangedSignal.emit(enabled);
}
void
Track::setLocked(bool locked)
{
this->locked = locked;
lockedChangedSignal.emit(locked);
}
void
Track::set_name(const string &name)
{
@ -75,8 +103,20 @@ Track::find_descendant_track_parent(
return shared_ptr<ParentTrack>();
}
sigc::signal<void, bool>
Track::signalEnabledChanged() const
{
return enabledChangedSignal;
}
sigc::signal<void, bool>
Track::signalLockedChanged() const
{
return lockedChangedSignal;
}
sigc::signal<void, std::string>
Track::signal_name_changed() const
Track::signalNameChanged() const
{
return nameChangedSignal;
}

View file

@ -37,38 +37,67 @@ class ParentTrack;
/**
* The model representation of a track. This is the abstract base class
* for all types of track that are implemented.
**/
*/
class Track
{
protected:
/**
* Constructor
**/
*/
Track();
public:
/**
* Returns true if this track can own any child tracks.
*/
virtual bool
can_host_children () const;
/**
* Gets the list of child tracks.
**/
*/
virtual const std::list< boost::shared_ptr<Track> >&
get_child_tracks() const;
get_child_tracks () const;
/**
* Gets the enabled status of this track, i.e. if the track is to be rendered.
*/
bool
getEnabled () const;
/**
* Gets the locked status of this track, i.e. if the track can be edited.
*/
bool
getLocked () const;
/**
* Gets the name of this track.
**/
const std::string get_name() const;
*/
const std::string
get_name () const;
/**
* Sets the enabled status of this track, i.e. if the track is to be rendered.
* @param[in] name The new enabled status.
*/
void
setEnabled (bool enabled);
/**
* Gets the locked status of this track, i.e. if the track can be edited.
* @param[in] name The new locked status.
*/
void
setLocked (bool locked);
/**
* Sets the name of this track.
* @param[in] name The new name to set this track to.
**/
void set_name(const std::string &name);
/**
* Returns true if this track can own any child tracks.
**/
virtual bool can_host_children() const;
*/
void
set_name (const std::string &name);
/**
* A utility function that attempts to find the parent of a track by
@ -76,61 +105,96 @@ public:
* @param child The child track to find the parent of.
* @return Returns the parent track if one was found, or an empty
* shared_ptr if none was found.
**/
*/
virtual boost::shared_ptr<ParentTrack>
find_descendant_track_parent(boost::shared_ptr<Track> child);
find_descendant_track_parent (boost::shared_ptr<Track> child);
public:
/**
* A signal which fires when the enabled status changes.
* @return Returns the signal. The signal sends the new name for the
* track.
*/
sigc::signal<void, bool>
signalEnabledChanged () const;
/**
* A signal which fires when the locked status changes changes.
* @return Returns the signal. The signal sends the new name for the
* track.
*/
sigc::signal<void, bool>
signalLockedChanged () const;
/**
* A signal which fires when the name changes.
* @return Returns the signal. The signal sends the new name for the
* track.
**/
sigc::signal<void, std::string> signal_name_changed() const;
*/
sigc::signal<void, std::string>
signalNameChanged () const;
public:
/**
* A debugging helper function that prints this track, and all it's
* child tracks in a human-readable form.
* @return Returns the human readable string.
**/
std::string print_branch();
*/
std::string
print_branch ();
/**
* A pure-virtual function which is the base of functions that print
* this track in human readable form.
* @return Returns the human readable string.
**/
virtual std::string print_track() = 0;
*/
virtual std::string
print_track () = 0;
protected:
/**
* An object used internally as a return value for when there's no
* children.
*/
static const std::list< boost::shared_ptr<Track> > NoChildren;
/**
* The internal implementation of print_branch.
* @param indentation The level of recursion into the tree. This value
* is used to specify the width of indentation to print with.
* @return Returns the human readable string.
**/
std::string print_branch_recursive(const unsigned int indentation);
*/
std::string
print_branch_recursive (const unsigned int indentation);
private:
//----- Data -----//
/**
* The name of this track.
**/
*/
std::string name;
/**
* True if this track is enabled, i.e. will not be rendered.
*/
bool enabled;
/**
* True if this track is locked, i.e. cannot be edited.
*/
bool locked;
/**
* A signal which fires when the enabled status changes.
*/
sigc::signal<void, bool> enabledChangedSignal;
/**
* A signal which fires when the locked status changes.
*/
sigc::signal<void, bool> lockedChangedSignal;
/**
* A signal which fires when the name changes.
**/
*/
sigc::signal<void, std::string> nameChangedSignal;
protected:
/**
* An object used internally as a return value for when there's no
* children.
**/
static const std::list< boost::shared_ptr<Track> > NoChildren;
};
} // namespace model

View file

@ -35,7 +35,7 @@ namespace output {
/**
* Supported Displayer formats
**/
*/
typedef enum {
DISPLAY_NONE,
DISPLAY_YUV,

View file

@ -21,6 +21,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file gdkdisplayer.hpp
** This file contains the definition of XvDisplayer, the XVideo
** video output implementation
@ -28,10 +30,10 @@
** @see displayer.hpp
*/
#include "displayer.hpp"
#ifndef GUI_OUTPUT_GDKDISPLAYER_H
#define GUI_OUTPUT_GDKDISPLAYER_H
#ifndef GDKDISPLAYER_HPP
#define GDKDISPLAYER_HPP
#include "displayer.hpp"
namespace Gtk {
class Widget;
@ -43,47 +45,48 @@ namespace output {
/**
* GdkDisplayer is a class which is responsible for rendering a video
* image via GDK.
**/
class GdkDisplayer : public Displayer
{
public:
/**
* Constructor
* @param[in] drawing_area The widget into which the video image will
* be drawn. This value must not be NULL.
* @param[in] width The width of the video image in pixels. This value
* must be greater than zero.
* @param[in] height The height of the video image in pixels. This
* value must be greater than zero.
**/
GdkDisplayer( Gtk::Widget *drawing_area, int width, int height );
/**
* Put an image of a given width and height with the expected input
* format (as indicated by the format method).
* @param[in] image The video image array to draw.
*/
void put( const void* image );
protected:
/**
* Indicates if this object can be used to render images on the
* running system.
*/
bool usable();
private:
/**
* The widget that video will be drawn into.
* @remarks This value must be a valid pointer.
**/
Gtk::Widget *drawingArea;
};
} // namespace output
} // namespace gui
*/
class GdkDisplayer
: public Displayer
{
public:
/**
* Constructor
* @param[in] drawing_area The widget into which the video image will
* be drawn. This value must not be NULL.
* @param[in] width The width of the video image in pixels. This value
* must be greater than zero.
* @param[in] height The height of the video image in pixels. This
* value must be greater than zero.
*/
GdkDisplayer( Gtk::Widget *drawing_area, int width, int height );
/**
* Put an image of a given width and height with the expected input
* format (as indicated by the format method).
* @param[in] image The video image array to draw.
*/
void put( const void* image );
protected:
/**
* Indicates if this object can be used to render images on the
* running system.
*/
bool usable();
private:
/**
* The widget that video will be drawn into.
* @remarks This value must be a valid pointer.
*/
Gtk::Widget *drawingArea;
};
}} // namespace gui::output
#endif // GDKDISPLAYER_HPP

View file

@ -21,6 +21,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file xvdisplayer.hpp
** This file contains the definition of XvDisplayer, the XVideo
** video output implementation
@ -28,6 +30,10 @@
** @see displayer.hpp
*/
#ifndef GUI_OUTPUT_XVDISPLAYER_H
#define GUI_OUTPUT_XVDISPLAYER_H
#include <X11/Xlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
@ -36,8 +42,6 @@
#include "displayer.hpp"
#ifndef XVDISPLAYER_HPP
#define XVDISPLAYER_HPP
namespace Gtk {
class Widget;
@ -49,89 +53,87 @@ namespace output {
/**
* XvDisplayer is a class which is responsible for rendering a video
* image via XVideo.
**/
class XvDisplayer : public Displayer
{
public:
/**
* Constructor
* @param drawing_area The widget into which the video image will be
* drawn. This value must not be NULL.
* @param width The width of the video image in pixels. This value
* must be greater than zero.
* @param height The height of the video image in pixels. This value
* must be greater than zero.
**/
XvDisplayer( Gtk::Widget *drawing_area, int width, int height );
*/
class XvDisplayer
: public Displayer
{
public:
/**
* Constructor
* @param drawing_area The widget into which the video image will be
* drawn. This value must not be NULL.
* @param width The width of the video image in pixels. This value
* must be greater than zero.
* @param height The height of the video image in pixels. This value
* must be greater than zero.
*/
XvDisplayer( Gtk::Widget *drawing_area, int width, int height );
~XvDisplayer();
/**
* Put an image of a given width and height with the expected input
* format (as indicated by the format method).
* @param[in] image The video image array to draw.
*/
void put( const void* image );
/**
* Indicates if this object can be used to render images on the
* running system.
*/
bool usable();
private:
/**
* Specifies whether the object is currently attached to an XVideo
* port.
* @remarks This value is false until the constructor has finished
* successfully.
*/
bool gotPort;
/**
* The current port being used.
* @remarks This value is meaningless unless gotPort is true.
*/
unsigned int grabbedPort;
/**
* The widget that video will be drawn into.
* @remarks This value must be a valid pointer.
*/
Gtk::Widget *drawingArea;
/**
* The display that video will be drawn into.
*/
Display *display;
/**
* The X11 window that video will be drawn into.
*/
Window window;
/**
* The graphics context which will be used when rendering video.
*/
GC gc;
/**
* The shared memory image object which video will be written into.
*/
XvImage *xvImage;
/**
* Info about the shared memory segment.
* @remarks shmInfo.shmaddr is set to NULL, when the SHM is detached.
*/
XShmSegmentInfo shmInfo;
};
/**
* Destructor
**/
~XvDisplayer();
/**
* Put an image of a given width and height with the expected input
* format (as indicated by the format method).
* @param[in] image The video image array to draw.
*/
void put( const void* image );
/**
* Indicates if this object can be used to render images on the
* running system.
*/
bool usable();
private:
/**
* Specifies whether the object is currently attached to an XVideo
* port.
* @remarks This value is false until the constructor has finished
* successfully.
**/
bool gotPort;
/**
* The current port being used.
* @remarks This value is meaninless unless gotPort is true.
**/
unsigned int grabbedPort;
/**
* The widget that video will be drawn into.
* @remarks This value must be a valid pointer.
**/
Gtk::Widget *drawingArea;
/**
* The display that video will be drawn into.
**/
Display *display;
/**
* The X11 window that video will be drawn into.
**/
Window window;
/**
* The graphics context which will be used when rednering video.
**/
GC gc;
/**
* The shared memory image object which video will be written into.
**/
XvImage *xvImage;
/**
* Info about the shared memory segment.
* @remarks shmInfo.shmaddr is set to NULL, when the SHM is detached.
**/
XShmSegmentInfo shmInfo;
};
} // namespace output
} // namespace gui
}} // namespace gui::output
#endif // XVDISPLAYER_HPP

View file

@ -38,20 +38,20 @@ public:
* Contructor.
* @param panel_manager The owner panel manager widget.
* @param dock_item The GdlDockItem that will host this panel.
**/
*/
AssetsPanel(workspace::PanelManager &panel_manager,
GdlDockItem *dock_item);
/**
* Get the title of the panel.
* @return Returns a pointer to the string title of the panel.
**/
*/
static const char* get_title();
/**
* Get the stock id for this type panel.
* @return Returns a pointer to the string stock id of the panel.
**/
*/
static const gchar* get_stock_id();
protected:

View file

@ -53,7 +53,7 @@ protected:
* @param dock_item The GdlDockItem that will host this panel.
* @param long_name This title of the panel
* @param stock_id The stock_id of this panel.
**/
*/
Panel(workspace::PanelManager &panel_manager,
GdlDockItem *dock_item, const gchar* long_name,
const gchar *stock_id);
@ -61,7 +61,7 @@ protected:
public:
/**
* Destructor
**/
*/
~Panel();
/**
@ -73,7 +73,7 @@ public:
* Shows or hides the panel.
* @param show A value of true will show the panel, false will hide
* it.
**/
*/
void show(bool show = true);
/**
@ -83,53 +83,53 @@ public:
/**
* Iconifys the panel.
**/
*/
void iconify();
/**
* Returns true if the panel is currently iconified.
**/
*/
bool is_iconified() const;
/**
* Locks or unlocks the panel.
* @param show A value of true will lock the panel, false will unlock
* it.
**/
*/
void lock(bool show = true);
/**
* Returns true if the panel is currently locked.
**/
*/
bool is_locked() const;
/**
* Returns a reference to the owner panel manager object.
**/
*/
workspace::PanelManager& get_panel_manager();
public:
/**
* A signal that fires when the dock item is hidden.
**/
*/
sigc::signal<void>& signal_hide_panel();
protected:
/**
* Returns a reference to the owner workspace window object.
**/
*/
workspace::WorkspaceWindow& get_workspace_window();
/**
* Returns a reference to the project
**/
*/
model::Project& get_project();
/**
* Returns a reference to the controller
**/
*/
controller::Controller& get_controller();
private:
@ -137,35 +137,35 @@ private:
/**
* An event handler for when dockItem is hidden.
* @param func_data A pointer to the panel that owns dock_item
**/
*/
static void on_item_hidden(GdlDockItem*, Panel *panel);
protected:
/**
* The owner panel manager object.
**/
*/
workspace::PanelManager &panelManager;
/**
* The owner dock item widget that will host the widgets in this
* panel.
**/
*/
GdlDockItem* dockItem;
/**
* A signal that fires when the dock item is hidden.
**/
*/
sigc::signal<void> hidePanelSignal;
/**
* The id of the hide panel handler.
**/
*/
gulong hide_panel_handler_id;
/**
* The panel bar to attach to the panel grip.
**/
*/
widgets::PanelBar panelBar;
};

View file

@ -29,9 +29,8 @@
#include "gui/model/project.hpp"
#include "gui/controller/controller.hpp"
extern "C" {
#include "lib/time.h"
}
using namespace Gtk;
using namespace sigc;

View file

@ -19,10 +19,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file timeline-panel.hpp
** This file contains the definition of the timeline panel
*/
#ifndef TIMELINE_PANEL_HPP
#define TIMELINE_PANEL_HPP
@ -30,8 +33,12 @@
#include "gui/widgets/timecode-widget.hpp"
#include "gui/widgets/timeline-widget.hpp"
#include <boost/scoped_ptr.hpp>
#include <boost/weak_ptr.hpp>
using namespace gui::widgets;
namespace gui {
namespace model {
@ -51,25 +58,25 @@ public:
* Constructor.
* @param panel_manager The owner panel manager widget.
* @param dock_item The GdlDockItem that will host this panel.
**/
*/
TimelinePanel(workspace::PanelManager &panel_manager,
GdlDockItem *dock_item);
/**
* Destructor
**/
*/
~TimelinePanel();
/**
* Get the title of the panel.
* @return Returns a pointer to the string title of the panel.
**/
*/
static const char* get_title();
/**
* Get the stock id for this type panel.
* @return Returns a pointer to the string stock id of the panel.
**/
*/
static const gchar* get_stock_id();
private:
@ -91,13 +98,13 @@ private:
/**
* An event handler for when the list of sequences changes.
**/
*/
void on_sequence_list_changed();
/**
* An event handler for when a new sequence is chosen in the
* sequenceChooser.
**/
*/
void on_sequence_chosen();
private:
@ -125,27 +132,27 @@ private:
/**
* The definition of the sequence chooser combo box columns
**/
*/
class SequenceChooserColumns : public Gtk::TreeModel::ColumnRecord
{
public:
/**
* Constructor
**/
*/
SequenceChooserColumns()
{ add(nameColumn); add(sequenceColumn); }
/**
* An invisible column which will be used to identify the sequence
* of a row.
**/
*/
Gtk::TreeModelColumn< boost::weak_ptr<model::Sequence> >
sequenceColumn;
/**
* The column to use as the label for the combo box widget items.
**/
Gtk::TreeModelColumn< Glib::ustring > nameColumn;
*/
Gtk::TreeModelColumn< uString > nameColumn;
};
private:

View file

@ -36,7 +36,7 @@ namespace panels {
/**
* A panel to display the video output.
**/
*/
class ViewerPanel : public Panel
{
public:
@ -44,20 +44,20 @@ public:
* Contructor.
* @param panel_manager The owner panel manager widget.
* @param dock_item The GdlDockItem that will host this panel.
**/
*/
ViewerPanel(workspace::PanelManager &panel_manager,
GdlDockItem *dock_item);
/**
* Get the title of the panel.
* @return Returns a pointer to the string title of the panel.
**/
*/
static const char* get_title();
/**
* Get the stock id for this type panel.
* @return Returns a pointer to the string stock id of the panel.
**/
*/
static const gchar* get_stock_id();
protected:
@ -68,7 +68,7 @@ protected:
/**
* The video display widget, which will display the video.
**/
*/
widgets::VideoDisplayWidget display;
};

View file

@ -38,14 +38,14 @@ namespace util {
* @param rect The rect to test.
* @return Returns true if the point is within the rectangle, false if
* not.
**/
*/
bool pt_in_rect(const Gdk::Point &point, const Gdk::Rectangle &rect);
/**
* Tests whether two rectangles overlap.
* @param a The first rectangle.
* @param b The second rectangle.
**/
*/
bool rects_overlap(const Gdk::Rectangle &a, const Gdk::Rectangle &b);
} // util

View file

@ -33,26 +33,26 @@ namespace widgets {
/**
* A modified toolbar widget for use in dialogs.
**/
*/
class ButtonBar : public Gtk::Box
{
public:
/**
* Constructor
**/
*/
ButtonBar();
/**
* Append a widget to the button bar.
* @param widget The button to append.
**/
*/
void append(Widget &widget);
/**
* Append a button to the button bar, and connect a click event.
* @param button The button to append.
* @param clicked_slot The slot to connect.
**/
*/
template<class T> void append(MiniWrapper<T>& button,
const sigc::slot<void>& clicked_slot)
{

View file

@ -57,7 +57,7 @@ MenuButton::MenuButton(const StockID& stock_id) :
setup_button();
}
MenuButton::MenuButton(const Glib::ustring& label, bool mnemonic) :
MenuButton::MenuButton(cuString& label, bool mnemonic) :
ToggleButton(),
caption(label, mnemonic),
arrow(arrowType, shadowType)

View file

@ -26,14 +26,14 @@
#ifndef MENU_BUTTON_HPP
#define MENU_BUTTON_HPP
#include <gtkmm.h>
#include "gui/gtk-base.hpp"
namespace gui {
namespace widgets {
/**
* A button that display a menu when clicked on.
**/
*/
class MenuButton : public Gtk::ToggleButton
{
public:
@ -43,8 +43,8 @@ public:
* @remarks With an empty button, you can Gtk::Button::add() a widget
* such as a Gtk::Pixmap or Gtk::Box. If you just wish to add a
* Gtk::Label, you may want to use the
* Gtk::MenuButton(const Glib::ustring& label) ctor directly instead.
**/
* Gtk::MenuButton(cuString& label) ctor directly instead.
*/
MenuButton();
/**
@ -52,7 +52,7 @@ public:
* item.
* @remarks Stock ids have identifiers like Gtk::Stock::OK and
* Gtk::Stock::APPLY.
**/
*/
MenuButton(const Gtk::StockID& stock_id);
/**
@ -60,37 +60,37 @@ public:
* @remarks Create a button with the given label inside. You won't be
* able to add a widget in this button since it already has a
* Gtk::Label in it
**/
MenuButton(const Glib::ustring& label, bool mnemonic=false);
*/
MenuButton(cuString& label, bool mnemonic=false);
/**
* Gets the menu which will be displayed when the button is clicked
* on.
* @return Returns a reference to the menu that will be clicked on.
* This reference can be used to populate the menu with items.
**/
*/
Gtk::Menu& get_menu();
/**
* Pops up the menu.
**/
*/
void popup();
protected:
/**
* An internal method which sets up the button at creat time.
**/
*/
void setup_button();
/**
* An event handler for when the button is pressed.
**/
*/
void on_pressed();
/**
* An event handler for when the menu is closed.
**/
*/
void on_menu_deactivated();
private:
@ -104,35 +104,35 @@ private:
* coordinates.
* @param push_in This value is set to true if the menu should be
* pushed in if it collides with the edge of the screen.
**/
*/
void on_menu_position(int& x, int& y, bool& push_in);
private:
/**
* The hBox for the layout of image, caption and arrow.
**/
*/
Gtk::HBox hBox;
/**
* The image that will optionally display an icon.
**/
*/
Gtk::Image image;
/**
* The caption text label to show on the button.
**/
*/
Gtk::Label caption;
/**
* The arrow widget that will be displayed to hint the user that this
* button is a drop-down.
**/
*/
Gtk::Arrow arrow;
/**
* The internal menu object which is the popup menu of this widget.
**/
*/
Gtk::Menu menu;
};

View file

@ -33,7 +33,7 @@ namespace widgets {
/**
* A wrapper for ToolButton-like Button widgets
**/
*/
template<class T>
class MiniWrapper : public T
{
@ -46,7 +46,7 @@ public:
* @param icon_size The size of the image to show.
* @remarks Stock ids have identifiers like Gtk::Stock::OK and
* Gtk::Stock::APPLY.
**/
*/
MiniWrapper(const Gtk::StockID& stock_id,
const Gtk::IconSize icon_size = Gtk::ICON_SIZE_LARGE_TOOLBAR) :
image(stock_id, icon_size)
@ -60,7 +60,7 @@ public:
* Sets a new image from a stock-id for this button.
* @param stock_id The stock_id of the image.
* @param icon_size The size of the image to show.
**/
*/
void set_stock_id(const Gtk::StockID& stock_id,
const Gtk::IconSize icon_size = Gtk::ICON_SIZE_LARGE_TOOLBAR)
{
@ -71,18 +71,18 @@ private:
/**
* The image widget for the button.
**/
*/
Gtk::Image image;
};
/**
* A ToolButton-like widget
**/
*/
typedef MiniWrapper<Gtk::Button> MiniButton;
/**
* A ToggleToolButton-like widget
**/
*/
typedef MiniWrapper<Gtk::ToggleButton> MiniToggleButton;
} // gui

View file

@ -39,7 +39,7 @@ namespace widgets {
/**
* A container widget for widgets to be displayed on GDL panels grips.
**/
*/
class PanelBar : public Gtk::Box
{
public:
@ -49,21 +49,21 @@ public:
* @param owner_panel The panel that is the parent of this panel bar.
* @param stock_id The stock id with a name and an icon for this
* panel.
**/
*/
PanelBar(panels::Panel &owner_panel, const gchar *stock_id);
private:
/**
* Sets up panelButton, populating it with menu items.
**/
*/
void setup_panel_button();
private:
/**
* An override to intercept realize events.
**/
*/
void on_realize();
/**
@ -75,7 +75,7 @@ private:
/**
* An override to intercept size allocate events.
**/
*/
void on_size_allocate(Gtk::Allocation& allocation);
private:
@ -84,50 +84,50 @@ private:
* An event handler for when a panel type is chosen.
* @param type_index The index of the panel description that will be
* instantiated.
**/
*/
void on_panel_type(int type_index);
/**
* An event handler for when the "Hide" menu item is clicked
**/
*/
void on_hide();
/**
* Event handler for when the "Lock" menu item is clicked
**/
*/
void on_lock();
/**
* Event handler for when the split panel menu item is clicked
* @param split_direction The direction to split in.
**/
*/
void on_split_panel(Gtk::Orientation split_direction);
private:
/**
* A reference to the owner panel object.
**/
*/
panels::Panel &panel;
/**
* The panel menu drop-down button widget, that will be displayed in
* the corner of the bar.
**/
*/
MenuButton panelButton;
/**
* A pointer to the lock menu item.
* @remarks This value will remain NULL until after setup_panel_button
* has been called.
**/
*/
Gtk::CheckMenuItem *lockItem;
/**
* The bar window.
* @remarks This window is used only to set the cursor as an arrow for
* any child widgets.
**/
*/
Glib::RefPtr<Gdk::Window> window;
};

View file

@ -105,7 +105,7 @@ TimelineWidget::set_state(shared_ptr<timeline::TimelineState> new_state)
// Clear the track tree
trackMap.clear();
if(state)
if (state)
{
// Hook up event handlers
state->get_view_window().changed_signal().connect( sigc::mem_fun(
@ -175,6 +175,7 @@ TimelineWidget::hovering_track_changed_signal() const
{
return hoveringTrackChangedSignal;
}
sigc::signal<void>
TimelineWidget::state_changed_signal() const
{
@ -285,39 +286,39 @@ TimelineWidget::create_timeline_tracks()
void
TimelineWidget::create_timeline_tracks_from_branch(
shared_ptr<model::Track> model_track)
shared_ptr<model::Track> modelTrack)
{
REQUIRE(model_track);
REQUIRE(modelTrack);
// Is a timeline UI track present in the map already?
if(!contains(trackMap, model_track))
if(!contains(trackMap, modelTrack))
{
// The timeline UI track is not present
// We will need to create one
trackMap[model_track] =
create_timeline_track_from_model_track(model_track);
trackMap[modelTrack] =
create_timeline_track_from_modelTrack(modelTrack);
}
// Recurse to child tracks
BOOST_FOREACH(shared_ptr<model::Track> child,
model_track->get_child_tracks())
modelTrack->get_child_tracks())
create_timeline_tracks_from_branch(child);
}
shared_ptr<timeline::Track>
TimelineWidget::create_timeline_track_from_model_track(
shared_ptr<model::Track> model_track)
TimelineWidget::create_timeline_track_from_modelTrack(
shared_ptr<model::Track> modelTrack)
{
REQUIRE(model_track);
REQUIRE(modelTrack);
// Choose a corresponding timeline track class from the model track's
// class
if(typeid(*model_track) == typeid(model::ClipTrack))
if(typeid(*modelTrack) == typeid(model::ClipTrack))
return shared_ptr<timeline::Track>(new timeline::ClipTrack(
*this, model_track));
else if(typeid(*model_track) == typeid(model::GroupTrack))
*this, dynamic_pointer_cast<model::ClipTrack>(modelTrack)));
else if(typeid(*modelTrack) == typeid(model::GroupTrack))
return shared_ptr<timeline::Track>(new timeline::GroupTrack(
*this, dynamic_pointer_cast<model::GroupTrack>(model_track)));
*this, dynamic_pointer_cast<model::GroupTrack>(modelTrack)));
ASSERT(NULL); // Unknown track type;
return shared_ptr<timeline::Track>();
@ -325,7 +326,7 @@ TimelineWidget::create_timeline_track_from_model_track(
void
TimelineWidget::remove_orphaned_tracks()
{
{
std::map<boost::shared_ptr<model::Track>,
boost::shared_ptr<timeline::Track> >
orphan_track_map(trackMap);
@ -348,32 +349,32 @@ TimelineWidget::remove_orphaned_tracks()
void
TimelineWidget::search_orphaned_tracks_in_branch(
boost::shared_ptr<model::Track> model_track,
boost::shared_ptr<model::Track> modelTrack,
std::map<boost::shared_ptr<model::Track>,
boost::shared_ptr<timeline::Track> > &orphan_track_map)
{
REQUIRE(model_track);
REQUIRE(modelTrack);
// Is the timeline UI still present?
if(contains(orphan_track_map, model_track))
orphan_track_map.erase(model_track);
if(contains(orphan_track_map, modelTrack))
orphan_track_map.erase(modelTrack);
// Recurse to child tracks
BOOST_FOREACH(shared_ptr<model::Track> child,
model_track->get_child_tracks())
modelTrack->get_child_tracks())
search_orphaned_tracks_in_branch(child, orphan_track_map);
}
shared_ptr<timeline::Track>
TimelineWidget::lookup_timeline_track(
shared_ptr<model::Track> model_track) const
shared_ptr<model::Track> modelTrack) const
{
REQUIRE(model_track);
REQUIRE(model_track != sequence()); // The sequence isn't
REQUIRE(modelTrack);
REQUIRE(modelTrack != sequence()); // The sequence isn't
// really a track
std::map<shared_ptr<model::Track>, shared_ptr<timeline::Track> >::
const_iterator iterator = trackMap.find(model_track);
const_iterator iterator = trackMap.find(modelTrack);
if(iterator == trackMap.end())
{
// The track is not present in the map

View file

@ -75,13 +75,13 @@ public:
* Gets a pointer to the current state object.
* @return The state object that the timeline widget is currently
* working with.
**/
*/
boost::shared_ptr<timeline::TimelineState> get_state();
/**
* Replaces the current TimelineState object with another.
* @param new_state The new state to swap in.
**/
*/
void set_state(boost::shared_ptr<timeline::TimelineState> new_state);
/**
@ -89,7 +89,7 @@ public:
* given point on the timeline still.
* @param zoom_size The number of steps to zoom by. The scale factor
* is 1.25^(-zoom_size).
**/
*/
void zoom_view(int zoom_size);
/**
@ -102,7 +102,8 @@ public:
*/
void set_tool(timeline::ToolType tool_type);
boost::shared_ptr<timeline::Track> get_hovering_track() const;
boost::shared_ptr<timeline::Track>
get_hovering_track() const;
public:
/* ===== Signals ===== */
@ -139,7 +140,7 @@ private:
/**
* Updates the timeline widget to match the state of the track tree.
**/
*/
void update_tracks();
void freeze_update_tracks();
@ -149,7 +150,7 @@ private:
/**
* Ensures timeline UI tracks have been created for every model track
* present in sequence.
**/
*/
void create_timeline_tracks();
/**
@ -157,41 +158,41 @@ private:
* creating UI timeline tracks for each model track if they don't
* already exist in trackMap.
* @param list The parent track of the branch.
**/
*/
void create_timeline_tracks_from_branch(
boost::shared_ptr<model::Track> model_track);
boost::shared_ptr<model::Track> modelTrack);
/**
* Creates a timeline UI track to correspond to a model track.
* @param model_track The model track to create a timeline track from.
* @param modelTrack The model track to create a timeline track from.
* @return The timeline track created, or an empty shared_ptr if
* model_track has an unreckognised type (this is an error condition).
**/
* modelTrack has an unreckognised type (this is an error condition).
*/
boost::shared_ptr<timeline::Track>
create_timeline_track_from_model_track(
boost::shared_ptr<model::Track> model_track);
create_timeline_track_from_modelTrack(
boost::shared_ptr<model::Track> modelTrack);
/**
* Removes any UI tracks which no longer have corresponding model
* tracks present in the sequence.
**/
*/
void remove_orphaned_tracks();
void search_orphaned_tracks_in_branch(
boost::shared_ptr<model::Track> model_track,
boost::shared_ptr<model::Track> modelTrack,
std::map<boost::shared_ptr<model::Track>,
boost::shared_ptr<timeline::Track> > &orphan_track_map);
/**
* Looks up a timeline UI track in trackMap that corresponds to a
* given model_track.
* @param model_track The model track to look up.
* given modelTrack.
* @param modelTrack The model track to look up.
* @returns The timeline UI track found, or an empty shared_ptr if
* model_track has no corresponding timeline UI track (this is an
* modelTrack has no corresponding timeline UI track (this is an
* error condition).
**/
*/
boost::shared_ptr<timeline::Track> lookup_timeline_track(
boost::shared_ptr<model::Track> model_track) const;
boost::shared_ptr<model::Track> modelTrack) const;
// ----- Layout Functions ----- //
@ -208,7 +209,7 @@ private:
/**
* An event handler that receives notifications for when the
* sequence's track tree has been changed.
**/
*/
void on_track_list_changed();
void on_playback_period_drag_released();
@ -220,7 +221,7 @@ private:
/**
* Helper to get the sequence object from the state.
* @return Returns a shared pointer to the sequence.
**/
*/
boost::shared_ptr<model::Sequence> sequence() const;
// ----- Other Functions ----- //
@ -233,7 +234,7 @@ protected:
/**
* The state that will be used as the data source for this timeline
* widget.
**/
*/
boost::shared_ptr<timeline::TimelineState> state;
// Model Data
@ -241,10 +242,10 @@ protected:
/**
* The trackMap maps model tracks to timeline widget tracks which are
* responsible for the UI representation of a track.
* @remarks The tree structure is maintianed by the model, and as the
* @remarks The tree structure is maintained by the model, and as the
* widget is updated with update_tracks, timeline tracks are added and
* removed from the map in correspondance with the tree.
**/
* removed from the map in correspondence with the tree.
*/
std::map<boost::shared_ptr<model::Track>,
boost::shared_ptr<timeline::Track> >
trackMap;

View file

@ -0,0 +1,67 @@
/*
basic-draw-strategy.cpp - Implementation of a basic draw strategy
Copyright (C) Lumiera.org
2010, Stefan Kangas <skangas@skangas.se
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "basic-draw-strategy.hpp"
namespace gui {
namespace widgets {
namespace timeline {
BasicDrawStrategy::BasicDrawStrategy()
{ }
void
BasicDrawStrategy::draw(const Entity &entity,
Cairo::RefPtr<Cairo::Context> cr,
TimelineViewWindow* const window) const
{
REQUIRE (cr);
REQUIRE (window);
int x = window->time_to_x(entity.getBegin());
int width = window->time_to_x(
entity.getEnd()) - window->time_to_x(entity.getBegin());
// Draw a rectangle for the entity
// TODO: get height from the timeline::Entity
cr->rectangle(x, 1, width, 100-2);
// if (entity.getSelected())
cr->set_source(Cairo::SolidPattern::create_rgb (0.4, 0.4, 0.8));
// else
// cr->set_source(Cairo::SolidPattern::create_rgb (0.4, 0.4, 0.4));
cr->fill_preserve();
cr->set_source_rgb(0.25, 0.25, 0.25);
cr->stroke();
// Show the entities name
cr->rectangle(x, 1, width, 100-2);
cr->clip();
cr->move_to (x + 3, 12);
cr->set_source_rgb (1.0, 1.0, 1.0);
cr->set_font_size (9);
cr->show_text (entity.getName());
}
} // namespace timeline
} // namespace widgets
} // namespace gui

View file

@ -0,0 +1,50 @@
/*
basic-draw-strategy.hpp - Declaration of a basic draw strategy
Copyright (C) Lumiera.org
2010, Stefan Kangas <skangas@skangas.se
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file basic-draw-strategy.hpp
** Declares the Timeline Entity draw strategy class.
*/
#ifndef TIMELINE_BASIC_DRAW_STRATEGY_HPP
#define TIMELINE_BASIC_DRAW_STRATEGY_HPP
#include "draw-strategy.hpp"
namespace gui {
namespace widgets {
namespace timeline {
class BasicDrawStrategy : public DrawStrategy
{
public:
BasicDrawStrategy();
void draw(const Entity &entity,
Cairo::RefPtr<Cairo::Context> cr,
TimelineViewWindow* const window) const;
};
} // namespace timeline
} // namespace widgets
} // namespace gui
#endif // TIMELINE_BASIC_DRAW_STRATEGY_HPP

View file

@ -0,0 +1,58 @@
/*
draw-strategy.hpp - Definition the timeline draw strategy interface
Copyright (C) Lumiera.org
2010, Stefan Kangas <skangas@skangas.se
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file draw-strategy.hpp
** Declares the timeline entity drawing strategy interface.
*/
#ifndef TIMELINE_DRAW_STRATEGY_HPP
#define TIMELINE_DRAW_STRATEGY_HPP
#include "timeline-entity.hpp"
#include "timeline-view-window.hpp"
namespace gui {
namespace widgets {
namespace timeline {
/**
* An interface for drawing strategies for timeline entities.
*/
class DrawStrategy
{
protected:
DrawStrategy() { }
virtual ~DrawStrategy() { }
public:
virtual void draw(const Entity &entity,
Cairo::RefPtr<Cairo::Context> cr,
TimelineViewWindow* const window) const = 0;
};
} // namespace timeline
} // namespace widgets
} // namespace gui
#endif // TIMELINE_DRAW_STRATEGY_HPP

View file

@ -26,41 +26,75 @@ namespace gui {
namespace widgets {
namespace timeline {
ArrowTool::ArrowTool(TimelineBody &timeline_body) :
Tool(timeline_body)
{
ArrowTool::ArrowTool(TimelineBody &timelineBody) :
Tool(timelineBody)
{
}
}
ToolType
ArrowTool::get_type() const
{
return Arrow;
}
ToolType
ArrowTool::get_type() const
{
return Arrow;
}
Gdk::Cursor
ArrowTool::get_cursor() const
{
return Gdk::Cursor(Gdk::LEFT_PTR);
}
Gdk::Cursor
ArrowTool::get_cursor() const
{
return Gdk::Cursor(Gdk::LEFT_PTR);
}
void
ArrowTool::on_button_press_event(GdkEventButton* event)
{
Tool::on_button_press_event(event);
}
void
ArrowTool::on_button_press_event(GdkEventButton* event)
{
REQUIRE (event != NULL);
Tool::on_button_press_event(event);
void
ArrowTool::on_button_release_event(GdkEventButton* event)
{
Tool::on_button_release_event(event);
}
// Convert the mouse click position to a Time
boost::shared_ptr<TimelineState> state = timelineBody.getTimelineWidget().get_state();
REQUIRE(state);
const TimelineViewWindow &window = state->get_view_window();
lumiera::Time tpoint = window.x_to_time(mousePoint.get_x());
void
ArrowTool::on_motion_notify_event(GdkEventMotion *event)
{
Tool::on_motion_notify_event(event);
}
// Get the clip, if any
boost::shared_ptr<timeline::Track> track = getHoveringTrack();
boost::shared_ptr<Clip> clip = track->getClipAt(tpoint);
// Nothing to do if there is no clip
if (clip == boost::shared_ptr<Clip>())
return;
clip->setSelected(true);
}
void
ArrowTool::on_button_release_event(GdkEventButton* event)
{
REQUIRE (event != NULL);
Tool::on_button_release_event(event);
boost::shared_ptr<timeline::Track> track =
getHoveringTrack();
}
void
ArrowTool::on_motion_notify_event(GdkEventMotion *event)
{
REQUIRE (event != NULL);
Tool::on_motion_notify_event(event);
// We do not need to do anything if we are not dragging
if (!isDragging)
return;
}
boost::shared_ptr<timeline::Track>
ArrowTool::getHoveringTrack ()
{
boost::shared_ptr<timeline::Track> track(
timelineBody.getTimelineWidget().get_hovering_track());
return track;
}
} // namespace timeline
} // namespace widgets

View file

@ -27,52 +27,63 @@
#define TIMELINE_ARROW_TOOL_HPP
#include <gtkmm.h>
#include "timeline-tool.hpp"
#include "gui/widgets/timeline-widget.hpp"
#include "timeline-body.hpp"
#include "timeline-track.hpp"
namespace gui {
namespace widgets {
namespace timeline {
/**
* A helper class to implement the timeline i-beam tool
*/
class ArrowTool : public Tool
{
public:
/**
* Constructor
* @param timeline_body The owner timeline body object
* A helper class to implement the timeline arrow tool
*/
ArrowTool(TimelineBody &timeline_body);
class ArrowTool : public Tool
{
public:
/**
* Constructor
* @param timelineBody The owner timeline body object
*/
ArrowTool(TimelineBody &timelineBody);
/**
* Gets the type of tool represented by this class
*/
ToolType get_type() const;
/**
* Gets the type of tool represented by this class
*/
ToolType get_type() const;
protected:
protected:
/**
* Gets the cursor to display for this tool at this moment.
*/
Gdk::Cursor get_cursor() const;
/**
* Gets the cursor to display for this tool at this moment.
*/
Gdk::Cursor get_cursor() const;
protected:
/**
* The event handler for button press events.
*/
void on_button_press_event(GdkEventButton* event);
/**
* The event handler for button press events.
*/
void on_button_press_event(GdkEventButton* event);
/**
* The event handler for button release events.
*/
void on_button_release_event(GdkEventButton* event);
/**
* The event handler for button release events.
*/
void on_button_release_event(GdkEventButton* event);
/**
* The event handler for mouse move events.
*/
void on_motion_notify_event(GdkEventMotion *event);
};
/**
* The event handler for mouse move events.
*/
void on_motion_notify_event(GdkEventMotion *event);
private:
boost::shared_ptr<timeline::Track>
getHoveringTrack ();
bool selectionRectangleActive;
};
} // namespace timeline
} // namespace widgets

View file

@ -20,7 +20,7 @@
* *****************************************************/
#include <cairomm-1.0/cairomm/cairomm.h>
#include <cairomm/cairomm.h>
#include <boost/foreach.hpp>
#include "timeline-body.hpp"
@ -43,7 +43,7 @@ namespace gui {
namespace widgets {
namespace timeline {
TimelineBody::TimelineBody(TimelineWidget &timeline_widget) :
TimelineBody::TimelineBody(TimelineWidget &timelineWidget) :
Glib::ObjectBase("TimelineBody"),
tool(NULL),
mouseDownX(0),
@ -51,10 +51,10 @@ TimelineBody::TimelineBody(TimelineWidget &timeline_widget) :
dragType(None),
beginShiftTimeOffset(0),
selectionAlpha(0.5),
timelineWidget(timeline_widget)
timelineWidget(timelineWidget)
{
// Connect up some events
timeline_widget.state_changed_signal().connect(
timelineWidget.state_changed_signal().connect(
sigc::mem_fun(this, &TimelineBody::on_state_changed) );
// Install style properties
@ -69,6 +69,12 @@ TimelineBody::~TimelineBody()
WARN_IF(!tool, gui, "An invalid tool pointer is unexpected here");
}
TimelineWidget&
TimelineBody::getTimelineWidget () const
{
return timelineWidget;
}
ToolType
TimelineBody::get_tool() const
{
@ -274,12 +280,12 @@ TimelineBody::on_motion_notify_event(GdkEventMotion *event)
// Forward the event to the tool
tool->on_motion_notify_event(event);
// See if the track that we're hovering over has changed
shared_ptr<timeline::Track> new_hovering_track(
shared_ptr<timeline::Track> newHoveringTrack(
timelineWidget.layoutHelper.track_from_y(event->y));
if(timelineWidget.get_hovering_track() != new_hovering_track)
timelineWidget.set_hovering_track(new_hovering_track);
if (timelineWidget.get_hovering_track() != newHoveringTrack)
timelineWidget.set_hovering_track(newHoveringTrack);
}
// false so that the message is passed up to the owner TimelineWidget
@ -324,7 +330,7 @@ TimelineBody::draw_tracks(Cairo::RefPtr<Cairo::Context> cr)
iterator != layout_tree.end();
iterator++)
{
const shared_ptr<model::Track> model_track(*iterator);
// const shared_ptr<model::Track> modelTrack(*iterator);
const shared_ptr<timeline::Track> timeline_track =
timelineWidget.lookup_timeline_track(*iterator);
@ -507,7 +513,7 @@ TimelineBody::register_styles() const
"The colour of the playback marker line",
GDK_TYPE_COLOR, G_PARAM_READABLE));
}
void
TimelineBody::read_styles()
{

View file

@ -29,6 +29,8 @@
#include "gui/gtk-lumiera.hpp"
#include "timeline-tool.hpp"
#include <boost/scoped_ptr.hpp>
namespace gui {
namespace model {
@ -65,16 +67,21 @@ public:
*/
~TimelineBody();
TimelineWidget&
getTimelineWidget () const;
/**
* Returns the type of the currently selected timeline tool.
*/
ToolType get_tool() const;
ToolType
get_tool() const;
/**
* Selects a tool of a specified type.
* @param tool_type The type of tool to set.
*/
void set_tool(ToolType tool_type);
void
set_tool(ToolType tool_type);
/* ===== Events ===== */
protected:
@ -114,7 +121,7 @@ protected:
/**
* The event handler for when the TimelineWidget's state object is
* replaced.
**/
*/
void on_state_changed();
/* ===== Internals ===== */
@ -152,7 +159,7 @@ private:
* A helper function to get the view window
* @remarks This function must not be called unless the TimlineWidget
* has a valid state.
**/
*/
TimelineViewWindow& view_window() const;
/**

View file

@ -27,46 +27,135 @@
#include "timeline-view-window.hpp"
using namespace Gtk;
using boost::dynamic_pointer_cast;
using boost::shared_ptr;
using util::contains;
namespace gui {
namespace widgets {
namespace timeline {
ClipTrack::ClipTrack(TimelineWidget &timeline_widget,
boost::shared_ptr<model::Track> track) :
Track(timeline_widget, track)
{
// TEST CODE: add a clip to the track
boost::shared_ptr<model::Clip> model_clip(new model::Clip());
boost::shared_ptr<timeline::Clip> timeline_clip(new timeline::Clip(model_clip));
clips.push_back(timeline_clip);
// END TEST CODE
}
ClipTrack::ClipTrack (TimelineWidget &timelineWidget,
shared_ptr<model::ClipTrack> track) :
Track(timelineWidget, track)
{
REQUIRE (track);
void
ClipTrack::draw_track(Cairo::RefPtr<Cairo::Context> cairo,
// Connect signals
track->getClipList().signal_changed().connect(
sigc::mem_fun(this, &ClipTrack::onClipListChanged));
updateClips();
}
void
ClipTrack::draw_track (
Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const
{
REQUIRE(cairo);
REQUIRE(window);
{
REQUIRE (cairo);
REQUIRE (window);
// Draw a rectangle to let us know it works? :-)
cairo->rectangle(window->time_to_x(0), 1,
window->time_to_x(500000) - window->time_to_x(0),
get_height() - 2);
cairo->set_source_rgb(0.5, 0.5, 0.5);
cairo->fill_preserve();
cairo->set_source_rgb(0.25, 0.25, 0.25);
cairo->stroke();
// Draw a rectangle to let us know it works? :-)
cairo->rectangle(window->time_to_x(0), 1,
window->time_to_x(500000) - window->time_to_x(0),
get_height() - 2);
// Draw all clips
BOOST_FOREACH(boost::shared_ptr<timeline::Clip> c, clips)
{
c->draw_clip(cairo, window);
}
}
cairo->set_source_rgb(0.5, 0.5, 0.5);
cairo->fill_preserve();
cairo->set_source_rgb(0.25, 0.25, 0.25);
cairo->stroke();
// Draw all clips
std::pair<shared_ptr<model::Clip>, shared_ptr<timeline::Clip> >
pair;
BOOST_FOREACH (pair, clipMap)
{
pair.second->draw(cairo, window);
}
}
boost::shared_ptr<timeline::Clip>
ClipTrack::getClipAt(lumiera::Time position) const
{
std::pair<shared_ptr<model::Clip>, shared_ptr<timeline::Clip> >
pair;
BOOST_FOREACH (pair, clipMap)
{
if (pair.first->isPlayingAt(position))
return pair.second;
}
// Nothing found
return boost::shared_ptr<timeline::Clip>();
}
//// private methods
void
ClipTrack::createTimelineClips()
{
// Share the draw strategy between all objects
// TODO: use factory/builder here
static boost::shared_ptr<timeline::DrawStrategy> drawStrategy(new BasicDrawStrategy());
BOOST_FOREACH (shared_ptr<model::Clip> modelClip, getModelTrack()->getClipList())
{
// Is a timeline UI clip present in the map already?
if (!contains (clipMap, modelClip))
{
// The timeline UI clip is not present
// We will need to create one
clipMap[modelClip] = shared_ptr<timeline::Clip>(
new timeline::Clip (modelClip, drawStrategy));
}
}
}
shared_ptr<model::ClipTrack>
ClipTrack::getModelTrack ()
{
return dynamic_pointer_cast<model::ClipTrack>(modelTrack);
}
void
ClipTrack::onClipListChanged ()
{
updateClips ();
}
void
ClipTrack::removeOrphanedClips ()
{
std::map< shared_ptr<model::Clip>,
shared_ptr<timeline::Clip> >
orphanClipMap (clipMap);
// Remove all clips which are still present in the sequence
BOOST_FOREACH (shared_ptr<model::Clip> modelClip, getModelTrack()->getClipList())
if (contains (orphanClipMap, modelClip))
orphanClipMap.erase(modelClip);
// orphanClipMap now contains all the orphaned clips
// Remove them
std::pair< shared_ptr<model::Clip>, shared_ptr<timeline::Clip> >
pair;
BOOST_FOREACH (pair, orphanClipMap)
{
ENSURE (pair.first);
clipMap.erase (pair.first);
}
}
void
ClipTrack::updateClips()
{
// Remove any clips which are no longer present in the model
removeOrphanedClips ();
// Create timeline clips from all the model clips
createTimelineClips ();
}
} // namespace timeline
} // namespace widgets

View file

@ -30,6 +30,7 @@
#include <vector>
#include "basic-draw-strategy.hpp"
#include "timeline-track.hpp"
#include "gui/model/clip-track.hpp"
@ -37,21 +38,75 @@ namespace gui {
namespace widgets {
namespace timeline {
class Clip;
class TimelineViewWindow;
class Clip;
class TimelineViewWindow;
class ClipTrack : public timeline::Track
{
public:
ClipTrack(TimelineWidget &timeline_widget,
boost::shared_ptr<model::Track> track);
class ClipTrack : public timeline::Track
{
public:
/**
* Constructor.
*/
ClipTrack(TimelineWidget &timelineWidget,
boost::shared_ptr<model::ClipTrack> track);
void draw_track(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const;
/**
* Draw the track in the timeline.
*/
void
draw_track(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const;
private:
std::vector<boost::shared_ptr<timeline::Clip> > clips;
};
/**
* Gets the clip that is occupying the given time. If there is no track, return a NULL
* pointer.
* @param the given time
*/
boost::shared_ptr<timeline::Clip>
getClipAt(lumiera::Time position) const;
private:
/**
* Ensures timeline UI clips have been created for every model clip in track.
*/
void
createTimelineClips();
/**
* Gets the modelTrack as a ClipTrack.
*/
boost::shared_ptr<model::ClipTrack>
getModelTrack ();
/**
* An event handler that receives notifications for when the models clip list has been
* changed.
*/
void
onClipListChanged();
/**
* Removes any UI clips which no longer have corresponding model clips present in the
* sequence.
*/
void
removeOrphanedClips();
/**
* Update the attached timeline clips.
*/
void
updateClips();
/**
* The clipMap maps model clips to timeline widget clips which are responsible for the
* UI representation of a clip.
*/
std::map<boost::shared_ptr<model::Clip>,
boost::shared_ptr<timeline::Clip> >
clipMap;
};
} // namespace timeline
} // namespace widgets

View file

@ -1,6 +1,6 @@
/*
timeline-clip.cpp - Implementation of the timeline clip object
Copyright (C) Lumiera.org
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
@ -26,46 +26,45 @@ namespace gui {
namespace widgets {
namespace timeline {
Clip::Clip(boost::shared_ptr<model::Clip> clip)
: model_clip(clip)
{
REQUIRE(model_clip);
}
Clip::Clip(boost::shared_ptr<model::Clip> clip,
boost::shared_ptr<timeline::DrawStrategy> drawStrategy)
: Entity(drawStrategy),
modelClip(clip),
selected(false)
{
REQUIRE(modelClip);
void
Clip::draw_clip(Cairo::RefPtr<Cairo::Context> cr,
TimelineViewWindow* const window) const
{
REQUIRE(cr);
REQUIRE(window);
// TODO: Connect signals
//modelClip->signalNameChanged().connect(mem_fun(this,
// &Clip::onNameChanged);
}
int x = window->time_to_x(1000000);
int width = window->time_to_x(2000000) - window->time_to_x(1000000);
// Draw a rectangle for the clip
cr->rectangle(x, 1, width, 100-2);
gavl_time_t
Clip::getBegin () const
{
REQUIRE (modelClip);
return modelClip->getBegin();
}
// TODO: get duration from the model::Clip
// TODO: get height from the Timeline::Track
gavl_time_t
Clip::getEnd () const
{
REQUIRE (modelClip);
return modelClip->getEnd();
}
cr->set_source_rgb(0.4, 0.4, 0.4);
cr->fill_preserve();
cr->set_source_rgb(0.25, 0.25, 0.25);
cr->stroke();
std::string
Clip::getName () const
{
REQUIRE (modelClip);
return modelClip->getName();
}
// Show the clip name
cr->rectangle(x, 1, width, 100-2);
cr->clip();
cr->move_to (x + 3, 12);
cr->set_source_rgb (1.0, 1.0, 1.0);
cr->set_font_size (9);
cr->show_text ("Clip Name"); // TODO: get clip name from model
// TODO: Show thumbnails for clip
}
void
Clip::setSelected(bool selected)
{
this->selected = selected;
}
} // namespace timeline

View file

@ -22,13 +22,14 @@
/** @file widgets/timeline/timeline-clip.hpp
** This file contains the definition of timeline clip object
*/
#include "gui/gtk-lumiera.hpp"
#include "gui/model/clip.hpp"
#include "timeline-view-window.hpp"
#include "include/logging.h"
#include "draw-strategy.hpp"
#include "timeline-entity.hpp"
#ifndef TIMELINE_CLIP_HPP
#define TIMELINE_CLIP_HPP
@ -36,18 +37,36 @@ namespace gui {
namespace widgets {
namespace timeline {
class Clip : public model::Clip
{
public:
Clip(boost::shared_ptr<model::Clip> clip);
class Clip : public Entity
{
public:
Clip(boost::shared_ptr<model::Clip> clip,
boost::shared_ptr<timeline::DrawStrategy> drawStrategy);
void draw_clip(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const;
gavl_time_t
getBegin () const;
private:
gavl_time_t
getEnd () const;
boost::shared_ptr<model::Clip> model_clip;
};
std::string
getName () const;
/**
* Sets the selected status of the clip.
*/
void
setSelected (bool state);
private:
boost::shared_ptr<model::Clip> modelClip;
/**
* True when this clip is selected in the GUI.
*/
bool selected;
};
} // namespace timeline
} // namespace widgets

View file

@ -0,0 +1,67 @@
/*
timeline-entity.cpp - Implementation of the timeline entity object
Copyright (C) Lumiera.org
2010, Stefan Kangas <skangas@skangas.se
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "timeline-entity.hpp"
#include "draw-strategy.hpp"
#include "gui/gtk-lumiera.hpp"
#include "include/logging.h"
namespace gui {
namespace widgets {
namespace timeline {
Entity::Entity(boost::shared_ptr<timeline::DrawStrategy> drawStrategy)
: enabled(true),
drawStrategy(drawStrategy)
{ }
Entity::~Entity()
{ }
void
Entity::draw(Cairo::RefPtr<Cairo::Context> cr,
TimelineViewWindow* const window) const
{
REQUIRE (cr);
REQUIRE (window);
drawStrategy->draw(*this, cr, window);
}
bool
Entity::getEnabled () const
{
return enabled;
}
void
Entity::setEnabled (bool enabled)
{
this->enabled = enabled;
}
} // namespace timeline
} // namespace widgets
} // namespace gui

View file

@ -0,0 +1,90 @@
/*
timeline-entity.hpp - Declaration of the timeline entity class
Copyright (C) Lumiera.org
2010, Stefan Kangas <skangas@skangas.se>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file timeline-entity.hpp
** Declares the Timeline Entity class.
*/
#ifndef TIMELINE_ENTITY_HPP
#define TIMELINE_ENTITY_HPP
#include <string>
// TODO: Remove once we get better measure of duration.
extern "C" {
#include <stdint.h>
#include <gavl/gavltime.h>
}
#include <boost/shared_ptr.hpp>
#include <cairomm/cairomm.h>
namespace gui {
namespace widgets {
namespace timeline {
class DrawStrategy;
class TimelineViewWindow;
/**
* Base class for timeline entities.
* Everything that can be placed on the timeline is a timeline Entity.
*/
class Entity {
protected:
Entity(boost::shared_ptr<timeline::DrawStrategy> drawStrategy);
virtual ~Entity();
public:
virtual gavl_time_t
getBegin () const = 0;
virtual void
draw(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const;
bool
getEnabled () const;
virtual gavl_time_t
getEnd () const = 0;
virtual std::string
getName () const = 0;
void
setEnabled(bool selected);
private:
bool enabled;
boost::shared_ptr<timeline::DrawStrategy> drawStrategy;
};
} // namespace timeline
} // namespace widgets
} // namespace gui
#endif // TIMELINE_ENTITY_HPP

View file

@ -35,7 +35,7 @@ GroupTrack::GroupTrack(TimelineWidget &timeline_widget,
shared_ptr<model::GroupTrack> track) :
Track(timeline_widget, track)
{
REQUIRE(track);
REQUIRE (track);
// Receive notifications of changes to the tracks
track->get_child_track_list().signal_changed().connect(

View file

@ -425,12 +425,12 @@ TimelineHeaderContainer::layout_headers()
shared_ptr<timeline::Track>
TimelineHeaderContainer::lookup_timeline_track(
shared_ptr<model::Track> model_track)
shared_ptr<model::Track> modelTrack)
{
REQUIRE(model_track != NULL);
REQUIRE(modelTrack != NULL);
shared_ptr<timeline::Track> timeline_track =
timelineWidget.lookup_timeline_track(model_track);
timelineWidget.lookup_timeline_track(modelTrack);
ENSURE(timeline_track);
return timeline_track;

View file

@ -119,14 +119,14 @@ private:
/**
* Applies a given function to all the widgets in the container.
**/
*/
void forall_vfunc(gboolean include_internals, GtkCallback callback,
gpointer callback_data);
/**
* An event handler that is called when a widget is removed from the
* container.
**/
*/
void on_remove(Widget* widget);
/* ===== Events ===== */
@ -162,28 +162,28 @@ private:
/**
* Draws the border decoration around the track header.
* @param model_track The track to draw the decoration for.
* @param modelTrack The track to draw the decoration for.
* @param clip_rect The clip to drawing to.
* @param depth The depth within the tree of this track. This is used
* to control the amount of indention.
* @param offset The vertical offset of the headers in pixels.
**/
*/
void draw_header_decoration(
boost::shared_ptr<model::Track> model_track,
boost::shared_ptr<model::Track> modelTrack,
const Gdk::Rectangle &clip_rect);
/**
* A helper function which calls lookup_timeline_track within the
* parent timeline widget, but also applies lots of data consistency
* checks in the process.
* @param model_track The model track to look up in the parent widget.
* @param modelTrack The model track to look up in the parent widget.
* @return Returns the track found, or returns NULL if no matching
* track was found.
* @remarks If the return value is going to be NULL, an ENSURE will
* fail.
**/
*/
boost::shared_ptr<timeline::Track> lookup_timeline_track(
boost::shared_ptr<model::Track> model_track);
boost::shared_ptr<model::Track> modelTrack);
void begin_drag();
@ -194,7 +194,7 @@ private:
* top of the Z-order.
* @param node The window of node's track header will be raised, as
* well as all it's descendant nodes.
**/
*/
void raise_recursive(
TimelineLayoutHelper::TrackTree::iterator_base node);
@ -230,7 +230,7 @@ private:
* the user right clicks on the header container.
* @remarks The context menu will be displayed when the user's right
* click is not processed by track headers.
**/
*/
Gtk::Menu contextMenu;
/**

View file

@ -160,8 +160,8 @@ TimelineHeaderWidget::on_expose_event(GdkEventExpose *event)
REQUIRE(style);
REQUIRE(gdkWindow);
shared_ptr<model::Track> model_track = track.get_model_track();
REQUIRE(model_track);
shared_ptr<model::Track> modelTrack = track.getModelTrack();
REQUIRE(modelTrack);
// Get the header box
const Gdk::Rectangle allocation = get_allocation();
@ -181,7 +181,7 @@ TimelineHeaderWidget::on_expose_event(GdkEventExpose *event)
else if(hoveringExpander)
state_type = STATE_PRELIGHT;
if(!model_track->get_child_tracks().empty())
if(!modelTrack->get_child_tracks().empty())
style->paint_expander (gdkWindow,
state_type,
box, *this, "",

View file

@ -38,7 +38,7 @@ class Track;
/**
* TimelineHeaderWidget is the base implementation of all header widgets
* and acts as a containers for the header controls.
**/
*/
class TimelineHeaderWidget : public Gtk::Container
{
public:
@ -46,7 +46,7 @@ public:
* Constructor
* @param timeline_track The timeline track that owns this header
* widget
**/
*/
TimelineHeaderWidget(timeline::Track &timeline_track);
void set_child_widget(Widget& child);
@ -103,24 +103,24 @@ private:
/**
* Applies a given function to all the widgets in the container.
**/
*/
void forall_vfunc(gboolean include_internals, GtkCallback callback,
gpointer callback_data);
/**
* A notification of when a widget is added to this container.
**/
*/
void on_add(Gtk::Widget* child);
/**
* A notification of when a widget is removed to this container.
**/
*/
void on_remove(Gtk::Widget* child);
/**
* An implementation of the a container function that specifies the
* types of child widget that this widget will accept.
**/
*/
GtkType child_type_vfunc() const;
/**
@ -137,19 +137,19 @@ private:
/**
* A reference to the timeline track that owns this widget.
**/
*/
timeline::Track &track;
/**
* The widget placed inside this container.
* @remarks This value is set to NULL if the container is empty
**/
*/
Gtk::Widget* widget;
/**
* This value is true if the mouse hovering over the expander.
* @remarks This value is updated by on_motion_notify_event
**/
*/
bool hoveringExpander;
/**
@ -157,12 +157,12 @@ private:
* expander.
* @remarks This value is updated by on_button_press_event and
* on_button_release_event
**/
*/
bool clickedExpander;
/**
* The widget's window object.
**/
*/
Glib::RefPtr<Gdk::Window> gdkWindow;
//----- Style Values -----//
@ -170,13 +170,13 @@ private:
/**
* The style value which indicates the amount of padding around each
* header pixels.
**/
*/
int margin;
/**
* The style value which indicates the size to draw the expand button
* in pixels.
**/
*/
int expand_button_size;
};

View file

@ -149,9 +149,9 @@ TimelineLayoutHelper::begin_dragging_track(
dragPoint.get_x() - rect.get_x(),
dragPoint.get_y() - rect.get_y());
const shared_ptr<model::Track> model_track =
dragging_track->get_model_track();
draggingTrackIter = iterator_from_track(model_track);
const shared_ptr<model::Track> modelTrack =
dragging_track->getModelTrack();
draggingTrackIter = iterator_from_track(modelTrack);
dragBranchHeight = measure_branch_height(draggingTrackIter);
dropPoint.relation = None;
@ -163,7 +163,7 @@ void
TimelineLayoutHelper::end_dragging_track(bool apply)
{
if(apply)
apply_drop_to_model_tree(dropPoint);
apply_drop_to_modelTree(dropPoint);
draggingTrackIter.node = NULL;
clone_tree_from_sequence();
@ -300,14 +300,14 @@ TimelineLayoutHelper::is_animating() const
TimelineLayoutHelper::TrackTree::pre_order_iterator
TimelineLayoutHelper::iterator_from_track(
boost::shared_ptr<model::Track> model_track)
boost::shared_ptr<model::Track> modelTrack)
{
REQUIRE(model_track);
REQUIRE(modelTrack);
TrackTree::pre_order_iterator iter;
for(iter = layoutTree.begin(); iter != layoutTree.end(); iter++)
{
if(*iter == model_track)
if(*iter == modelTrack)
break;
}
@ -384,15 +384,15 @@ TimelineLayoutHelper::layout_headers_recursive(
Gdk::Rectangle rect;
int track_height = 0;
const shared_ptr<model::Track> &model_track = *iterator;
REQUIRE(model_track);
const shared_ptr<model::Track> &modelTrack = *iterator;
REQUIRE(modelTrack);
shared_ptr<timeline::Track> timeline_track =
lookup_timeline_track(model_track);
lookup_timeline_track(modelTrack);
// Is this the root track of a dragging branch?
bool being_dragged = false;
if(dragging)
being_dragged = (model_track == *draggingTrackIter);
being_dragged = (modelTrack == *draggingTrackIter);
// Is the track going to be shown?
if(parent_expanded)
@ -473,11 +473,11 @@ TimelineLayoutHelper::layout_headers_recursive(
shared_ptr<timeline::Track>
TimelineLayoutHelper::lookup_timeline_track(
shared_ptr<model::Track> model_track)
shared_ptr<model::Track> modelTrack)
{
REQUIRE(model_track != NULL);
REQUIRE(modelTrack != NULL);
shared_ptr<timeline::Track> timeline_track =
timelineWidget.lookup_timeline_track(model_track);
timelineWidget.lookup_timeline_track(modelTrack);
ENSURE(timeline_track);
return timeline_track;
@ -503,10 +503,10 @@ TimelineLayoutHelper::attempt_drop(TrackTree::pre_order_iterator target,
const Gdk::Point &point)
{
// Lookup the tracks
const shared_ptr<model::Track> model_track(*target);
REQUIRE(model_track);
const shared_ptr<model::Track> modelTrack(*target);
REQUIRE(modelTrack);
const weak_ptr<timeline::Track> timeline_track =
lookup_timeline_track(model_track);
lookup_timeline_track(modelTrack);
// Calculate coordinates
const Gdk::Rectangle &rect = headerBoxes[timeline_track];
@ -530,9 +530,9 @@ TimelineLayoutHelper::attempt_drop(TrackTree::pre_order_iterator target,
full_width, half_height)))
{
// We're hovering over the lower half of the header
if(model_track->can_host_children())
if(modelTrack->can_host_children())
{
if(model_track->get_child_tracks().empty())
if(modelTrack->get_child_tracks().empty())
{
// Is our track being dragged after this header?
if(dragPoint.get_x() < x_mid)
@ -596,7 +596,7 @@ TimelineLayoutHelper::apply_drop_to_layout_tree(
}
void
TimelineLayoutHelper::apply_drop_to_model_tree(
TimelineLayoutHelper::apply_drop_to_modelTree(
const TimelineLayoutHelper::DropPoint &drop)
{
const shared_ptr<model::Sequence> sequence = get_sequence();

View file

@ -21,7 +21,7 @@
*/
/** @file timeline-layout-helper.cpp
** This file contains the definition of the layout helpeer class
** This file contains the definition of the layout helper class
*/
#ifndef TIMELINE_LAYOUT_HELPER_HPP
@ -30,6 +30,8 @@
#include "gui/gtk-lumiera.hpp"
#include "lib/tree.hpp"
#include <boost/optional.hpp>
namespace gui {
namespace model {
@ -56,7 +58,7 @@ class TimelineLayoutHelper : public boost::noncopyable
public:
/**
* Definition of the layout track tree type.
**/
*/
typedef lumiera::tree< boost::shared_ptr<model::Track> > TrackTree;
public:
@ -64,7 +66,7 @@ public:
* Constructor.
* @param owner The timeline widget which is the owner of this helper
* class.
**/
*/
TimelineLayoutHelper(TimelineWidget &owner);
/**
@ -73,19 +75,19 @@ public:
* @remarks The current layout tree will be deleted and replaced with
* the clone.
* @see add_branch
**/
*/
void clone_tree_from_sequence();
/**
* Gets a reference to the helper's layout tree.
* @return Returns a reference to the helper's layout tree.
**/
*/
TrackTree& get_layout_tree();
/**
* Recalculates the track layout from layoutTree.
* @see layout_headers_recursive
**/
*/
void update_layout();
/**
@ -97,7 +99,7 @@ public:
* @remarks This function is only usable after update_layout() has
* been called on a valid tree of tracks.
* @see update_layout()
**/
*/
boost::optional<Gdk::Rectangle> get_track_header_rect(
boost::weak_ptr<timeline::Track> track);
@ -111,7 +113,7 @@ public:
* usable after update_layout() has been called on a valid tree of
* tracks.
* @see update_layout()
**/
*/
boost::shared_ptr<timeline::Track> header_from_point(
Gdk::Point point);
@ -125,31 +127,31 @@ public:
* usable after update_layout() has been called on a valid tree of
* tracks.
* @see update_layout()
**/
*/
boost::shared_ptr<timeline::Track> track_from_y(int y);
/**
* Begins to drag the track under mouse_point, if there is one.
* @param mouse_point The mouse point to begin dragging from, measured
* in pixels from the top left of the header container widget.
**/
*/
boost::shared_ptr<timeline::Track>
begin_dragging_track(const Gdk::Point &mouse_point);
/**
* Drops the dragging track.
* @param apply true if the model tree should be modified.
**/
*/
void end_dragging_track(bool apply);
/**
* Returns true if a track is being dragged.
**/
*/
bool is_dragging_track() const;
/**
* Gets the iterator of the layout tree node that is being dragged.
**/
*/
TrackTree::pre_order_iterator get_dragging_track_iter() const;
/**
@ -160,7 +162,7 @@ public:
* @remarks drag_to_point may only be called after
* begin_dragging_track and before end_dragging_point have been
* called.
**/
*/
void drag_to_point(const Gdk::Point &mouse_point);
/**
@ -168,23 +170,23 @@ public:
* @remarks This function is only on returns a valid value fter
* update_layout() has been called on a valid tree of tracks.
* @see update_layout()
**/
*/
int get_total_height() const;
/**
* Returns true if the layout is currently animating.
**/
*/
bool is_animating() const;
/**
* A utility function which finds the iterator of a track in the
* layout tree.
* @param model_track The model track to look for.
* @param modelTrack The model track to look for.
* @return Returns the model iterator of layoutTree.end() if no
* iterator was found.
**/
*/
TrackTree::pre_order_iterator iterator_from_track(
boost::shared_ptr<model::Track> model_track);
boost::shared_ptr<model::Track> modelTrack);
/**
* A function that recursively calculates the visible height of a
@ -192,7 +194,7 @@ public:
* @param parent_iterator The parent of the branch to measure. This
* node and all the child nodes will be included in the measurement.
* @return Returns the height of the branch in pixels.
**/
*/
int measure_branch_height(TrackTree::iterator_base parent_iterator);
protected:
@ -200,50 +202,50 @@ protected:
/**
* An enum to specify the relationship between a tree node, and
* another node which is going to be inserted adjacent.
**/
*/
enum TreeRelation
{
/**
* No relation
**/
*/
None,
/**
* The node will be inserted immediately before this one.
**/
*/
Before,
/**
* The node will be inserted immediately after this one.
**/
*/
After,
/**
* The node will be inserted as the first child of this one.
**/
*/
FirstChild,
/**
* The node will be inserted as the last child of this one.
**/
*/
LastChild
};
/**
* A structure used to specify where a track will be dropped when
* dragging ends.
**/
*/
struct DropPoint
{
/**
* Specifies the target node onto which the dragging track will be
* dropped.
**/
*/
TrackTree::pre_order_iterator target;
/**
* The where to drop the dragging track in relation to target.
**/
*/
TreeRelation relation;
};
@ -258,7 +260,7 @@ protected:
* @param[in] parent A pointer to the model track whose children
* will be added to the layout tree branch.
* @see clone_tree_from_sequence()
**/
*/
void add_branch(TrackTree::iterator_base parent_iterator,
boost::shared_ptr<model::Track> parent);
@ -280,7 +282,7 @@ protected:
* false if any of them are collapsed.
* @return Returns the height of the branch in pixels.
* @see update_layout()
**/
*/
int layout_headers_recursive(
TrackTree::iterator_base parent_iterator, const int branch_offset,
const int header_width, const int indent_width, const int depth,
@ -290,23 +292,23 @@ protected:
* A helper function which calls lookup_timeline_track within the
* parent timeline widget, but also applies lots of data consistency
* checks in the process.
* @param model_track The model track to look up in the parent widget.
* @param modelTrack The model track to look up in the parent widget.
* @return Returns the track found, or returns NULL if no matching
* track was found.
* @remarks If the return value is going to be NULL, an ENSURE will
* fail.
**/
*/
boost::shared_ptr<timeline::Track> lookup_timeline_track(
boost::shared_ptr<model::Track> model_track);
boost::shared_ptr<model::Track> modelTrack);
/**
* A helper function which kicks off the animation timer.
**/
*/
void begin_animation();
/**
* The animation timer tick callback.
**/
*/
bool on_animation_tick();
/**
@ -318,7 +320,7 @@ protected:
* point is hovering over it, and if it is, it works out what part of
* the header, and therefore what drop location the user us gesturally
* pointing to.
**/
*/
TimelineLayoutHelper::DropPoint
attempt_drop(TrackTree::pre_order_iterator target,
const Gdk::Point &point);
@ -327,31 +329,31 @@ protected:
* Drops the dragging track to a new location in the layout tree as
* specified by drop.
* @param[in] drop The point in the tree to drop onto.
**/
*/
void apply_drop_to_layout_tree(const DropPoint &drop);
/**
* Drops the dragging track to a new location in the model tree as
* specified by drop.
* @param[in] drop The point in the tree to drop onto.
**/
void apply_drop_to_model_tree(const DropPoint &drop);
*/
void apply_drop_to_modelTree(const DropPoint &drop);
/**
* Helper to get the sequence object from the state.
* @return Returns a shared pointer to the sequence.
**/
*/
boost::shared_ptr<model::Sequence> get_sequence() const;
protected:
/**
* The owner timeline widget as provided to the constructor.
**/
*/
TimelineWidget &timelineWidget;
/**
* The layout tree.
**/
*/
TrackTree layoutTree;
/**
@ -360,7 +362,7 @@ protected:
* need to be perpetually recalculated. This cache is regenerated by
* the update_layout method.
* @see update_layout()
**/
*/
std::map<boost::weak_ptr<timeline::Track>, Gdk::Rectangle>
headerBoxes;
@ -368,7 +370,7 @@ protected:
* The total height of the track tree layout in pixels. This value
* is only valid after layout_headers has been called.
* @see update_layout()
**/
*/
int totalHeight;
/**
@ -376,13 +378,13 @@ protected:
* dragged.
* @remarks draggingTrackIter.node is set to NULL when no drag is
* taking place.
**/
*/
TrackTree::pre_order_iterator draggingTrackIter;
/**
* The offset of the mouse relative to the top-left corner of the
* dragging track.
**/
*/
Gdk::Point dragStartOffset;
/**
@ -390,26 +392,26 @@ protected:
* top left of the whole layout.
* @remarks This value is changed by begin_dragging_track and
* drag_to_point
**/
*/
Gdk::Point dragPoint;
/**
* The total height of the dragging branch in pixels.
* @remarks This value is updated by begin_dragging_track
**/
*/
int dragBranchHeight;
/**
* The tree point the the user is currently hovering on.
* @remarks This value is updated by drag_to_point.
**/
*/
DropPoint dropPoint;
/**
* The connection to the animation timer.
* @see begin_animation()
* @see on_animation_tick()
**/
*/
sigc::connection animationTimer;
/**
@ -417,7 +419,7 @@ protected:
* @remarks This value is recalculated by update_layout()
* @see update_layout()
* @see on_animation_tick()
**/
*/
bool animating;
};

View file

@ -20,16 +20,15 @@
* *****************************************************/
#include <cairomm-1.0/cairomm/cairomm.h>
#include <cairomm/cairomm.h>
#include "timeline-ruler.hpp"
#include "gui/widgets/timeline-widget.hpp"
#include "gui/window-manager.hpp"
#include "gui/util/cairo-util.hpp"
extern "C" {
#include "lib/time.h"
}
using namespace Gtk;
using namespace Cairo;

View file

@ -109,7 +109,7 @@ private:
/**
* The event handler for when the TimelineWidget's state object is
* replaced.
**/
*/
void on_state_changed();
private:
@ -170,7 +170,7 @@ private:
/**
* A helper function to get the view window
**/
*/
TimelineViewWindow& view_window() const;
/**

View file

@ -41,7 +41,7 @@ namespace timeline {
* TimelineState is a container for the state data for TimelineWidget.
* @remarks TimelineState s can be swapped out so that TimelineWidget
* can flip between different views.
**/
*/
class TimelineState
{
public:
@ -50,7 +50,7 @@ public:
* Constructor
* @param source_sequence The sequence on which the TimelineWidget
* will operate when this TimelineState is attached.
**/
*/
TimelineState(boost::shared_ptr<model::Sequence> source_sequence);
public:
@ -58,13 +58,13 @@ public:
/**
* Gets the sequence that is attached to this timeline state object.
* @return Returns a shared_ptr to the sequence object.
**/
*/
boost::shared_ptr<model::Sequence> get_sequence() const;
/**
* Gets a reference to the timeline view window object.
* @return Returns the timeline view window object.
**/
*/
timeline::TimelineViewWindow& get_view_window();
/**
@ -120,13 +120,13 @@ public:
/**
* A signal to notify when the selected period has changed.
**/
*/
sigc::signal<void> selection_changed_signal() const;
/**
* A signal to notify when the playback point or playback periods have
* changed.
**/
*/
sigc::signal<void> playback_changed_signal() const;
private:
@ -136,53 +136,53 @@ private:
* represent.
* @remarks This pointer is set by the constructor and is constant, so
* will not change in value during the lifetime of the class.
**/
*/
boost::shared_ptr<model::Sequence> sequence;
// View State
/**
* The ViewWindow for the TimelineWidget display with.
**/
*/
timeline::TimelineViewWindow viewWindow;
// Selection State
/**
* The start time of the selection period.
**/
*/
lumiera::Time selectionStart;
/**
* The end time of the selection period.
**/
*/
lumiera::Time selectionEnd;
/**
* The start time of the playback period.
**/
*/
lumiera::Time playbackPeriodStart;
/**
* The end time of the playback period.
**/
*/
lumiera::Time playbackPeriodEnd;
/**
* The time of the playback point.
**/
*/
lumiera::Time playbackPoint;
// Signals
/**
* A signal to notify when the selected period has changed.
**/
*/
sigc::signal<void> selectionChangedSignal;
/**
* A signal to notify when the playback point or playback periods have
* changed.
**/
*/
sigc::signal<void> playbackChangedSignal;
};

View file

@ -30,8 +30,8 @@ namespace gui {
namespace widgets {
namespace timeline {
Tool::Tool(TimelineBody &timeline_body) :
timelineBody(timeline_body),
Tool::Tool(TimelineBody &timelineBody) :
timelineBody(timelineBody),
isDragging(false)
{
}
@ -40,7 +40,7 @@ bool
Tool::apply_cursor()
{
Glib::RefPtr<Window> window = timelineBody.get_window();
if(!window)
if (!window)
return false;
window->set_cursor(get_cursor());
@ -69,6 +69,8 @@ Tool::on_button_release_event(GdkEventButton* event)
void
Tool::on_motion_notify_event(GdkEventMotion *event)
{
REQUIRE (event != NULL);
mousePoint = Point(event->x, event->y);
}

View file

@ -58,13 +58,13 @@ class Tool
protected:
/**
* Constructor
* @param timeline_body The owner timeline body object
* @param timelineBody The owner timeline body object
*/
Tool(TimelineBody &timeline_body);
Tool(TimelineBody &timelineBody);
public:
/**
* Destructor to be overriden by derived classes.
* Destructor to be overridden by derived classes.
* @remarks If this were not present, derrived class destructors
* would not be called.
*/
@ -85,25 +85,25 @@ public:
/* ===== Event Handlers ===== */
/**
* The event handler for button press events.
* @remarks This can be overriden by the derrived classes, but
* @remarks This can be overridden by the derived classes, but
* Tool::on_button_press_event must be called <b>at the start</b>
* of the derrived class's override.
* of the derived class's override.
*/
virtual void on_button_press_event(GdkEventButton* event);
/**
* The event handler for button release events.
* @remarks This can be overriden by the derrived classes, but
* @remarks This can be overridden by the derived classes, but
* Tool::on_button_release_event must be called <b>at the end</b> of
* the derrived class's override.
* the derived class's override.
*/
virtual void on_button_release_event(GdkEventButton* event);
/**
* The event handler for mouse move events.
* @remarks This can be overriden by the derrived classes, but
* @remarks This can be overridden by the derived classes, but
* Tool::on_motion_notify_event must be called <b>at the start</b> of
* the derrived class's override.
* the derived class's override.
*/
virtual void on_motion_notify_event(GdkEventMotion *event);
@ -132,12 +132,12 @@ protected:
/**
* A helper function to get the state
**/
*/
boost::shared_ptr<TimelineState> get_state() const;
/**
* A helper function to get the view window
**/
*/
TimelineViewWindow& view_window() const;
protected:

View file

@ -39,22 +39,20 @@ const float Track::ExpandAnimationPeriod = 0.15;
Track::Track(TimelineWidget &timeline_widget,
shared_ptr<model::Track> track) :
timelineWidget(timeline_widget),
model_track(track),
enabled(true),
modelTrack(track),
expanded(true),
expandDirection(None),
locked(false),
headerWidget(*this),
enableButton(Gtk::StockID("track_enabled"), WindowManager::MenuIconSize),
lockButton(Gtk::StockID("track_unlocked"), WindowManager::MenuIconSize)
{
REQUIRE(model_track);
REQUIRE(modelTrack);
titleMenuButton.set_relief(RELIEF_HALF);
titleMenuButton.unset_flags(CAN_FOCUS);
buttonBar.append(enableButton, mem_fun(this, &Track::on_enable));
buttonBar.append(lockButton, mem_fun(this, &Track::on_lock));
buttonBar.append(enableButton, mem_fun(this, &Track::onToggleEnabled));
buttonBar.append(lockButton, mem_fun(this, &Track::onToggleLocked));
headerWidget.set_child_widget(headerBox);
@ -71,11 +69,11 @@ Track::Track(TimelineWidget &timeline_widget,
title_list.push_back( Menu_Helpers::MenuElem(_("_Remove"),
mem_fun(this, &Track::on_remove_track) ) );
update_name();
// Setup tooltips
enableButton.set_tooltip_text(_("Disable track"));
lockButton.set_tooltip_text(_("Lock track"));
updateEnableButton();
updateLockButton();
updateName();
// Setup the context menu
Menu::MenuList& context_list = contextMenu.items();
@ -85,9 +83,12 @@ Track::Track(TimelineWidget &timeline_widget,
mem_fun(this, &Track::on_remove_track) ) );
// Connect to the model
model_track->signal_name_changed().connect(sigc::mem_fun(this,
&Track::on_name_changed));
modelTrack->signalEnabledChanged().connect(sigc::mem_fun(this,
&Track::onEnabledChanged));
modelTrack->signalLockedChanged().connect(sigc::mem_fun(this,
&Track::onLockedChanged));
modelTrack->signalNameChanged().connect(sigc::mem_fun(this,
&Track::onNameChanged));
}
Track::~Track()
@ -102,9 +103,9 @@ Track::get_header_widget()
}
shared_ptr<model::Track>
Track::get_model_track() const
Track::getModelTrack() const
{
return model_track;
return modelTrack;
}
int
@ -119,6 +120,13 @@ Track::get_expanded() const
return expanded;
}
boost::shared_ptr<timeline::Clip>
Track::getClipAt(lumiera::Time) const
{
// Default implementation returns empty pointer
return boost::shared_ptr<timeline::Clip>();
}
void
Track::expand_collapse(ExpandDirection direction)
{
@ -226,17 +234,69 @@ Track::show_header_context_menu(guint button, guint32 time)
}
void
Track::update_name()
Track::onEnabledChanged(bool)
{
REQUIRE(model_track);
titleMenuButton.set_label(model_track->get_name());
updateEnableButton();
}
void
Track::on_enable()
Track::onLockedChanged(bool)
{
enabled = !enabled;
if (enabled)
updateLockButton();
}
void
Track::on_set_name()
{
REQUIRE(modelTrack);
Gtk::Window *window = dynamic_cast<Window*>(
timelineWidget.get_toplevel());
REQUIRE(window != NULL);
dialogs::NameChooser dialog(*window,
_("Set Track Name"), modelTrack->get_name());
if(dialog.run() == RESPONSE_OK)
modelTrack->set_name(dialog.get_name());
}
void
Track::onNameChanged(std::string)
{
updateName();
}
void
Track::on_remove_track()
{
REQUIRE(modelTrack);
boost::shared_ptr<TimelineState> state = timelineWidget.get_state();
REQUIRE(state);
state->get_sequence()->remove_descendant_track(modelTrack);
}
void
Track::onToggleEnabled()
{
bool status = modelTrack->getEnabled();
modelTrack->setEnabled(!status);
}
void
Track::onToggleLocked()
{
bool status = modelTrack->getLocked();
modelTrack->setLocked(!status);
}
void
Track::updateEnableButton()
{
REQUIRE (modelTrack);
if (modelTrack->getEnabled())
{
enableButton.set_stock_id(Gtk::StockID("track_enabled"), WindowManager::MenuIconSize);
enableButton.set_tooltip_text(_("Disable track"));
@ -249,10 +309,11 @@ Track::on_enable()
}
void
Track::on_lock()
Track::updateLockButton()
{
locked = !locked;
if (locked)
REQUIRE (modelTrack);
if (modelTrack->getLocked())
{
lockButton.set_stock_id(Gtk::StockID("track_locked"), WindowManager::MenuIconSize);
lockButton.set_tooltip_text(_("Unlock track"));
@ -265,35 +326,10 @@ Track::on_lock()
}
void
Track::on_set_name()
Track::updateName()
{
REQUIRE(model_track);
Gtk::Window *window = dynamic_cast<Window*>(
timelineWidget.get_toplevel());
REQUIRE(window != NULL);
dialogs::NameChooser dialog(*window,
_("Set Track Name"), model_track->get_name());
if(dialog.run() == RESPONSE_OK)
model_track->set_name(dialog.get_name());
}
void
Track::on_name_changed(std::string)
{
update_name();
}
void
Track::on_remove_track()
{
REQUIRE(model_track);
boost::shared_ptr<TimelineState> state = timelineWidget.get_state();
REQUIRE(state);
state->get_sequence()->remove_descendant_track(model_track);
REQUIRE(modelTrack);
titleMenuButton.set_label(modelTrack->get_name());
}
} // namespace timeline

View file

@ -19,20 +19,28 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file widgets/timeline/timeline-track.hpp
** This file contains the definition of timeline track object
*/
#ifndef TIMELINE_TRACK_HPP
#define TIMELINE_TRACK_HPP
#include "gui/gtk-lumiera.hpp"
#include "gui/model/track.hpp"
#include "gui/widgets/menu-button.hpp"
#include "gui/widgets/mini-button.hpp"
#include "gui/widgets/button-bar.hpp"
#include "timeline-header-container.hpp"
#include "timeline-header-widget.hpp"
#include "gui/widgets/timeline/timeline-clip.hpp"
#include "gui/widgets/timeline/timeline-header-container.hpp"
#include "gui/widgets/timeline/timeline-header-widget.hpp"
#include <boost/scoped_ptr.hpp>
#ifndef TIMELINE_TRACK_HPP
#define TIMELINE_TRACK_HPP
namespace gui {
namespace widgets {
@ -44,7 +52,7 @@ class TimelineViewWindow;
* Timeline tracks are created by the timeline widget to correspond to
* model tracks. Timeline tracks are used to store UI specific state
* data.
**/
*/
class Track : public sigc::trackable
{
public:
@ -53,7 +61,7 @@ public:
* An enum used by the branch expand/collapse animation.
* ExpandDirection represents whether the branch us being expanded or
* collapsed, or neither.
**/
*/
enum ExpandDirection
{
None,
@ -61,19 +69,26 @@ public:
Collapse
};
public:
/**
* Constructor
*/
Track(TimelineWidget &timeline_widget,
boost::shared_ptr<model::Track> track);
/**
* Destructor
**/
*/
~Track();
Gtk::Widget& get_header_widget();
boost::shared_ptr<model::Track> get_model_track() const;
boost::shared_ptr<model::Track>
getModelTrack() const;
/**
* Return the visual height of the track in pixels.
* @return The visual height of the track in pixels.
*/
int get_height() const;
/**
@ -81,14 +96,14 @@ public:
* @return Returns true if the branch is expanded, false if it's
* collapsed.
* @see expand_collapse
**/
*/
bool get_expanded() const;
/**
* Expands or collapses this branch.
* @param direction Specifies whether this branch should be expanded
* or collapse. direction must not equal None
**/
*/
void expand_collapse(ExpandDirection direction);
/**
@ -100,74 +115,104 @@ public:
* (and animating). When the branch is not animating this value has
* an indeterminate value.
* @see tick_expand_animation
**/
*/
float get_expand_animation_state() const;
/**
* Gets whether the branch is animation.
* @return Returns true if the branch is animating, false if not.
**/
*/
bool is_expand_animating() const;
/**
* When this track is being animated, tick_expand_animation must be
* called repeatedly to cause the animation to progress.
**/
*/
void tick_expand_animation();
/**
* Calculates the expander style, given the animation state.
**/
*/
Gtk::ExpanderStyle get_expander_style() const;
/**
*
*/
void show_header_context_menu(guint button, guint32 time);
/**
* Draw the track
*/
virtual void draw_track(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window)
const = 0;
public:
//----- Constants -----//
/**
* Gets the clip that is occupying the given time.
* The default implementation simply returns an empty pointer.
* @param the given time
*/
virtual boost::shared_ptr<timeline::Clip>
getClipAt(lumiera::Time position) const;
private:
/**
* Specifies the period of the expand animation in seconds.
**/
*/
static const float ExpandAnimationPeriod;
private:
//----- Internals -----//
void update_name();
private:
/**
* Event handler for when the enabled status changes.
*/
void onEnabledChanged(bool);
//----- Event Handlers -----//
void on_enable();
void on_lock();
/**
* Event handler for when the track name changes.
*/
void onNameChanged(std::string);
/**
* Event handler for when the user requested to remove the track.
*/
void on_remove_track();
/**
* Event handler for when the locked status changes.
*/
void onLockedChanged(bool);
/**
* Event handler for when the user requested a name change.
*/
void on_set_name();
/**
* Event handler for when the track name changes
**/
void on_name_changed(std::string);
* Event handler for when the user pressed the Enable button.
*/
void onToggleEnabled();
/**
* Event handler for when the user pressed the Lock button.
*/
void onToggleLocked();
void updateEnableButton();
void updateLockButton();
void updateName();
void on_remove_track();
protected:
TimelineWidget &timelineWidget;
boost::shared_ptr<model::Track> model_track;
boost::shared_ptr<model::Track> modelTrack;
private:
/**
* True if this track is enabled.
*/
bool enabled;
/**
* This bool is true if this branch is expanded. false if it is
* collapsed.
**/
*/
bool expanded;
/**
@ -175,7 +220,7 @@ private:
* is moving - if any.
* @remarks If no animation is occuring, expandDirection is set to
* None.
**/
*/
ExpandDirection expandDirection;
/**
@ -186,18 +231,13 @@ private:
* 0.0 when the branch is fully collapsed (and animating). When the
* branch is not animating this value has an indeterminate value.
* @see tick_expand_animation
**/
*/
double expandAnimationState;
/**
* An internal timer used for the expand/collapse animation.
**/
boost::scoped_ptr<Glib::Timer> expand_timer;
/**
* True if this track is locked.
*/
bool locked;
boost::scoped_ptr<Glib::Timer> expand_timer;
//----- Header Widgets ------//

View file

@ -40,7 +40,7 @@ namespace timeline {
* TimelineViewWindow is a helper class for TimelineWidget which manages
* the view window of the timeline: the zoom and shift. The class also
* provides utility functions for handling time in the timeline.
**/
*/
class TimelineViewWindow
{
public:
@ -49,7 +49,7 @@ public:
* Constructor
* @param offset The initial view offset.
* @param scale The initial scale.
**/
*/
TimelineViewWindow(lumiera::Time offset, int64_t scale);
/**
@ -84,14 +84,14 @@ public:
* given point on the timeline still.
* @param zoom_size The number of steps to zoom by. The scale factor
* is 1.25^(-zoom_size).
**/
*/
void zoom_view(int point, int zoom_size);
/**
* Scrolls the view horizontally as a proportion of the view area.
* @param shift_size The size of the shift in 1/256ths of the view
* width.
**/
*/
void shift_view(int view_width, int shift_size);
/**
@ -99,7 +99,7 @@ public:
* @param time The time value to convert.
* @return Returns the x-value as pixels from the left hand edge of
* the timeline body.
**/
*/
int time_to_x(int64_t time) const;
/**
@ -107,12 +107,12 @@ public:
* @param x The x coordinte (as pixels from the left hand edge of
* the timeline body) to convert.
* @return Returns the time at the coordinate.
**/
*/
lumiera::Time x_to_time(int x) const;
/**
* A signal to indicate that the scale or offset have been changed.
**/
*/
sigc::signal<void> changed_signal() const;
private:

View file

@ -1,5 +1,5 @@
/*
video-display-widget.cpp - Implementation of the video viewer widget
VideoDisplayWidget - Implementation of the video viewer widget
Copyright (C) Lumiera.org
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
@ -20,9 +20,6 @@
* *****************************************************/
#include <gdkmm/drawable.h>
#include <gdkmm/general.h>
#include <cairomm-1.0/cairomm/cairomm.h>
#include "gui/gtk-lumiera.hpp"
#include "gui/output/xvdisplayer.hpp"
@ -32,62 +29,58 @@
namespace gui {
namespace widgets {
VideoDisplayWidget::VideoDisplayWidget() :
displayer(NULL)
{
}
VideoDisplayWidget::~VideoDisplayWidget()
{
if(displayer != NULL)
delete displayer;
}
Displayer*
VideoDisplayWidget::get_displayer() const
{
return displayer;
}
void
VideoDisplayWidget::on_realize()
{
// Call base class:
Gtk::Widget::on_realize();
// Set colors
modify_bg(Gtk::STATE_NORMAL, Gdk::Color("black"));
if(displayer != NULL)
delete displayer;
displayer = createDisplayer(this, 320, 240);
add_events(Gdk::ALL_EVENTS_MASK);
}
Displayer*
VideoDisplayWidget::createDisplayer( Gtk::Widget *drawingArea, int width, int height )
{
REQUIRE(drawingArea != NULL);
REQUIRE(width > 0 && height > 0);
Displayer *displayer = NULL;
VideoDisplayWidget::VideoDisplayWidget ( )
: displayer (NULL)
{ }
displayer = new XvDisplayer( drawingArea, width, height );
if ( !displayer->usable() )
{
delete displayer;
displayer = NULL;
}
if ( displayer == NULL )
{
displayer = new GdkDisplayer( drawingArea, width, height );
}
return displayer;
}
} // namespace widgets
} // namespace gui
VideoDisplayWidget::~VideoDisplayWidget ( )
{
if (displayer != NULL) delete displayer;
}
Displayer*
VideoDisplayWidget::get_displayer ( ) const
{
return displayer;
}
void VideoDisplayWidget::on_realize ( )
{
// Call base class:
Gtk::Widget::on_realize ();
// Set colours
modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("black"));
if (displayer != NULL) delete displayer;
displayer = createDisplayer (this, 320, 240);
add_events (Gdk::ALL_EVENTS_MASK);
}
Displayer*
VideoDisplayWidget::createDisplayer (Gtk::Widget *drawingArea, int width, int height)
{
REQUIRE (drawingArea != NULL);
REQUIRE (width > 0 && height > 0);
Displayer *displayer = NULL;
displayer = new XvDisplayer (drawingArea, width, height);
if (!displayer->usable ())
{
delete displayer;
displayer = NULL;
}
if (displayer == NULL)
{
displayer = new GdkDisplayer (drawingArea, width, height);
}
return displayer;
}
}}// namespace gui::widgets

View file

@ -1,5 +1,5 @@
/*
video-display-widget.hpp - Declaration of the video viewer widget
VIDEO-DISPLAY-WIDGET.hpp - GUI widget for displaying video
Copyright (C) Lumiera.org
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
@ -19,10 +19,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file video-display-widget.hpp
** This file contains the definition of video viewer widget
*/
#ifndef VIDEO_DISPLAY_WIDGET_HPP
#define VIDEO_DISPLAY_WIDGET_HPP
@ -34,31 +37,31 @@ using namespace gui::output;
namespace gui {
namespace widgets {
class VideoDisplayWidget : public Gtk::DrawingArea
{
public:
VideoDisplayWidget();
~VideoDisplayWidget();
Displayer* get_displayer() const;
/* ===== Overrides ===== */
private:
virtual void on_realize();
/* ===== Internals ===== */
private:
static Displayer*
createDisplayer( Gtk::Widget *drawingArea, int width, int height );
private:
Displayer *displayer;
};
} // namespace widgets
} // namespace gui
class VideoDisplayWidget
: public Gtk::DrawingArea
{
public:
VideoDisplayWidget();
~VideoDisplayWidget();
Displayer* get_displayer() const;
/* ===== Overrides ===== */
private:
virtual void on_realize();
/* ===== Internals ===== */
private:
static Displayer*
createDisplayer( Gtk::Widget *drawingArea, int width, int height );
private:
Displayer *displayer;
};
}} // namespace gui::widgets
#endif // VIDEO_DISPLAY_WIDGET_HPP

Some files were not shown because too many files have changed in this diff Show more