diff --git a/.gitignore b/.gitignore index 10dbaee23..cf7ebb45d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,11 @@ *~ *.tar.* .[^.]* +*.o *.os *.gch ,valgrind.log* -admin/scons/*.pyc +*.pyc optcache Makefile.in build/* @@ -13,5 +14,8 @@ bin/* autom4te.cache/* scripts/* configure +config.log aclocal.m4 semantic.cache +wiki/backups/* +doc/devel/draw/*.png diff --git a/Makefile.am b/Makefile.am index 2edbc6e28..effa2b05b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,6 @@ # Copyright (C) Lumiera.org # 2007, Christian Thaeter +# 2008, Joel Holdsworth # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -47,6 +48,9 @@ include $(top_srcdir)/src/gui/Makefile.am # plugins #include $(top_srcdir)/src... +# resources +include $(top_srcdir)/icons/Makefile.am + # tests include $(top_srcdir)/tests/common/Makefile.am include $(top_srcdir)/tests/components/Makefile.am diff --git a/SConstruct b/SConstruct index c5f2971ee..9c56cece3 100644 --- a/SConstruct +++ b/SConstruct @@ -21,13 +21,6 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ##################################################################### -import sys -sys.path.append("./admin/scons") - -import os -from Buildhelper import * -from LumieraEnvironment import * - #-----------------------------------Configuration OPTIONSCACHEFILE = 'optcache' @@ -37,6 +30,8 @@ BINDIR = 'bin' TESTDIR = 'tests' ICONDIR = 'icons' VERSION = '0.1+pre.01' +TOOLDIR = './admin/scons' +SVGRENDERER = 'admin/render-icon' #-----------------------------------Configuration # NOTE: scons -h for help. @@ -46,6 +41,14 @@ VERSION = '0.1+pre.01' +import os +import sys + +sys.path.append(TOOLDIR) + +from Buildhelper import * +from LumieraEnvironment import * + ##################################################################### @@ -56,7 +59,10 @@ def setupBasicEnvironment(): EnsureSConsVersion(0,96,90) opts = defineCmdlineOptions() - env = LumieraEnvironment(options=opts) + env = LumieraEnvironment(options=opts + ,toolpath = [TOOLDIR] + ,tools = ["default", "BuilderGCH", "BuilderDoxygen"] + ) env.Append ( CCCOM=' -std=gnu99') # workaround for a bug: CCCOM currently doesn't honor CFLAGS, only CCFLAGS env.Replace( VERSION=VERSION @@ -68,12 +74,12 @@ def setupBasicEnvironment(): , CCFLAGS='-Wall ' # -fdiagnostics-show-option ) - RegisterPrecompiledHeader_Builder(env) + RegisterIcon_Builder(env,SVGRENDERER) handleNoBugSwitches(env) env.Append(CPPDEFINES = '_GNU_SOURCE') appendCppDefine(env,'DEBUG','DEBUG', 'NDEBUG') - appendCppDefine(env,'OPENGL','USE_OPENGL') +# appendCppDefine(env,'OPENGL','USE_OPENGL') appendVal(env,'ARCHFLAGS', 'CCFLAGS') # for both C and C++ appendVal(env,'OPTIMIZE', 'CCFLAGS', val=' -O3') appendVal(env,'DEBUG', 'CCFLAGS', val=' -ggdb') @@ -101,8 +107,7 @@ def handleNoBugSwitches(env): level = env['BUILDLEVEL'] if level in ['ALPHA', 'BETA']: if not env['DEBUG']: - print 'NoBug: ALPHA or BETA builds without DEBUG not possible, exiting.' - Exit(1) + print 'Warning: NoBug ALPHA or BETA builds requires DEBUG=yes, switching DEBUG on!' env.Replace( DEBUG = 1 ) env.Append(CPPDEFINES = 'EBUG_'+level) elif level == 'RELEASE': @@ -123,7 +128,7 @@ def defineCmdlineOptions(): allowed_values=('ALPHA', 'BETA', 'RELEASE')) ,BoolOption('DEBUG', 'Build with debugging information and no optimizations', False) ,BoolOption('OPTIMIZE', 'Build with strong optimization (-O3)', False) - ,BoolOption('OPENGL', 'Include support for OpenGL preview rendering', False) +# ,BoolOption('OPENGL', 'Include support for OpenGL preview rendering', False) # ,EnumOption('DIST_TARGET', 'Build target architecture', 'auto', # allowed_values=('auto', 'i386', 'i686', 'x86_64' ), ignorecase=2) ,PathOption('DESTDIR', 'Installation dir prefix', '/usr/local') @@ -168,24 +173,21 @@ def configurePlatform(env): # run all configuration checks in the given env # Perform checks for prerequisites -------------------------------------------- + problems = [] if not conf.TryAction('pkg-config --version > $TARGET')[0]: - print 'We need pkg-config for including library configurations, exiting.' - Exit(1) + problems.append('We need pkg-config for including library configurations, exiting.') if not conf.CheckLibWithHeader('m', 'math.h','C'): - print 'Did not find math.h / libm, exiting.' - Exit(1) + problems.append('Did not find math.h / libm.') if not conf.CheckLibWithHeader('dl', 'dlfcn.h', 'C'): - print 'Functions for runtime dynamic loading not available, exiting.' - Exit(1) + problems.append('Functions for runtime dynamic loading not available.') if not conf.CheckLibWithHeader('nobugmt', 'nobug.h', 'C'): - print 'Did not find NoBug [http://www.pipapo.org/pipawiki/NoBug], exiting.' - Exit(1) + problems.append('Did not find NoBug [http://www.pipapo.org/pipawiki/NoBug].') if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'C'): - print 'Did not find the pthread lib or pthread.h, exiting.' + problems.append('Did not find the pthread lib or pthread.h.') else: conf.env.Append(CPPFLAGS = ' -DHAVE_PTHREAD') conf.env.Append(CCFLAGS = ' -pthread') @@ -197,49 +199,56 @@ def configurePlatform(env): conf.env.Append(CPPFLAGS = ' -DHAS_VALGRIND_VALGIND_H') if not conf.CheckCXXHeader('tr1/memory'): - print 'We rely on the std::tr1 proposed standard extension for shared_ptr.' - Exit(1) + problems.append('We rely on the std::tr1 proposed standard extension for shared_ptr.') if not conf.CheckCXXHeader('boost/config.hpp'): - print 'We need the C++ boost-lib.' - Exit(1) + problems.append('We need the C++ boost-lib.') else: if not conf.CheckCXXHeader('boost/shared_ptr.hpp'): - print 'We need boost::shared_ptr (shared_ptr.hpp).' - Exit(1) + problems.append('We need boost::shared_ptr (shared_ptr.hpp).') if not conf.CheckLibWithHeader('boost_program_options-mt','boost/program_options.hpp','C++'): - print 'We need boost::program_options (including binary lib for linking).' - Exit(1) + problems.append('We need boost::program_options (including binary lib for linking).') if not conf.CheckLibWithHeader('boost_regex-mt','boost/regex.hpp','C++'): - print 'We need the boost regular expression lib (incl. binary lib for linking).' - Exit(1) + problems.append('We need the boost regular expression lib (incl. binary lib for linking).') # if not conf.CheckLibWithHeader('gavl', ['gavlconfig.h', 'gavl/gavl.h'], 'C'): if not conf.CheckPkgConfig('gavl', 1.0): - print 'Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html], exiting.' - Exit(1) + problems.append('Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html].') else: conf.env.mergeConf('gavl') if not conf.CheckPkgConfig('gtkmm-2.4', 2.8): - print 'Unable to configure GTK--, exiting.' - Exit(1) + problems.append('Unable to configure GTK--, exiting.') + + if not conf.CheckPkgConfig('glibmm-2.4', '2.16'): + problems.append('Unable to configure Lib glib--, exiting.') if not conf.CheckPkgConfig('cairomm-1.0', 0.6): - print 'Unable to configure Cairo--, exiting.' - Exit(1) + problems.append('Unable to configure Cairo--, exiting.') if not conf.CheckPkgConfig('gdl-1.0', '0.6.1'): - print 'Unable to configure the GNOME DevTool Library, exiting.' - Exit(1) + problems.append('Unable to configure the GNOME DevTool Library, exiting.') - if not conf.CheckPkgConfig('xv'): Exit(1) + if not conf.CheckPkgConfig('librsvg-2.0', '2.18.1'): + problems.append('Need rsvg Library for rendering icons.') + + if not conf.CheckPkgConfig('xv'): problems.append('Need lib xv') # if not conf.CheckPkgConfig('xext'): Exit(1) # if not conf.CheckPkgConfig('sm'): Exit(1) # # obviously not needed? + + # report missing dependencies + if problems: + print "*** unable to build due to the following problems:" + for isue in problems: + print " * %s" % isue + print + print "build aborted." + Exit(1) + print "** Gathered Library Info: %s" % conf.env.libInfo.keys() @@ -269,6 +278,10 @@ def defineBuildTargets(env, artifacts): setup sub-environments with special build options if necessary. We use a custom function to declare a whole tree of srcfiles. """ + # use PCH to speed up building +# env['GCH'] = ( env.PrecompiledHeader('$SRCDIR/pre.hpp') +# + env.PrecompiledHeader('$SRCDIR/pre_a.hpp') +# ) objback = srcSubtree(env,'$SRCDIR/backend') objproc = srcSubtree(env,'$SRCDIR/proc') @@ -281,27 +294,29 @@ def defineBuildTargets(env, artifacts): + env.StaticLibrary('$BINDIR/lumi.la', objlib) ) - # use PCH to speed up building - precomp = ( env.PrecompiledHeader('$SRCDIR/pre') - + env.PrecompiledHeader('$SRCDIR/pre_a') - ) - env.Depends(objproc, precomp) - env.Depends(objlib, precomp) artifacts['lumiera'] = env.Program('$BINDIR/lumiera', ['$SRCDIR/main.cpp']+ core ) artifacts['plugins'] = env.SharedLibrary('$BINDIR/lumiera-plugin', objplug) - + # the Lumiera GTK GUI - envgtk = env.Clone().mergeConf(['gtkmm-2.4','cairomm-1.0','gdl-1.0','xv','xext','sm']) + envgtk = env.Clone().mergeConf(['gtkmm-2.4','cairomm-1.0','gdl-1.0','librsvg-2.0','xv','xext','sm']) objgui = srcSubtree(envgtk,'$SRCDIR/gui') + # 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'])] + ) + artifacts['lumigui'] = ( envgtk.Program('$BINDIR/lumigui', objgui + core) - + env.Install('$BINDIR', env.Glob('$ICONDIR/*.png')) + env.Install('$BINDIR', env.Glob('$SRCDIR/gui/*.rc')) + + artifacts['icons'] ) # call subdir SConscript(s) for independent components SConscript(dirs=[SRCDIR+'/tool'], exports='env artifacts core') + SConscript(dirs=['admin'], exports='env envgtk artifacts core') SConscript(dirs=[TESTDIR], exports='env artifacts core') @@ -321,16 +336,9 @@ def definePostBuildTargets(env, artifacts): env.Clean ('build', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log' ]) env.Clean ('build', [ '$SRCDIR/pre.gch' ]) - # Doxygen documentation - # Note: at the moment we only depend on Doxyfile - # obviousely, we should depend on all sourcefiles - # real Doxygen builder for scons is under developement for 0.97 - # so for the moment I prefere not to bother - doxyfile = File('doc/devel/Doxyfile') - env.NoClean(doxyfile) - doxydoc = artifacts['doxydoc'] = [ Dir('doc/devel/html'), Dir('doc/devel/latex') ] - env.Command(doxydoc, doxyfile, "doxygen Doxyfile 2>&1 |tee ,doxylog", chdir='doc/devel') - env.Clean ('doc/devel', doxydoc + ['doc/devel/,doxylog']) + doxydoc = artifacts['doxydoc'] = env.Doxygen('doc/devel/Doxyfile') + env.Alias ('doc', doxydoc) + env.Clean ('doc', doxydoc + ['doc/devel/,doxylog','doc/devel/warnings.txt']) def defineInstallTargets(env, artifacts): diff --git a/admin/Makefile.am b/admin/Makefile.am index 6385eb910..9eb4fbb89 100644 --- a/admin/Makefile.am +++ b/admin/Makefile.am @@ -22,3 +22,7 @@ vgsuppression_SOURCES = $(admin_srcdir)/vgsuppression.c vgsuppression_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ vgsuppression_LDADD = liblumi.a -lnobugmt -lpthread -ldl +noinst_PROGRAMS += rsvg-convert +rsvg_convert_SOURCES = $(admin_srcdir)/rsvg-convert.c +rsvg_convert_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror +rsvg_convert_LDADD = -lcairo -lglib-2.0 -lgthread-2.0 -lrsvg-2 diff --git a/admin/SConscript b/admin/SConscript new file mode 100644 index 000000000..d0ad7b84e --- /dev/null +++ b/admin/SConscript @@ -0,0 +1,17 @@ +# -*- python -*- +## +## SConscript - SCons buildscript for helper tools (called by SConstruct) +## + +Import('env','envgtk','artifacts','core') + +vgsuppr = env.Program('#$BINDIR/vgsuppression',['vgsuppression.c']+core) +rsvg = envgtk.Program('#$BINDIR/rsvg-convert','rsvg-convert.c') + +artifacts['tools'] += [ vgsuppr ## for supressing false valgrind alarms + + rsvg ## for rendering SVG icons (uses librsvg) + ] + +# Rendering the SVG Icons depends on rsvg-convert +env.Depends(artifacts['icons'], rsvg) + diff --git a/admin/render-icon.py b/admin/render-icon.py new file mode 100755 index 000000000..26bdb3653 --- /dev/null +++ b/admin/render-icon.py @@ -0,0 +1,178 @@ +#!/usr/bin/python + +# render-icons.py - Icon rendering utility script +# +# Copyright (C) Lumiera.org +# 2008, Joel Holdsworth +# +# 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. + +import sys +import getopt +from xml.dom import minidom +import os +import shutil + +#svgDir = "svg" +#prerenderedDir = "prerendered" +inkscapePath = "/usr/bin/inkscape" +rsvgPath = "./rsvg-convert" +artworkLayerPrefix = "artwork:" + +def createDirectory( name ): + if os.path.exists(name) == False: + os.mkdir(name) + +def copyMergeDirectory( src, dst ): + listing = os.listdir(src) + for file_name in listing: + src_file_path = os.path.join(src, file_name) + dst_file_path = os.path.join(dst, file_name) + shutil.copyfile(src_file_path, dst_file_path) + +def getDocumentSize( svg_element ): + width = float(svg_element.getAttribute("width")) + height = float(svg_element.getAttribute("height")) + return [width, height] + +def findChildLayerElement( parent_element ): + for node in parent_element.childNodes: + if node.nodeType == minidom.Node.ELEMENT_NODE: + if node.tagName == "g": + if node.getAttribute("inkscape:groupmode") == "layer": + return node + return None + +def parsePlateLayer( layer ): + rectangles = [] + for node in layer.childNodes: + if node.nodeType == minidom.Node.ELEMENT_NODE: + if node.tagName == "rect": + x = float(node.getAttribute("x")) + y = float(node.getAttribute("y")) + width = float(node.getAttribute("width")) + height = float(node.getAttribute("height")) + rectangles.append([x, y, width, height]) + return rectangles + +def parseSVG( file_path ): + print "Parsing " + file_path + svgdoc = minidom.parse(file_path) + for root_node in svgdoc.childNodes: + if root_node.nodeType == minidom.Node.ELEMENT_NODE: + if root_node.tagName == "svg": + size = getDocumentSize( root_node ) + layer = findChildLayerElement( root_node ) + if layer != None: + layer_name = layer.getAttribute("inkscape:label") + if layer_name[:len(artworkLayerPrefix)] == artworkLayerPrefix: + artwork_name = layer_name[len(artworkLayerPrefix):] + plate = findChildLayerElement( layer ) + if plate != None: + return artwork_name, size, parsePlateLayer( plate ) + return None + +def renderSvgInkscape(file_path, out_dir, artwork_name, rectangle, doc_size): + + # Calculate the rendering rectangle + x1 = rectangle[0] + y1 = doc_size[1] - rectangle[1] - rectangle[3] + x2 = x1 + rectangle[2] + y2 = y1 + rectangle[3] + + # Call Inkscape to do the render + os.spawnlp(os.P_WAIT, inkscapePath, inkscapePath, + file_path, + "-z", + "-a %g:%g:%g:%g" % (x1, y1, x2, y2), + "-w %g" % (rectangle[2]), "-h %g" % (rectangle[3]), + "--export-png=" + os.path.join(out_dir, "%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name))) + +def renderSvgRsvg(file_path, out_dir, artwork_name, rectangle, doc_size): + # Prepare a Cairo context + width = int(rectangle[2]) + height = int(rectangle[3]) + + if not os.path.exists(rsvgPath): + print "Error: executable %s not found." % rsvgPath + + os.spawnlp(os.P_WAIT, rsvgPath, rsvgPath, + "--source-rect=%g:%g:%g:%g" % (rectangle[0], rectangle[1], rectangle[2], rectangle[3]), + "--output=" + os.path.join(out_dir, "%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name)), + file_path) + +def renderSvgIcon(file_path, out_dir): + artwork_name, doc_size, rectangles = parseSVG(file_path) + for rectangle in rectangles: + renderSvgRsvg(file_path, out_dir, artwork_name, rectangle, doc_size) + +def getTargetNames(file_path): + """get a list of target names to be rendered from the given source SVG + usable to setup the build targets for SCons + """ + artwork_name, _ , rectangles = parseSVG(file_path) + return ["%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name) for rectangle in rectangles ] + +#def renderSvgIcons(): +# listing = os.listdir(svgDir) +# for file_path in listing: +# [root, extension] = os.path.splitext(file_path) +# if extension.lower() == ".svg": +# renderSvgIcon(os.path.join(svgDir, file_path)) + +#def copyPrerenderedIcons(): +# listing = os.listdir(prerenderedDir) +# for list_item in listing: +# src_dir = os.path.join(prerenderedDir, list_item) +# copyMergeDirectory(src_dir, list_item) + +def printHelp(): + print "render-icon.py SRCFILE.svg TARGETDIR" + print "An icon rendering utility script for lumiera" + +def parseArguments(argv): + optlist, args = getopt.getopt(argv, "") + + if len(args) == 2: + return args[0], args[1] + + printHelp() + return None, None + +def main(argv): + in_path, out_dir = parseArguments(argv) + + if in_path == None or out_dir == None: + return + + if os.path.exists(out_dir) == False: + print "Directory not found: " + out_dir + return + + # Create the icons folders + createDirectory(os.path.join(out_dir, "48x48")) + createDirectory(os.path.join(out_dir, "32x32")) + createDirectory(os.path.join(out_dir, "24x24")) + createDirectory(os.path.join(out_dir, "22x22")) + createDirectory(os.path.join(out_dir, "16x16")) + + renderSvgIcon(in_path, out_dir) + + # Copy in prerendered icons + #copyPrerenderedIcons() + +if __name__=="__main__": + main(sys.argv[1:]) + diff --git a/admin/rsvg-convert.c b/admin/rsvg-convert.c new file mode 100644 index 000000000..7ed5a9910 --- /dev/null +++ b/admin/rsvg-convert.c @@ -0,0 +1,219 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- + + rsvg-convert.c: Command line utility for exercising rsvg with cairo. + + Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005 Dom Lachowicz + Copyright (C) 2005 Caleb Moore + Copyright (C) 2008 Joel Holdsworth + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Carl Worth , + Caleb Moore , + Dom Lachowicz , + Joel Holdsworth +*/ + +#ifndef N_ +#define N_(X) X +#endif + +#include +#include +#include + +#include +#include + +#ifdef CAIRO_HAS_PS_SURFACE +#include +#endif + +#ifdef CAIRO_HAS_PDF_SURFACE +#include +#endif + +#ifdef CAIRO_HAS_SVG_SURFACE +#include +#endif + +#ifndef _ +#define _(X) X +#endif + +struct RsvgSizeCallbackData { + gint width; + gint height; +}; + +struct RsvgSourceRectangle { + double left; + double top; + double width; + double height; +}; + +static void +display_error (GError * err) +{ + if (err) { + g_print ("%s", err->message); + g_error_free (err); + } +} + +static void +rsvg_cairo_size_callback (int *width, int *height, gpointer data) +{ + RsvgDimensionData *dimensions = data; + *width = dimensions->width; + *height = dimensions->height; +} + +static cairo_status_t +rsvg_cairo_write_func (void *closure, const unsigned char *data, unsigned int length) +{ + fwrite (data, 1, length, (FILE *) closure); + return CAIRO_STATUS_SUCCESS; +} + +int +main (int argc, char **argv) +{ + GOptionContext *g_option_context; + int width = -1; + int height = -1; + char *source_rect_string = NULL; + char *output = NULL; + GError *error = NULL; + char *filename = NULL; + + char **args = NULL; + RsvgHandle *rsvg; + cairo_surface_t *surface = NULL; + cairo_t *cr = NULL; + RsvgDimensionData dimensions; + FILE *output_file = stdout; + + struct RsvgSourceRectangle source_rect = {0, 0, 0, 0}; + + GOptionEntry options_table[] = { + {"width", 'w', 0, G_OPTION_ARG_INT, &width, + N_("width [optional; defaults to the SVG's width]"), N_("")}, + {"height", 'h', 0, G_OPTION_ARG_INT, &height, + N_("height [optional; defaults to the SVG's height]"), N_("")}, + {"source-rect", 'r', 0, G_OPTION_ARG_STRING, &source_rect_string, + N_("source rectangle [optional; defaults to rectangle of the SVG document]"), N_("left:top:width:height")}, + {"output", 'o', 0, G_OPTION_ARG_STRING, &output, + N_("output filename"), NULL}, + {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &args, NULL, N_("FILE")}, + {NULL} + }; + + g_thread_init(NULL); + + g_option_context = g_option_context_new (_("- SVG Converter")); + g_option_context_add_main_entries (g_option_context, options_table, NULL); + g_option_context_set_help_enabled (g_option_context, TRUE); + if (!g_option_context_parse (g_option_context, &argc, &argv, &error)) { + display_error (error); + exit (1); + } + + g_option_context_free (g_option_context); + + if (output != NULL) { + output_file = fopen (output, "wb"); + if (!output_file) { + fprintf (stderr, _("Error saving to file: %s\n"), output); + exit (1); + } + } + + if (args[0] != NULL) { + filename = args[0]; + } + + /* Parse the source rect */ + if(source_rect_string != NULL) { + const int n = sscanf(source_rect_string, "%lg:%lg:%lg:%lg", + &source_rect.left, &source_rect.top, + &source_rect.width, &source_rect.height); + if(n != 4 || source_rect.width <= 0.0 || source_rect.height < 0.0) { + fprintf (stderr, _("Invalid source rect: %s\n"), source_rect_string); + exit(1); + } + } + + rsvg_init (); + + rsvg = rsvg_handle_new_from_file (filename, &error); + + if (!rsvg) { + fprintf (stderr, _("Error reading SVG:")); + display_error (error); + fprintf (stderr, "\n"); + exit (1); + } + + /* if the user did not specify a source rectangle, get the page size from the SVG */ + if(source_rect_string == NULL) { + rsvg_handle_set_size_callback (rsvg, rsvg_cairo_size_callback, &dimensions, NULL); + source_rect.left = 0; + source_rect.top = 0; + source_rect.width = dimensions.width; + source_rect.height = dimensions.height; + } + + rsvg_handle_get_dimensions (rsvg, &dimensions); + + if(width != -1 && height != -1) { + dimensions.width = width; + dimensions.height = height; + } else if(source_rect_string != NULL) { + dimensions.width = source_rect.width; + dimensions.height = source_rect.height; + } + + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + dimensions.width, dimensions.height); + + cr = cairo_create (surface); + + cairo_translate(cr, -source_rect.left, -source_rect.top); + + if(width != -1 && height != -1 && source_rect_string != NULL) { + cairo_scale(cr, (double)dimensions.width / (double)source_rect.width, + (double)dimensions.height / (double)source_rect.height); + } + + rsvg_handle_render_cairo (rsvg, cr); + + cairo_surface_write_to_png_stream (surface, rsvg_cairo_write_func, output_file); + + g_object_unref (G_OBJECT (rsvg)); + + cairo_destroy (cr); + cairo_surface_destroy (surface); + + fclose (output_file); + + rsvg_term (); + + return 0; +} + diff --git a/admin/scons/BuilderDoxygen.py b/admin/scons/BuilderDoxygen.py new file mode 100644 index 000000000..943fce946 --- /dev/null +++ b/admin/scons/BuilderDoxygen.py @@ -0,0 +1,230 @@ +# -*- python -*- +## +## BuilderDoxygen.py - SCons builder for generating Doxygen documentation +## + +# +# Astxx, the Asterisk C++ API and Utility Library. +# Copyright (C) 2005, 2006 Matthew A. Nicholson +# Copyright (C) 2006 Tim Blechmann +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1 as published by the Free Software Foundation. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see http://www.gnu.org/licenses/ +##################################################################### + +# history: 8/2008 adapted for Lumiera build system +# added patch for Doxyfile in subdirectory +# see http://www.scons.org/wiki/DoxygenBuilder + + +import os +import os.path +import glob +from fnmatch import fnmatch + + +def DoxyfileParse(file_contents): + """ + Parse a Doxygen source file and return a dictionary of all the values. + Values will be strings and lists of strings. + """ + data = {} + + import shlex + lex = shlex.shlex(instream = file_contents, posix = True) + lex.wordchars += "*+./-:" + lex.whitespace = lex.whitespace.replace("\n", "") + lex.escape = "" + + lineno = lex.lineno + token = lex.get_token() + key = token # the first token should be a key + last_token = "" + key_token = False + next_key = False + new_data = True + + def append_data(data, key, new_data, token): + if new_data or len(data[key]) == 0: + data[key].append(token) + else: + data[key][-1] += token + + while token: + if token in ['\n']: + if last_token not in ['\\']: + key_token = True + elif token in ['\\']: + pass + elif key_token: + key = token + key_token = False + else: + if token == "+=": + if not data.has_key(key): + data[key] = list() + elif token == "=": + data[key] = list() + else: + append_data( data, key, new_data, token ) + new_data = True + + last_token = token + token = lex.get_token() + + if last_token == '\\' and token != '\n': + new_data = False + append_data( data, key, new_data, '\\' ) + + # compress lists of len 1 into single strings + for (k, v) in data.items(): + if len(v) == 0: + data.pop(k) + + # items in the following list will be kept as lists and not converted to strings + if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS"]: + continue + + if len(v) == 1: + data[k] = v[0] + + return data + +def DoxySourceScan(node, env, path): + """ + Doxygen Doxyfile source scanner. This should scan the Doxygen file and add + any files used to generate docs to the list of source files. + """ + default_file_patterns = [ + '*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx', + '*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++', + '*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm', + '*.py', + ] + + default_exclude_patterns = [ + '*~', + ] + + sources = [] + + data = DoxyfileParse(node.get_contents()) + + if data.get("RECURSIVE", "NO") == "YES": + recursive = True + else: + recursive = False + + file_patterns = data.get("FILE_PATTERNS", default_file_patterns) + exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns) + + # + # We're running in the top-level directory, but the doxygen + # configuration file is in the same directory as node; this means + # that relative pathnames in node must be adjusted before they can + # go onto the sources list + conf_dir = os.path.dirname(str(node)) + + for node in data.get("INPUT", []): + if not os.path.isabs(node): + node = os.path.join(conf_dir, node) + if os.path.isfile(node): + sources.append(node) + elif os.path.isdir(node): + if recursive: + for root, dirs, files in os.walk(node): + for f in files: + filename = os.path.join(root, f) + + pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False) + exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True) + + if pattern_check and not exclude_check: + sources.append(filename) + else: + for pattern in file_patterns: + sources.extend(glob.glob("/".join([node, pattern]))) + + sources = map( lambda path: env.File(path), sources ) + return sources + + +def DoxySourceScanCheck(node, env): + """Check if we should scan this file""" + return os.path.isfile(node.path) + +def DoxyEmitter(source, target, env): + """Doxygen Doxyfile emitter""" + # possible output formats and their default values and output locations + output_formats = { + "HTML": ("YES", "html"), + "LATEX": ("YES", "latex"), + "RTF": ("NO", "rtf"), + "MAN": ("NO", "man"), + "XML": ("NO", "xml"), + } + + data = DoxyfileParse(source[0].get_contents()) + + targets = [] + out_dir = data.get("OUTPUT_DIRECTORY", ".") + + # add our output locations + for (k, v) in output_formats.items(): + if data.get("GENERATE_" + k, v[0]) == "YES": + targets.append(env.Dir( os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]))) ) + + # don't clobber targets + for node in targets: + env.Precious(node) + + # set up cleaning stuff + for node in targets: + env.Clean(node, node) + + return (targets, source) + + +def generate(env): + """ + Add builders and construction variables for the + Doxygen tool. This is currently for Doxygen 1.4.6. + """ + doxyfile_scanner = env.Scanner( + DoxySourceScan, + "DoxySourceScan", + scan_check = DoxySourceScanCheck, + ) + + import SCons.Builder + doxyfile_builder = SCons.Builder.Builder( + action = "cd ${SOURCE.dir} && (${DOXYGEN} ${SOURCE.file} 2>&1 |tee ,doxylog)", + emitter = DoxyEmitter, + target_factory = env.fs.Entry, + single_source = True, + source_scanner = doxyfile_scanner, + ) + + env.Append(BUILDERS = { + 'Doxygen': doxyfile_builder, + }) + + env.AppendUnique( + DOXYGEN = 'doxygen', + ) + +def exists(env): + """ + Make sure doxygen exists. + """ + return env.Detect("doxygen") + diff --git a/admin/scons/BuilderGCH.py b/admin/scons/BuilderGCH.py new file mode 100644 index 000000000..c522cb9cd --- /dev/null +++ b/admin/scons/BuilderGCH.py @@ -0,0 +1,110 @@ +# -*- python -*- +## +## BuilderGCH.py - SCons builder for gcc's precompiled headers +## + +# Copyright (C) scons.org/wiki/GchBuilder +# 2006 Tim Blechmann +# 2008 Hermann Vosseler +# +# 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, see http://www.gnu.org/licenses/ +##################################################################### + +# history: 8/2008 adapted for Lumiera build system +# changed to accept a list of precompiled header defs + + +from types import ListType + +import SCons.Action +import SCons.Builder +import SCons.Scanner.C +import SCons.Util +import SCons.Script + +SCons.Script.EnsureSConsVersion(0,96,92) + +GchAction = SCons.Action.Action('$GCHCOM', '$GCHCOMSTR') +GchShAction = SCons.Action.Action('$GCHSHCOM', '$GCHSHCOMSTR') + +def gen_suffix(env, sources): + return sources[0].get_suffix() + env['GCHSUFFIX'] + + +GchShBuilder = SCons.Builder.Builder(action = GchShAction, + source_scanner = SCons.Scanner.C.CScanner(), + suffix = gen_suffix) + +GchBuilder = SCons.Builder.Builder(action = GchAction, + source_scanner = SCons.Scanner.C.CScanner(), + suffix = gen_suffix) + +def setup_dependency(target,source,env, key): + scanner = SCons.Scanner.C.CScanner() + path = scanner.path(env) + deps = scanner(source[0], env, path) + + if env.has_key(key) and env[key]: + for header in env[key]: + header_path = header.path.strip('.gch') + if header_path in [x.path for x in deps]: + print "Precompiled header(%s) %s \t <--- %s" % (key,header_path,source[0]) + env.Depends(target, header) + + +def static_pch_emitter(target,source,env): + SCons.Defaults.StaticObjectEmitter( target, source, env ) + setup_dependency(target,source,env, key='GCH') + return (target, source) + +def shared_pch_emitter(target,source,env): + SCons.Defaults.SharedObjectEmitter( target, source, env ) + setup_dependency(target,source,env, key='GCH-sh') + return (target, source) + +def generate(env): + """ + Add builders and construction variables for the Gch builder. + """ + env.Append(BUILDERS = { + 'gch': env.Builder( + action = GchAction, + target_factory = env.fs.File, + ), + 'gchsh': env.Builder( + action = GchShAction, + target_factory = env.fs.File, + ), + }) + + try: + bld = env['BUILDERS']['GCH'] + bldsh = env['BUILDERS']['GCH-sh'] + except KeyError: + bld = GchBuilder + bldsh = GchShBuilder + env['BUILDERS']['PrecompiledHeader'] = bld + env['BUILDERS']['PrecompiledHeaderShared'] = bldsh + + env['GCHCOM'] = '$CXX -o $TARGET -x c++-header -c $CXXFLAGS $_CCCOMCOM $SOURCE' + env['GCHSHCOM'] = '$CXX -o $TARGET -x c++-header -c $SHCXXFLAGS $_CCCOMCOM $SOURCE' + env['GCHSUFFIX'] = '.gch' + + for suffix in SCons.Util.Split('.c .C .cc .cxx .cpp .c++'): + env['BUILDERS']['StaticObject'].add_emitter( suffix, static_pch_emitter ) + env['BUILDERS']['SharedObject'].add_emitter( suffix, shared_pch_emitter ) + + +def exists(env): + return env.Detect('g++') diff --git a/admin/scons/Buildhelper.py b/admin/scons/Buildhelper.py index 02f17b2b4..38940424c 100644 --- a/admin/scons/Buildhelper.py +++ b/admin/scons/Buildhelper.py @@ -28,6 +28,8 @@ import fnmatch import re import tarfile +from SCons.Action import Action + # @@ -58,13 +60,13 @@ def srcSubtree(env,tree,isShared=False,builder=None, **args): else: builder = lambda f: env.Object(f, **args) - return [builder(f) for f in scanSrcSubtree(root)] + return [builder(f) for f in scanSubtree(root)] SRCPATTERNS = ['*.c','*.cpp','*.cc'] -def scanSrcSubtree(roots): +def scanSubtree(roots, patterns=SRCPATTERNS): """ first expand (possible) wildcards and filter out non-dirs. Then scan the given subtree for source filesnames (python generator function) @@ -73,7 +75,7 @@ def scanSrcSubtree(roots): for (dir,_,files) in os.walk(root): if dir.startswith('./'): dir = dir[2:] - for p in SRCPATTERNS: + for p in patterns: for f in fnmatch.filter(files, p): yield os.path.join(dir,f) @@ -102,22 +104,50 @@ def filterNodes(nlist, removeName=None): return filter(predicate, nlist) -def RegisterPrecompiledHeader_Builder(env): - """ Registeres an Custom Builder for generating a precompiled Header. - Note you should define a dependency to the PCH file - """ - def genCmdline(source, target, env, for_signature): - return '$CXXCOM -x c++-header %s' % source[0] - def fixSourceDependency(target, source, env): - print "precompiled header: %s --> %s" % (source[0],target[0]) - return (target, source) + +def getDirname(dir): + """ extract directory name without leading path """ + dir = os.path.realpath(dir) + if not os.path.isdir(dir): + dir,_ = os.path.split(dir) + _, name = os.path.split(dir) + return name - gchBuilder = env.Builder( generator = genCmdline - , emitter = fixSourceDependency - , suffix = '.gch' - , src_suffix = '.hpp' - ) - env.Append(BUILDERS = {'PrecompiledHeader' : gchBuilder}) + + +def RegisterIcon_Builder(env, renderer): + """ Registeres 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. + """ + renderer = __import__(renderer) # load python script for invoking the 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 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 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) diff --git a/admin/scons/LumieraEnvironment.py b/admin/scons/LumieraEnvironment.py index 82d419a65..2d8f1bb01 100644 --- a/admin/scons/LumieraEnvironment.py +++ b/admin/scons/LumieraEnvironment.py @@ -22,7 +22,8 @@ ##################################################################### -from SCons.SConf import SConf +import SCons +import SCons.SConf from SCons.Environment import Environment from Buildhelper import * @@ -77,17 +78,34 @@ class LumieraEnvironment(Environment): return libInfo def Glob (self, pattern): - """ temporary workaround; newer versions of SCons provide this as a global function - """ + """ temporary workaround; newer versions of SCons provide this as a global function """ pattern = self.subst(pattern) return glob.glob(pattern) + + def AddMethod (self, function): + """ temporary workaround; newer versions of SCons provide this as a global function """ + self.__dict__[function.__name__] = function.__get__(self) + + +#### temporary pre 1.0 SCons compatibility hack #### +_ver = map(int, SCons.__version__.split('.')) +_old = (_ver[0]<1 and _ver[1]<98) +if _old: + ConfigBase = SCons.SConf.SConf +else: + ConfigBase = SCons.SConf.SConfBase + del LumieraEnvironment.Glob + del LumieraEnvironment.AddMethod + # use the official impl present since SCons 0.98 + # use the new name of the config context base class -class LumieraConfigContext(SConf): + +class LumieraConfigContext(ConfigBase): """ Extends the SCons Configure context with some convenience methods """ def __init__(self, *args,**kw): - SConf.__init__(self,*args,**kw) + ConfigBase.__init__(self,*args,**kw) def CheckPkgConfig (self, libID, minVersion=0): print "Checking for library configuration: %s " % libID diff --git a/configure.ac b/configure.ac index e4279aa66..b5a61ab03 100644 --- a/configure.ac +++ b/configure.ac @@ -159,7 +159,9 @@ AC_CHECK_LIB(Xv, XvQueryAdaptors, , ############## Pkg Dependancies -PKG_CHECK_MODULES(GTK_LUMIERA, [gtkmm-2.4 >= 2.8 gdl-1.0 >= 0.6.1 cairomm-1.0 >= 0.6.0 gavl >= 0.2.5]) +PKG_CHECK_MODULES(GTK_LUMIERA, [ + gtkmm-2.4 >= 2.8 gdl-1.0 >= 0.6.1 cairomm-1.0 >= 0.6.0 + gavl >= 0.2.5 librsvg-2.0 >= 2.18.1]) AC_SUBST(GTK_LUMIERA_CFLAGS) AC_SUBST(GTK_LUMIERA_LIBS) diff --git a/doc/devel/.gitignore b/doc/devel/.gitignore index 96886436c..d6d649abd 100644 --- a/doc/devel/.gitignore +++ b/doc/devel/.gitignore @@ -1,2 +1,3 @@ ,doxylog +warnings.txt html/* diff --git a/doc/devel/Doxyfile b/doc/devel/Doxyfile index 1d6c5f87c..b7c59fa54 100644 --- a/doc/devel/Doxyfile +++ b/doc/devel/Doxyfile @@ -1,14 +1,14 @@ -# Doxyfile 1.5.1 +# Doxyfile 1.5.5 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = Lumiera -PROJECT_NUMBER = 3.0+alpha +PROJECT_NUMBER = 0.1+pre OUTPUT_DIRECTORY = CREATE_SUBDIRS = YES OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = NO ABBREVIATE_BRIEF = "The $name class" \ @@ -30,17 +30,23 @@ STRIP_FROM_PATH = ../../src/ \ STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES +QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO +DETAILS_AT_TOP = YES INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 4 ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO BUILTIN_STL_SUPPORT = YES +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -49,6 +55,7 @@ EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO @@ -58,8 +65,9 @@ CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES @@ -79,12 +87,13 @@ WARN_IF_UNDOCUMENTED = NO WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = YES WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = +WARN_LOGFILE = warnings.txt #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = ../../src/ \ ../../tests/ +INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.c \ *.cc \ *.cxx \ @@ -130,6 +139,7 @@ RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = YES EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO @@ -168,6 +178,10 @@ HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Lumiera Doxygen docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +HTML_DYNAMIC_SECTIONS = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO @@ -251,6 +265,7 @@ PERL_PATH = /usr/bin/perl # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES +MSCGEN_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES CLASS_GRAPH = YES @@ -267,8 +282,7 @@ DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 +DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 1000 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = YES diff --git a/doc/devel/draw/Lumi.Architecture-1.svg b/doc/devel/draw/Lumi.Architecture-1.svg index 9df05b7d3..40fab02c7 100644 --- a/doc/devel/draw/Lumi.Architecture-1.svg +++ b/doc/devel/draw/Lumi.Architecture-1.svg @@ -14,10 +14,10 @@ sodipodi:version="0.32" inkscape:version="0.45.1" version="1.0" - sodipodi:docbase="/home/hiv/devel/skizzen" - sodipodi:docname="Cin3.Architecture-1.svg" + sodipodi:docbase="/mnt/Lager/heim/devel/lumi/doc/devel/draw" + sodipodi:docname="Lumi.Architecture-1.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" - inkscape:export-filename="/home/hiv/devel/skizzen/Cin3.Architecture-1.png" + inkscape:export-filename="/home/hiv/devel/skizzen/Lumi.Architecture-1.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90"> + inkscape:window-y="28" + showgrid="true" + inkscape:grid-points="true" + inkscape:grid-bbox="false" + gridspacingx="2px" + gridspacingy="2px" + objecttolerance="50" + gridtolerance="10000" /> @@ -87,7 +94,7 @@ style="opacity:1;color:#000000;fill:#ececec;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="rect3136" width="449.55356" - height="142.91072" + height="144.89977" x="46.375008" y="369.10715" /> Defaults + y="267.42578">SessionDefaults Cache + width="119.99424" + height="29.96665" + x="159.96713" + y="480.03333" /> IO-Handling Storage Backend(s) + x="300" + y="480">Storage Backend(s) Plugins (Codecs, Effects,...) + y="355.89285" /> + y="232.85713" /> - - - - (re)-Building + + Plugin Loader + + + + + + Serializer + + + + + + + Defaults + + + + diff --git a/doc/devel/draw/LumiLogo.svg b/doc/devel/draw/LumiLogo.svg new file mode 100644 index 000000000..a4d60254d --- /dev/null +++ b/doc/devel/draw/LumiLogo.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + image/svg+xml + + Lumiera Logo + 8/2008 + + + Lumiera.org + + + + + + + + + + + + + + + + diff --git a/doc/devel/draw/high-level-model.svg b/doc/devel/draw/high-level-model.svg new file mode 100644 index 000000000..f5f0af8e5 --- /dev/null +++ b/doc/devel/draw/high-level-model.svg @@ -0,0 +1,3045 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + Lumiera: Anatomy of the high-level-model + + + Ichthyostega + + + 8/2008 + + + + + + + + + + + + + + + + + + ∑ + + + + + + + + + + + + + + + + + Proc + + + + + + + + x + + + + + + + + + + + + + + Tap + + + + + + + + + + + + + + + + + + + + W + + + + + + + + + + + + + + + + + + + + + + Transition + + + + + + + + + + + + + + + + + + + + + + + Clip + + + + + + + + + + + + W + t + + + + + + + + + + + + + + + + + + + + + + + + Auto + + + + + + + + + + + + + + + + + + + + + + + Chan1 + + + + Chan2 + + + + + + + + + + + + + + + + + + + + + x + + + + + + + + + + + + + + + + + + + + + + + + + + + W + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + x + + + + + + + + + + + + + + + + + x + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Meta + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + global Pipes + + + + EDL-1 + + + + EDL-2 + + + + + + + Anatomy of thehigh-level model + The model is an association of Media Objects, grouped to form Processing Pipes, which are a linear chain of data processing modules, starting from an source port and providing an exit point. Optionally, there may be a wiring plug, requesting the exit point to be connected to another pipe. When omitted, the wiring will be figured out automatically. Several pipes may be joined together by a transition, which in the general case simultaneously treats N media streams. Commonly, a transition simply combines two streams into one output. Individual Media Objects are attached, located or joined together by Placements. A Placement is a handle for a single MObject and contains a list of placement specifications, (called Locating Pin)Besides absolute and relative placement, there is also the possibility of a placement to stick directly to another MObject's placement, e.g. to attach an effect to a clip or to connect an automation data set to an effect. + + Actually a clip is handled as if it was comprised of local pipe(s). In the example shown here, a two-channel clip has three effects attached, plus a wiring plug. Each of those attachments is used only if applicable to the media stream type the respective pipe will process. Thus, effectively each channel (sub)clip gets its own specifically adapted processing pipe. + The Session contains several independent EDLs plus an output bus section (global Pipes). Each EDL holds a collection of MObjects placed within a Tree of Tracks. The wiring, if not defined locally within an MObject's placement, is derived by searching up this track tree and utilizing the wiring plug locating pins found there, if applicable. Besides routing to a global pipe, wiring plugs can also connect to the source port of an Meta-Clip. + diff --git a/doc/devel/uml/class132741.html b/doc/devel/uml/class132741.html index a9dd11ca8..89bb5e220 100644 --- a/doc/devel/uml/class132741.html +++ b/doc/devel/uml/class132741.html @@ -16,7 +16,7 @@ -

Declaration :

  • C++ : class State
  • Java : public interface State

Directly inherited by : InvocationStateBase StateAdapter StateProxy

+

Declaration :

  • C++ : class State
  • Java : public interface State

Directly inherited by : StateAdapter StateProxy

Artifact : stateproxy, Component(s) : Builder

Relation currFrame (<unidirectional association>)

Declaration :

  • Uml : # currFrame : Frame
  • C++ : protected: Frame * currFrame
diff --git a/doc/devel/uml/class142469.html b/doc/devel/uml/class142469.html index 31b631174..58c82f008 100644 --- a/doc/devel/uml/class142469.html +++ b/doc/devel/uml/class142469.html @@ -16,9 +16,8 @@ -

Declaration :

  • C++ : template<class WIRING, class POLICY> class StateProxy : public State, public InPlace
- -
Relation wiring (<unidirectional association>)

Declaration :

+

Declaration :

  • C++ : class StateProxy : public State
+

All public operations : allocateBuffer , fetch , isCalculated , releaseBuffer

diff --git a/doc/devel/uml/class142725.html b/doc/devel/uml/class142725.html index 13bdadf5b..93345b68f 100644 --- a/doc/devel/uml/class142725.html +++ b/doc/devel/uml/class142725.html @@ -17,5 +17,9 @@

Declaration :

  • C++ : class WiringDescriptor

Directly inherited by : NodeWiring

+
+ +
Operation callDown

Declaration :

  • Uml : + callDown(inout : State, in requiredOutput : uint) : , exceptions : BuffHandle
  • C++ : public: virtual callDown () throw (BuffHandle)
+

All public operations : callDown

diff --git a/doc/devel/uml/class143365.html b/doc/devel/uml/class143365.html index 8f96f6b27..c4e3718c3 100644 --- a/doc/devel/uml/class143365.html +++ b/doc/devel/uml/class143365.html @@ -16,7 +16,13 @@ -

Declaration :

-
+

Declaration :

+ +
Relation <association>

Declaration :

+
Relation <association>

Declaration :

+
Relation <association>

Declaration :

+
Relation <unidirectional association>

Declaration :

+
Operation callDown

Declaration :

  • Uml : + callDown() :
  • C++ : public: callDown ()
+

All public operations : callDown , callDown

diff --git a/doc/devel/uml/class143493.html b/doc/devel/uml/class143493.html index 63ef30fb2..37a6496d9 100644 --- a/doc/devel/uml/class143493.html +++ b/doc/devel/uml/class143493.html @@ -4,21 +4,18 @@ -Class InvocationStateBase +Class OperationBase -
Class InvocationStateBase
+
Class OperationBase

-

Declaration :

  • C++ : class InvocationStateBase : public State

Directly inherited by : Caching

-
-
-

All public operations : allocateBuffer , fetch , isCalculated , releaseBuffer

+

Declaration :

  • C++ : class OperationBase

Directly inherited by : FeedCache ProcessData ReadSource

diff --git a/doc/devel/uml/class143621.html b/doc/devel/uml/class143621.html index 39379446c..649d441e7 100644 --- a/doc/devel/uml/class143621.html +++ b/doc/devel/uml/class143621.html @@ -4,21 +4,20 @@ -Class Caching +Class QueryCache -
Class Caching
+
Class QueryCache

-

Declaration :

Directly inherited by : Process

+

Declaration :

Directly inherited by : Strategy

-

All public operations : allocateBuffer , fetch , isCalculated , releaseBuffer

diff --git a/doc/devel/uml/class143749.html b/doc/devel/uml/class143749.html index 2d3726110..426d12aaa 100644 --- a/doc/devel/uml/class143749.html +++ b/doc/devel/uml/class143749.html @@ -4,21 +4,21 @@ -Class Process +Class PullInput -
Class Process
+
Class PullInput

-

Declaration :

  • C++ : class Process : public Caching

Directly inherited by : InPlace

+

Declaration :

Directly inherited by : QueryCache Strategy

-
-

All public operations : allocateBuffer , fetch , isCalculated , releaseBuffer

+ +
Relation <association>

Declaration :

diff --git a/doc/devel/uml/class143877.html b/doc/devel/uml/class143877.html index b3164a70a..bad34df65 100644 --- a/doc/devel/uml/class143877.html +++ b/doc/devel/uml/class143877.html @@ -4,21 +4,20 @@ -Class InPlace +Class ReadSource -
Class InPlace
+
Class ReadSource

-

Declaration :

  • C++ : class InPlace : public Process

Directly inherited by : StateProxy

+

Declaration :

Directly inherited by : Strategy

-

All public operations : allocateBuffer , fetch , isCalculated , releaseBuffer

diff --git a/doc/devel/uml/class144005.html b/doc/devel/uml/class144005.html index 9fd2629bc..bc2bf60f2 100644 --- a/doc/devel/uml/class144005.html +++ b/doc/devel/uml/class144005.html @@ -4,19 +4,19 @@ -Class WiringTable +Class BuffTable -
Class WiringTable
+
Class BuffTable

-

Declaration :

  • C++ : template<int SIZ> class WiringTable
+

Declaration :

  • C++ : template<int SIZ> class BuffTable
Relation <directional aggregation by value>

Declaration :

Relation <unidirectional association>

Declaration :

diff --git a/doc/devel/uml/class144261.html b/doc/devel/uml/class144261.html new file mode 100644 index 000000000..d9c258fab --- /dev/null +++ b/doc/devel/uml/class144261.html @@ -0,0 +1,25 @@ + + + + + + +Class Invocation + + + + + +
Class Invocation
+

+ + + + +

Declaration :

  • C++ : class Invocation
+ +
Relation <unidirectional association>

Declaration :

+
Relation <unidirectional association>

Declaration :

+
Relation <unidirectional association>

Declaration :

+ + diff --git a/doc/devel/uml/class144389.html b/doc/devel/uml/class144389.html new file mode 100644 index 000000000..fb3f25daf --- /dev/null +++ b/doc/devel/uml/class144389.html @@ -0,0 +1,24 @@ + + + + + + +Class ProcessData + + + + + +
Class ProcessData
+

+ + + + +

Declaration :

Directly inherited by : PullInput

+
+ +
Relation <association>

Declaration :

+ + diff --git a/doc/devel/uml/class144517.html b/doc/devel/uml/class144517.html new file mode 100644 index 000000000..8eace63da --- /dev/null +++ b/doc/devel/uml/class144517.html @@ -0,0 +1,25 @@ + + + + + + +Class Strategy + + + + + +
Class Strategy
+

+ + + + +

Declaration :

+ +
Relation <association>

Declaration :

+
Relation <association>

Declaration :

+
Relation <association>

Declaration :

+ + diff --git a/doc/devel/uml/class144645.html b/doc/devel/uml/class144645.html new file mode 100644 index 000000000..c5cc7c0cb --- /dev/null +++ b/doc/devel/uml/class144645.html @@ -0,0 +1,23 @@ + + + + + + +Class FeedCache + + + + + +
Class FeedCache
+

+ + + + +

Declaration :

Directly inherited by : ProcessData

+
+
+ + diff --git a/doc/devel/uml/classes.html b/doc/devel/uml/classes.html index 7992c89cf..319577971 100644 --- a/doc/devel/uml/classes.html +++ b/doc/devel/uml/classes.html @@ -27,11 +27,11 @@ AutoAutomation data for some parameter (i.e. a time varying function) BackendCache BuffHandle +BuffTable Buildableinterface BuilderFacadeboundaryProvides unified access to the builder functionality. While individual components of the builder subsystem may be called if necessary or suitable, it is usually better to do all extern invocations via the high level methods of this Facade BuilderToolinterfaceUsed according to the visitor pattern: each Tool contains the concrete implementation for one task to be done to the various MObject classes BuildInstruct(Interface) building instructions to be executed by the Builder on the render node network under construction. -Caching Caller Categorytree like classification of Assets Clipbookkeeping (asset) view of a media clip. @@ -60,6 +60,7 @@ ExplicitPlacementinterface External Factorya template for generating functor-like Factory objects, used to encapsulate object creation and providing access via smart-pointers only. +FeedCache File FileHandle FileHandleCache @@ -74,10 +75,9 @@ FrameDescriptorinterfaceA FrameDescriptor implements the higher level interfaces for frames. Further refinements are made by subclassing and policy classes FrameReference GLBuf -InPlace InterpolatorProvides the implementation for getting the acutal value of a time varying or automated effect/plugin parameter Invalid -InvocationStateBase +Invocation Label Link LocatingPinAn element with value semantics, which actually implements the placement of some MObject by positioning it in some way. @@ -94,6 +94,7 @@ MutexI provided a reworked Mutex class in my Cinelerra2 repository NodeCreatorToolThis Tool implementation plays the central role in the buld process: given a MObject from Session, it is able to attach ProcNodes to the render engine under construction such as to reflect the properties of the MObject in the actual render. NodeWiring +OperationBase ParameterDescriptor and access object for a plugin parameter. Parameters may be provided with values from the session, and this values may be automated. ParamProviderinterfaceA facility to get the actual value of a plugin/effect parameter PathManagerWhile building a render engine, this Strategy class decides on the actual render strategy in accordance to the current controller settings (system state) @@ -105,13 +106,16 @@ Previewalternative version of the media data, probably with lower resolution Prockey abstraction: data processing asset ProcDispatcher -Process +ProcessData Processor ProcNodeinterfaceKey abstraction of the Render Engine: A Data processing Node ProcPattspecial type of structural Asset representing information how to build some part of the render engine's processing nodes network. ProjectorSpecial video processing node used to scale and translate image data. +PullInput +QueryCache QueryHandlerinterface QueryHandlerImpl +ReadSource RelativeLocation RelTypeenumthe possible kinds of RelativePlacements RenderEngine @@ -132,6 +136,7 @@ StateAdapter StateProxyimplementation std::exceptionauxiliary +Strategy Structkey abstraction: structural asset ThreadWe can basically reuse the Thread class design from Cinelerra2, Thread becomes a baseclass for all Threads Timedenotes a temporal position (time point), based on timeline start.

investigate posix.4 realtime timers, wrap these here @@ -147,7 +152,6 @@ VFrame Visitable WiringDescriptor -WiringTable Wish WriteBuffer WriteBufferPool diff --git a/doc/devel/uml/classes_list.html b/doc/devel/uml/classes_list.html index f89fb300a..8e8c2d9a6 100644 --- a/doc/devel/uml/classes_list.html +++ b/doc/devel/uml/classes_list.html @@ -28,11 +28,11 @@ Auto
BackendCache
BuffHandle
+BuffTable
Buildable
BuilderFacade
BuilderTool
BuildInstruct
-Caching
Caller
Category
Clip
@@ -61,6 +61,7 @@ ExplicitPlacement
External
Factory
+FeedCache
File
FileHandle
FileHandleCache
@@ -75,10 +76,9 @@ FrameDescriptor
FrameReference
GLBuf
-InPlace
Interpolator
Invalid
-InvocationStateBase
+Invocation
Label
Link
LocatingPin
@@ -95,6 +95,7 @@ Mutex
NodeCreatorTool
NodeWiring
+OperationBase
Parameter
ParamProvider
PathManager
@@ -106,13 +107,16 @@ Preview
Proc
ProcDispatcher
-Process
+ProcessData
Processor
ProcNode
ProcPatt
Projector
+PullInput
+QueryCache
QueryHandler
QueryHandlerImpl
+ReadSource
RelativeLocation
RelType
RenderEngine
@@ -133,6 +137,7 @@ StateAdapter
StateProxy
std::exception
+Strategy
Struct
Thread
Time
@@ -148,7 +153,6 @@ VFrame
Visitable
WiringDescriptor
-WiringTable
Wish
WriteBuffer
WriteBufferPool
diff --git a/doc/devel/uml/fig128005.png b/doc/devel/uml/fig128005.png index e9bef7624..4cae19a1d 100644 Binary files a/doc/devel/uml/fig128005.png and b/doc/devel/uml/fig128005.png differ diff --git a/doc/devel/uml/fig128901.png b/doc/devel/uml/fig128901.png index 6bb94e8cc..bd2b52fe1 100644 Binary files a/doc/devel/uml/fig128901.png and b/doc/devel/uml/fig128901.png differ diff --git a/doc/devel/uml/fig129029.png b/doc/devel/uml/fig129029.png index 6313cb7fb..3e8223916 100644 Binary files a/doc/devel/uml/fig129029.png and b/doc/devel/uml/fig129029.png differ diff --git a/doc/devel/uml/fig129285.png b/doc/devel/uml/fig129285.png index d8f8bec2e..c42d770d3 100644 Binary files a/doc/devel/uml/fig129285.png and b/doc/devel/uml/fig129285.png differ diff --git a/doc/devel/uml/fig130053.png b/doc/devel/uml/fig130053.png index 9cee6c87a..c25a4871d 100644 Binary files a/doc/devel/uml/fig130053.png and b/doc/devel/uml/fig130053.png differ diff --git a/doc/devel/uml/fig130821.png b/doc/devel/uml/fig130821.png index 8f9dab369..0c951bf06 100644 Binary files a/doc/devel/uml/fig130821.png and b/doc/devel/uml/fig130821.png differ diff --git a/doc/devel/uml/fig131973.png b/doc/devel/uml/fig131973.png index 78f068e2d..d16d88131 100644 Binary files a/doc/devel/uml/fig131973.png and b/doc/devel/uml/fig131973.png differ diff --git a/doc/devel/uml/fig132357.png b/doc/devel/uml/fig132357.png index e454c31e9..8f89db240 100644 Binary files a/doc/devel/uml/fig132357.png and b/doc/devel/uml/fig132357.png differ diff --git a/doc/devel/uml/index.html b/doc/devel/uml/index.html index de5e95e2f..1081df7d3 100644 --- a/doc/devel/uml/index.html +++ b/doc/devel/uml/index.html @@ -116,7 +116,7 @@ Documentation
Artifact Lumiera

Depends on common

Depends on gui

Depends on proc

Depends on backend

the main executable to be built

-

executable associated with : mobject, source, frame, placement, sessionimpl, builderfacade, controllerfacade, processor, pluginadapter, effect, buildertool, segmentationtool, aframe, assembler, trafo, explicitplacement, auto, glrender, link, parameter, renderengine, allocation, vframe, toolfactory, arender, renderstate, label, glbuf, procnode, stateproxy, hub, buildable, abstractmo, nodecreatertool, projector, interpolator, edl, fixture, glpipe, vrender, exitnode, pathmanager, track, paramprovider, mask, main, conmanager, clip, meta, fixedlocation, relativelocation

+

executable associated with : glbuf, procnode, stateproxy, hub, buildable, abstractmo, nodecreatertool, projector, interpolator, edl, fixture, glpipe, vrender, exitnode, pathmanager, track, paramprovider, mask, main, conmanager, clip, meta, fixedlocation, relativelocation, mobject, source, frame, placement, sessionimpl, builderfacade, controllerfacade, processor, pluginadapter, effect, buildertool, segmentationtool, aframe, assembler, trafo, explicitplacement, auto, glrender, link, parameter, renderengine, allocation, vframe, toolfactory, arender, renderstate, label

Artifact main

Artifact source

@@ -902,12 +902,16 @@ reuse exiting Engine

Selection :

    Transformation
    -
    -
    Class Caching
    -
    Class Process
    -
    Class InPlace
    -
    +
    +
    +
    Class PullInput
    +
    +
    +
    Class FeedCache
    +
    Class Strategy
    +
    Class BuffTable
    +

    diff --git a/doc/devel/uml/index_60.html b/doc/devel/uml/index_60.html index 8712d7074..a873c25b0 100644 --- a/doc/devel/uml/index_60.html +++ b/doc/devel/uml/index_60.html @@ -17,8 +17,8 @@ - + @@ -28,10 +28,10 @@ - - + + diff --git a/doc/devel/uml/index_65.html b/doc/devel/uml/index_65.html index ab57596c5..33d5ebd2f 100644 --- a/doc/devel/uml/index_65.html +++ b/doc/devel/uml/index_65.html @@ -55,12 +55,12 @@ - + - - + + diff --git a/doc/devel/uml/index_66.html b/doc/devel/uml/index_66.html index db64b33db..3a6ba7379 100644 --- a/doc/devel/uml/index_66.html +++ b/doc/devel/uml/index_66.html @@ -24,6 +24,7 @@ + @@ -36,8 +37,8 @@ - + diff --git a/doc/devel/uml/index_67.html b/doc/devel/uml/index_67.html index 1612ca9ea..8432e5cc6 100644 --- a/doc/devel/uml/index_67.html +++ b/doc/devel/uml/index_67.html @@ -19,7 +19,8 @@ - + + @@ -29,34 +30,34 @@ - - - - - - - + + + + + - - - + + + + + + + - - - - - - - - - - + + + + + + + + diff --git a/doc/devel/uml/index_69.html b/doc/devel/uml/index_69.html index 1f6fd3f19..a7245b34b 100644 --- a/doc/devel/uml/index_69.html +++ b/doc/devel/uml/index_69.html @@ -18,14 +18,14 @@
    NameKindDescription
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    <flow>transition
    Assetsclass view
    ATTACHattributeattach subject to anchor (e.g. an effect to a clip)
    au1class instance
    aud_aclass instance
    aud_Aclass instance
    aud_aclass instance
    audioclass instance
    audio1class instance
    audio1class instance
    audio1class instance
    audio1class instance
    audio1class instance
    autoartifactMedia Object holding automation data
    AutoclassAutomation data for some parameter (i.e. a time varying function)
    Automation Entitiesclass diagram
    BackendCacheclass
    BackendLayerpackage
    BuffHandleclass
    BuffTableclass
    buildoperation
    build flowactivity diagram
    build necessary?decision activity node
    buildableartifactmarker interface denoting any MObject able to be treated by Tools
    buildEngineoperationMain Operation of the Builder: create a render engine for a given part of the timeline
    Buildercomponent
    builderpackagesourcecode package

    The Builder creating the Render Engine,
    located within the MObject Subsystem
    Builderpackage
    builderpackagesourcecode package

    The Builder creating the Render Engine,
    located within the MObject Subsystem
    Builder Entitiesclass diagram
    Builder Workingsclass view
    BuilderFacadeclassProvides unified access to the builder functionality. While individual components of the builder subsystem may be called if necessary or suitable, it is usually better to do all extern invocations via the high level methods of this Facade
    NameKindDescription
    Cachecomponent
    Cachecomponent view
    Cachingclass
    callDownoperation
    callDownoperation
    Callerclass
    categoryrelationprimary tree like classification of the asset
    Categoryclasstree like classification of Assets
    chainrelationChain of additional Placements further constraining the position of this MObject
    checked_inrelationchecked_in objects are subject of cache aging and must be not in use
    checked_outrelationthis list keeps all mappings which are in use, and thus prevents them from Cache aging
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    class instanceclass instance
    clearoperationclear current session contents
    without resetting overall session config.
    Afterwards, the session will contain only one
    empty EDL, while all Assets are retained.
    client codecomponent
    Clipclassbookkeeping (asset) view of a media clip.
    - + - + diff --git a/doc/devel/uml/index_70.html b/doc/devel/uml/index_70.html index 5e1189dd5..56bc1daaf 100644 --- a/doc/devel/uml/index_70.html +++ b/doc/devel/uml/index_70.html @@ -18,6 +18,7 @@
    NameKindDescription
    edlartifactthe (high level) Edit Decision List within the current Session
    EDLclass
    EDLcomponent
    EDLclass
    EDL Example1object diagramA simple example showing how the actual objects are placed in the Fixture (=definitive playlist). It shows a Video and Audio clip placed on two tracks
    EDL Example2object diagramMore complex example showing the Object graph in the EDL and how it is linked into the Fixture to yield the actual locations. In this example, an HUE Effect is applied on a part of the Clip
    edlsrelation
    EffectclassEffect or media processing component
    effectartifactEffect or media processing component
    effectartifactEDL representation of a pluggable and automatable effect.
    effectartifactEffect or media processing component
    Effectclass
    elementsrelationrelevant MObjects comprising this segment. TODO: actually necessary??
    enableoperationchange the enabled status of this asset. Note the corresponding #isActive predicate may depend on the enablement status of parent assets as well
    + diff --git a/doc/devel/uml/index_72.html b/doc/devel/uml/index_72.html index 3547e6f3e..7e5b73a00 100644 --- a/doc/devel/uml/index_72.html +++ b/doc/devel/uml/index_72.html @@ -23,8 +23,8 @@ - +
    NameKindDescription
    Factoryclassa template for generating functor-like Factory objects, used to encapsulate object creation and providing access via smart-pointers only.
    FeedCacheclass
    fetchoperation
    Fileclass
    filerelation
    Hierarchyclass diagramLumiera Exception hierarchy
    howtoProcoperation@return descriptor how to build a render pipeline corresponding to this media
    hubartifactspecial ProcNode used to build data distributing connections
    HUEclass instance
    HUEclass instance
    HUEclass instance
    diff --git a/doc/devel/uml/index_73.html b/doc/devel/uml/index_73.html index 9a0a77429..e127cf07e 100644 --- a/doc/devel/uml/index_73.html +++ b/doc/devel/uml/index_73.html @@ -20,10 +20,9 @@ idattributeAsset primary key. In Memory Databaseclass diagram inFixtureactivity action pin -InPlaceclass -inputclass instance -inputclass instance inputclass instance +inputclass instance +inputclass instance instanceoperation instructionsrelation Interfaceclass view @@ -32,7 +31,7 @@ interpolatorartifactdenotes a facility to get (continuously interpolated) parameter values InterpolatorclassProvides the implementation for getting the acutal value of a time varying or automated effect/plugin parameter Invalidclass -InvocationStateBaseclass +Invocationclass iporelation isActiveoperationweather this asset is swithced on and consequently included in the fixture and participates in rendering isCalculatedoperation diff --git a/doc/devel/uml/index_77.html b/doc/devel/uml/index_77.html index 1428ef6eb..e6d8e8031 100644 --- a/doc/devel/uml/index_77.html +++ b/doc/devel/uml/index_77.html @@ -33,8 +33,8 @@ MediaFactoryclassspecialized Asset Factory for configuring (new) media asset instances based on existing media files on disk; can create placeholder assets as well merge activity nodemerge activity node Metaclasskey abstraction: metadata and organisational asset -metaartifactabstract base class of all MObjects representing meta data or processing instructions metaartifactkey abstraction: metadata and organisational asset +metaartifactabstract base class of all MObjects representing meta data or processing instructions Metaclass mobjectartifactKey Abstraction: A Media Object in the Session mobjectpackagesourcecode package

    MObject Subsystem
    including the Session (EDL), Builder and Processing Controller diff --git a/doc/devel/uml/index_79.html b/doc/devel/uml/index_79.html index d1fdc83c0..e17eadde8 100644 --- a/doc/devel/uml/index_79.html +++ b/doc/devel/uml/index_79.html @@ -18,6 +18,7 @@ + diff --git a/doc/devel/uml/index_80.html b/doc/devel/uml/index_80.html index a3268b59b..368babe6a 100644 --- a/doc/devel/uml/index_80.html +++ b/doc/devel/uml/index_80.html @@ -53,8 +53,8 @@ - + @@ -67,6 +67,7 @@ +
    NameKindDescription
    offsetattributeOffset the actual position by this (time) value relative to the anchor point. TODO: Representation?
    OperationBaseclass
    orgattributeorigin or authorship id. Can be a project abbreviation, a package id or just the authors nickname or UID. This allows for the compnent name to be more generic (e.g. "blur"). Default for all assets provided by the core Lumiera codebase is "lumi".
    ouputclass instance
    ouputclass instance
    Proc-Asset Relationsclass diagram
    proc-componentscomponent diagram
    ProcDispatcherclass
    Processclass
    processoperation
    ProcessDataclass
    ProcessingLayerpackage
    Processorclass
    processorartifacta single render pipeline for one segment of the timeline
    projectorartifactvideo ProcNode for scaling and translating image data
    providerrelation
    pulloperation
    PullInputclass
    diff --git a/doc/devel/uml/index_81.html b/doc/devel/uml/index_81.html index 5a521bd2f..6367201fd 100644 --- a/doc/devel/uml/index_81.html +++ b/doc/devel/uml/index_81.html @@ -20,6 +20,7 @@ queryclass view Query System overviewcomponent view query useuse case view +QueryCacheclass QueryHandlerclass QueryHandlerImplclass diff --git a/doc/devel/uml/index_82.html b/doc/devel/uml/index_82.html index b5b305e10..9b107d854 100644 --- a/doc/devel/uml/index_82.html +++ b/doc/devel/uml/index_82.html @@ -17,14 +17,15 @@ + - + diff --git a/doc/devel/uml/index_83.html b/doc/devel/uml/index_83.html index 5dd747140..4ea8bf79b 100644 --- a/doc/devel/uml/index_83.html +++ b/doc/devel/uml/index_83.html @@ -32,8 +32,8 @@ - + @@ -47,8 +47,8 @@ - + @@ -64,6 +64,7 @@ + diff --git a/doc/devel/uml/index_84.html b/doc/devel/uml/index_84.html index b0541e88b..96532f18f 100644 --- a/doc/devel/uml/index_84.html +++ b/doc/devel/uml/index_84.html @@ -42,13 +42,13 @@ - + - +
    NameKindDescription
    ReadSourceclass
    refPointclass instance
    regoperationregisters an asset object in the internal DB, providing its unique key
    registryrelation@internal Table or DB holding all registered asset instances.
    relativelocationartifactPlacement implemnetaion providing various ways of attaching a MObject to another one
    RelativeLocationclass
    releaseBufferoperation
    relTypeattributethe kind of relation denoted by this Placement
    RelTypeclassthe possible kinds of RelativePlacements
    relTypeattributethe kind of relation denoted by this Placement
    removeoperationremove the given asset <i>together with all its dependants</i> from the internal DB
    Render Entitiesclass diagram
    Render Mechanicsclass diagram
    Service Componentsclass view
    Sessioncomponent
    sessionartifactInterface: the session edited by the user
    sessionpackagesourcecode package

    Everything concerning the EDL and Session, within the MObject Subsystem
    Sessionclass view
    sessionpackagesourcecode package

    Everything concerning the EDL and Session, within the MObject Subsystem
    SessionclassPrimary Interface for all editing tasks.
    The session contains defaults, all the assets being edited, and a set of EDL with the individual MObjects to be manipulated and rendered.
    Session structureclass diagram
    sessionimplartifactholds the complete session data to be edited by the user
    SimpleClipclassElementary clip consisting of only one media stream
    SmartPointerclass
    SmartPointersclass view
    sourcerelationmedia source of this clip
    sourcerelationthe media source this clip referes to
    sourcerelationmedia source of this clip
    SourceclassSource Node: represents a media source to pull data from.
    sourceartifactRepresentation of a Media source
    Source Overviewdeployment diagram
    StateProxyclass
    stateproxyartifactKey Interface representing a render process and encapsulating state
    std::exceptionclass
    Strategyclass
    Structclasskey abstraction: structural asset
    structartifactkey abstraction: structural asset
    Struct-Asset Relationsclass diagram
    trafoartifacttransforming processing Node
    treatoperation
    treatoperationThis operation is to be overloaded for the specific MObject subclasses to be treated.
    treatoperation
    treatoperation
    treatoperation
    treatoperation
    treatoperation
    treatoperation
    treatoperation
    treatoperation
    treatoperation
    TypeHandlerclass
    TypeHandler<Pipe>class
    diff --git a/doc/devel/uml/index_86.html b/doc/devel/uml/index_86.html index cda6a585e..3538c8202 100644 --- a/doc/devel/uml/index_86.html +++ b/doc/devel/uml/index_86.html @@ -22,18 +22,18 @@ vframeartifacta buffer and render process holding a Video frame vid1class instance vid_Aclass instance -vid_aclass instance +vid_aclass instance vid_Aclass instance vid_Aclass instance -vid_aclass instance -videoclass instance -videoclass instance +vid_aclass instance videoclass instance +videoclass instance videoclass instance +videoclass instance video1class instance -video1class instance video1class instance video1class instance +video1class instance video1class instance video1class instance Visitableclass diff --git a/doc/devel/uml/index_87.html b/doc/devel/uml/index_87.html index 7e2b7e31f..616839a54 100644 --- a/doc/devel/uml/index_87.html +++ b/doc/devel/uml/index_87.html @@ -20,9 +20,7 @@ whatoperation whatoperationthe base class of all exceptions thrown by the standard library when to queryuse case diagram -wiringrelation WiringDescriptorclass -WiringTableclass wiringTemplaterelation wishartifactLocatingPin representing a low-priority directive by the user,
    to be fulfilled only if possible (and after satisfying the
    more important LocatingPins) Wishclass diff --git a/doc/devel/uml/public_operations.html b/doc/devel/uml/public_operations.html index c252030f0..07fb079d7 100644 --- a/doc/devel/uml/public_operations.html +++ b/doc/devel/uml/public_operations.html @@ -23,6 +23,8 @@ buildAssembler buildEngineBuilderFacadeMain Operation of the Builder: create a render engine for a given part of the timeline buildProcessorPathManager +callDownNodeWiring +callDownWiringDescriptor chainPlacementcreate and add another Placement for this media object, thus increasingly constraining the (possible) position of this object. clearSessManagerclear current session contents
    without resetting overall session config.
    Afterwards, the session will contain only one
    empty EDL, while all Assets are retained.
    configureToolFactory @@ -67,12 +69,12 @@ saveSessManagercreate a complete, serialized representation
    of the current session config and contents.
    @todo how to serialize, prameters, return value? treatApplicable treatBuilderToolThis operation is to be overloaded for the specific MObject subclasses to be treated. -treatNodeCreatorTool treatNodeCreatorTool treatNodeCreatorTool +treatNodeCreatorTool treatNodeCreatorTool -treatSegmentationTool treatSegmentationTool +treatSegmentationTool treatSegmentationTool useFileFileProviderAnnounces that the application intends to use this file with mode (READ|WRITE|READWRITE) useTemporaryStorageFileProviderProvides a pool for interminate frames diff --git a/icons/Makefile.am b/icons/Makefile.am new file mode 100644 index 000000000..6693b6d1d --- /dev/null +++ b/icons/Makefile.am @@ -0,0 +1,65 @@ +# Copyright (C) Lumiera.org +# 2008, Joel Holdsworth +# +# 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. + +svgdir = $(top_srcdir)/icons/svg +prerendereddir = $(top_srcdir)/icons/prerendered +icondir = $(top_builddir) +iconcommand = python $(top_srcdir)/admin/render-icon.py + +16x16 = $(icondir)/16x16 +22x22 = $(icondir)/22x22 +24x24 = $(icondir)/24x24 +32x32 = $(icondir)/32x32 +48x48 = $(icondir)/48x48 + +16x16pre = $(prerendereddir)/16x16 +22x22pre = $(prerendereddir)/22x22 +24x24pre = $(prerendereddir)/24x24 +32x32pre = $(prerendereddir)/32x32 +48x48pre = $(prerendereddir)/48x48 + +lumigui_DEPENDENCIES += \ + rsvg-convert \ + $(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png \ + $(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png \ + $(16x16)/panel-assets.png $(22x22)/panel-assets.png $(32x32)/panel-assets.png \ + $(16x16)/panel-timeline.png \ + $(16x16)/panel-viewer.png $(22x22)/panel-viewer.png $(32x32)/panel-viewer.png + +$(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png : $(svgdir)/tool-arrow.svg + $(iconcommand) $< $(icondir) +$(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png : $(svgdir)/tool-i-beam.svg + $(iconcommand) $< $(icondir) + +$(16x16)/panel-assets.png: + cp $(16x16pre)/panel-assets.png $(16x16) +$(22x22)/panel-assets.png: + cp $(22x22pre)/panel-assets.png $(22x22) +$(32x32)/panel-assets.png: + cp $(32x32pre)/panel-assets.png $(32x32) + +$(16x16)/panel-timeline.png: + cp $(16x16pre)/panel-timeline.png $(16x16) + +$(16x16)/panel-viewer.png: + cp $(16x16pre)/panel-viewer.png $(16x16) +$(22x22)/panel-viewer.png: + cp $(22x22pre)/panel-viewer.png $(22x22) +$(32x32)/panel-viewer.png: + cp $(32x32pre)/panel-viewer.png $(32x32) + + diff --git a/icons/assets-panel.png b/icons/prerendered/16x16/panel-assets.png similarity index 100% rename from icons/assets-panel.png rename to icons/prerendered/16x16/panel-assets.png diff --git a/icons/timeline-panel.png b/icons/prerendered/16x16/panel-timeline.png similarity index 100% rename from icons/timeline-panel.png rename to icons/prerendered/16x16/panel-timeline.png diff --git a/icons/viewer-panel.png b/icons/prerendered/16x16/panel-viewer.png similarity index 100% rename from icons/viewer-panel.png rename to icons/prerendered/16x16/panel-viewer.png diff --git a/icons/prerendered/22x22/panel-assets.png b/icons/prerendered/22x22/panel-assets.png new file mode 100644 index 000000000..dc7628738 Binary files /dev/null and b/icons/prerendered/22x22/panel-assets.png differ diff --git a/icons/prerendered/22x22/panel-viewer.png b/icons/prerendered/22x22/panel-viewer.png new file mode 100644 index 000000000..58fc213ec Binary files /dev/null and b/icons/prerendered/22x22/panel-viewer.png differ diff --git a/icons/prerendered/32x32/panel-assets.png b/icons/prerendered/32x32/panel-assets.png new file mode 100644 index 000000000..4b55b504a Binary files /dev/null and b/icons/prerendered/32x32/panel-assets.png differ diff --git a/icons/prerendered/32x32/panel-viewer.png b/icons/prerendered/32x32/panel-viewer.png new file mode 100644 index 000000000..b449f37a5 Binary files /dev/null and b/icons/prerendered/32x32/panel-viewer.png differ diff --git a/icons/svg/tool-arrow.svg b/icons/svg/tool-arrow.svg new file mode 100644 index 000000000..026b6633f --- /dev/null +++ b/icons/svg/tool-arrow.svg @@ -0,0 +1,732 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/svg/tool-i-beam.svg b/icons/svg/tool-i-beam.svg new file mode 100644 index 000000000..7f26e1d55 --- /dev/null +++ b/icons/svg/tool-i-beam.svg @@ -0,0 +1,690 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 965ac6079..29d794f7a 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -40,11 +40,11 @@ liblumicommon_a_SOURCES = \ noinst_HEADERS += \ $(liblumicommon_a_srcdir)/cmdline.hpp \ $(liblumicommon_a_srcdir)/factory.hpp \ + $(liblumicommon_a_srcdir)/frameid.hpp \ $(liblumicommon_a_srcdir)/singleton.hpp \ $(liblumicommon_a_srcdir)/singletonpolicies.hpp \ $(liblumicommon_a_srcdir)/singletonpreconfigure.hpp \ $(liblumicommon_a_srcdir)/lumitime.hpp \ - $(liblumicommon_a_srcdir)/typelist.hpp \ $(liblumicommon_a_srcdir)/visitor.hpp \ $(liblumicommon_a_srcdir)/visitordispatcher.hpp \ $(liblumicommon_a_srcdir)/visitorpolicies.hpp \ @@ -56,7 +56,10 @@ noinst_HEADERS += \ $(liblumicommon_a_srcdir)/query/mockconfigrules.hpp \ $(liblumicommon_a_srcdir)/singletonfactory.hpp \ $(liblumicommon_a_srcdir)/singletonsubclass.hpp \ - $(liblumicommon_a_srcdir)/typelistutil.hpp \ + $(liblumicommon_a_srcdir)/meta/typelist.hpp \ + $(liblumicommon_a_srcdir)/meta/configflags.hpp \ + $(liblumicommon_a_srcdir)/meta/generator.hpp \ + $(liblumicommon_a_srcdir)/meta/typelistutil.hpp \ $(liblumicommon_a_srcdir)/util.hpp \ $(liblumicommon_a_srcdir)/test/mockinjector.hpp \ $(liblumicommon_a_srcdir)/test/suite.hpp \ diff --git a/src/common/cmdline.cpp b/src/common/cmdline.cpp index dec1a0620..eca0b18bb 100644 --- a/src/common/cmdline.cpp +++ b/src/common/cmdline.cpp @@ -52,7 +52,7 @@ namespace util /** create as a tokenized copy of the current commandline. * Note that argv[0] is allways ignored. */ - Cmdline::Cmdline (int argc, char* argv[]) + Cmdline::Cmdline (int argc, const char** argv) : vector (noneg(argc-1)) { for (int i=1; i (&cause); if (err) - if (isnil (err->cause_)) - return cause.what(); // cause is root cause - else - return err->cause_; // cause was caused by another exception + { + if (isnil (err->cause_)) + return cause.what(); // cause is root cause + else + return err->cause_; // cause was caused by another exception + } // unknown other exception type return cause.what (); diff --git a/src/proc/frame.hpp b/src/common/frameid.hpp similarity index 50% rename from src/proc/frame.hpp rename to src/common/frameid.hpp index 239987e97..9cb95eb37 100644 --- a/src/proc/frame.hpp +++ b/src/common/frameid.hpp @@ -1,5 +1,5 @@ /* - FRAME.hpp - Key Abstraction: render process and buffer holding frame data. + FRAMEID.hpp - distinct identification of a single data frame Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -21,26 +21,36 @@ */ -#ifndef PROC_INTERFACE_FRAME_H -#define PROC_INTERFACE_FRAME_H +#ifndef LUMIERA_FRAMEID_H +#define LUMIERA_FRAMEID_H -namespace proc_interface +namespace lumiera { /** - * TODO: how to relate to Cehteh's Frame entity in the Backend? - * The latter is the fundamental Frame entity, wheras this Object - * rather represents a buffer set containing frame date. + * Identification tuple for addressing frames unambiguosly. + * + * @todo currently (7/08) this is a dummy implementation to find out + * what interface the Proc layer needs. Probably the backend will + * later on define what is actually needed; this header should then + * be replaced by a combined C/C++ header */ - class Frame + class FrameID : boost::totally_ordered { - ///////////////// + long dummy; + public: + FrameID(long dum=0) : dummy(dum) {} + operator long () { return dummy; } + + bool operator< (const FrameID& of) const { return dummy < of.dummy; } + bool operator== (const FrameID& of) const { return dummy == of.dummy; } }; - - -} // namespace proc_interface + + + +} // namespace lumiera #endif diff --git a/src/common/meta/configflags.hpp b/src/common/meta/configflags.hpp new file mode 100644 index 000000000..c63552855 --- /dev/null +++ b/src/common/meta/configflags.hpp @@ -0,0 +1,191 @@ +/* + CONFIGFLAGS.hpp - Building classes based on configuration cases + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 configflags.hpp + ** Under some circumstances it is necessary to assemble functionality + ** out of elementary building blocks. Especially, this assembly can be + ** expressed as template specialisations directed by a configuration type. + ** Thus, the purpose of this header is to encode flag-like configuraitons + ** as distinct types, which can be used to select such specialisations. + ** Each possible configuration can be encoded as a list of flags, which allows + ** to generate, filter and process those configurations. The final goal is to + ** automatically generate a factory which is able to deliver objects + ** configured according to the situation encoded in the flags. + ** + ** @note currently there is an inherent limitation to configurations defined by + ** a maximum of 5 independant flags. While it is easy to increase this limit, + ** you should consider that the final goal is to genarate template instantiations, + ** which would lead to more and more code bloat with growing number of possible + ** combination. + ** + ** @see proc::engine::config::Strategy usage example + ** @see proc::engine::config::ConfigSelector + ** @see typelist.hpp + ** + */ + + +#ifndef LUMIERA_META_CONFIGFLAGS_H +#define LUMIERA_META_CONFIGFLAGS_H + + +#include "common/meta/typelist.hpp" + + +namespace lumiera { + namespace typelist { + + const size_t CONFIG_FLAGS_MAX = 5; + + + template struct Flag { typedef Flag ID; }; + template<> struct Flag<0> { typedef NullType ID; }; + + + template< char f1=0 + , char f2=0 + , char f3=0 + , char f4=0 + , char f5=0 + > + struct Flags + { + typedef typename Types< typename Flag::ID + , typename Flag::ID + , typename Flag::ID + , typename Flag::ID + , typename Flag::ID + >::List + Tuple; + typedef Tuple List; + }; + + + template< char f1=0 + , char f2=0 + , char f3=0 + , char f4=0 + , char f5=0 + > + struct Config ///< distinct type representing a configuration + { + typedef typename Flags::Tuple Flags; + typedef Flags List; + }; + + + + template + struct ConfigSetFlag; ///< set (prepend) the Flag to the given config + + template< char Fl + , char f1 + , char f2 + , char f3 + , char f4 + , char IGN + > + struct ConfigSetFlag > + { + typedef typelist::Config Config; + }; + + + + /** build a configuration type from a list-of-flags */ + template > + struct BuildConfigFromFlags + { + typedef CONF Config; + typedef Config Type; + }; + template + struct BuildConfigFromFlags< Node,FLAGS>, CONF> + { + typedef typename ConfigSetFlag< Fl + , typename BuildConfigFromFlags::Config + >::Config Config; + typedef Config Type; + }; + /** create a configuration type for the given list-of-flags */ + template + struct DefineConfigByFlags : BuildConfigFromFlags { }; + + + /** + * Helper for calculating values and for + * invoking runtime code based on a given FlagTuple. + * Can also be used on a Typelist of several Configs. + * The latter case is typically used to invoke an operation + * while ennumerating all Flag-Configurations defined in Code. + * An example would be to build (at runtime) an dispatcher table. + * Explanation: For the Case covering a List of Configs, we provide + * a templated visitaion function, which can accept a functor object + * to be invoked on each Configuration. + */ + template + struct FlagInfo; + + template + struct FlagInfo, FLAGS> > + { + enum{ BITS = MAX(ff, FlagInfo::BITS) + , CODE = (1<::CODE + }; + }; + template<> + struct FlagInfo + { + enum{ BITS = 0 + , CODE = 0 + }; + + template + static typename FUNC::Ret + accept (FUNC& functor) + { + return functor.done(); + } + }; + template + struct FlagInfo > + { + typedef typename CONF::Flags ThisFlags; + enum{ BITS = MAX (char(FlagInfo::BITS), char(FlagInfo::BITS)) + }; + + template + static typename FUNC::Ret + accept (FUNC& functor) + { + functor.template visit(FlagInfo::CODE); + return FlagInfo::accept (functor); + } + }; + + + + } // namespace typelist + +} // namespace lumiera +#endif diff --git a/src/common/typelistutil.hpp b/src/common/meta/generator.hpp similarity index 86% rename from src/common/typelistutil.hpp rename to src/common/meta/generator.hpp index 3fb6a531e..59f340b5d 100644 --- a/src/common/typelistutil.hpp +++ b/src/common/meta/generator.hpp @@ -1,5 +1,5 @@ /* - TYPELISTUTIL.hpp - metaprogramming utilities for lists-of-types + GENERATOR.hpp - metaprogramming utilities for generating classes and interfaces Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -38,7 +38,7 @@ This code is heavily inspired by */ -/** @file typelistutil.hpp +/** @file generator.hpp ** Helpers for working with lumiera::typelist::Types (i.e. lists-of-types). ** The main purpose is to build interfaces and polymorphic implementations ** (using virtual functions) based on templated Types or Collections of types, @@ -50,10 +50,10 @@ This code is heavily inspired by */ -#ifndef LUMIERA_TYPELISTUTIL_H -#define LUMIERA_TYPELISTUTIL_H +#ifndef LUMIERA_META_GENERATOR_H +#define LUMIERA_META_GENERATOR_H -#include "common/typelist.hpp" +#include "common/meta/typelist.hpp" @@ -196,42 +196,6 @@ namespace lumiera }; - /** - * Metafunction counting the number of Types in the collection - */ - template - struct count; - template<> - struct count - { - enum{ value = 0 }; - }; - template - struct count > - { - enum{ value = 1 + count::value }; - }; - - /** - * Metafunction " max( sizeof(T) ) for T in TYPES " - */ - template - struct maxSize; - template<> - struct maxSize - { - enum{ value = 0 }; - }; - template - struct maxSize > - { - enum{ thisval = sizeof(TY) - , nextval = maxSize::value - , value = nextval > thisval? nextval:thisval - }; - }; - - } // namespace typelist } // namespace lumiera diff --git a/src/common/typelist.hpp b/src/common/meta/typelist.hpp similarity index 94% rename from src/common/typelist.hpp rename to src/common/meta/typelist.hpp index f358a605e..c2d4568d0 100644 --- a/src/common/typelist.hpp +++ b/src/common/meta/typelist.hpp @@ -53,8 +53,8 @@ This code is heavily inspired by */ -#ifndef LUMIERA_TYPELIST_H -#define LUMIERA_TYPELIST_H +#ifndef LUMIERA_META_TYPELIST_H +#define LUMIERA_META_TYPELIST_H @@ -64,11 +64,15 @@ namespace lumiera namespace typelist { - class NullType { }; + class NullType + { + typedef NullType List; + }; template struct Node { + typedef Node List; typedef H Head; typedef T Tail; }; @@ -113,6 +117,8 @@ namespace lumiera }; + typedef Node NodeNull; + } // namespace typelist diff --git a/src/common/meta/typelistutil.hpp b/src/common/meta/typelistutil.hpp new file mode 100644 index 000000000..3a0d56284 --- /dev/null +++ b/src/common/meta/typelistutil.hpp @@ -0,0 +1,213 @@ +/* + TYPELISTUTIL.hpp - Utils for working with lists-of-types + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 LUMIERA_META_TYPELISTUTIL_H +#define LUMIERA_META_TYPELISTUTIL_H + + + +#include "common/meta/typelist.hpp" + +namespace lumiera { + namespace typelist { + + + /** + * Metafunction counting the number of Types in the collection + */ + template + struct count; + template<> + struct count + { + enum{ value = 0 }; + }; + template + struct count > + { + enum{ value = 1 + count::value }; + }; + + /** + * Metafunction " max( sizeof(T) ) for T in TYPES " + */ + template + struct maxSize; + template<> + struct maxSize + { + enum{ value = 0 }; + }; + template + struct maxSize > + { + enum{ thisval = sizeof(TY) + , nextval = maxSize::value + , value = nextval > thisval? nextval:thisval + }; + }; + + + /** apply a transformation (template) to each type in the list */ + template class _TRANS_> + struct Apply { typedef TY List; }; + + template< class TY, class TYPES + , template class _TRANS_ + > + struct Apply, _TRANS_ > { typedef Node< typename _TRANS_::Type + , typename Apply::List + > List; }; + + + template + struct CondNode { typedef TAIL Next; }; + + template + struct CondNode { typedef Node Next; }; + + /** filter away those types which don't fulfill a predicate metafunction */ + template< class TYPES + , template class _P_ ///< a template providing a boolean member \c ::value + > + struct Filter; + + template class _P_> + struct Filter { typedef NullType List; }; + + template< class TY, class TYPES + , template class _P_ + > + struct Filter,_P_> { typedef typename CondNode< _P_::value + , TY + , typename Filter::List + >::Next + List; }; + + + /** append lists-of-types */ + template + struct Append { typedef Node::List> List; }; + + template< class TY, class TYPES + , class TAIL + > + struct Append, TAIL> { typedef Node::List> List; }; + + template + struct Append > { typedef Node List; }; + + template + struct Append, NullType> { typedef Node List; }; + + template + struct Append { typedef Node List; }; + + template + struct Append { typedef Node List; }; + + template<> + struct Append { typedef NullType List; }; + + + + /** + * prefix each of the elements, + * yielding a list-of lists-of-types + */ + template + struct PrefixAll { typedef Node< typename Append::List, NullType> List; }; + + template + struct PrefixAll { typedef NullType List; }; + + template + struct PrefixAll { typedef Node< typename Append::List, NullType> List; }; + + template< class T + , class TY, class TYPES + > + struct PrefixAll > { typedef Node< typename Append::List + , typename PrefixAll::List + > List; }; + + + + + template + struct Distribute { typedef typename PrefixAll::List List; }; + + template + struct Distribute { typedef NullType List; }; + + template< class TY, class TYPES + , class TAIL + > + struct Distribute,TAIL> { typedef typename Append< typename PrefixAll::List + , typename Distribute::List + >::List + List; }; + + + + /** use a permutation generator + * for creating a list of all possible combinations + */ + template< class X + , template class _PERMU_> + struct Combine { typedef typename Distribute< typename _PERMU_::List + , Node + >::List List; }; + template< template class _PERMU_> + struct Combine { typedef Node List; }; + + template< class TY, class TYPES + , template class _PERMU_> + struct Combine,_PERMU_> { typedef typename Distribute< typename _PERMU_::List + , typename Combine::List + >::List List; }; + + /** permutation generator for the Combine metafunction, + * yielding an "on" and "off" case + */ + template + struct FlagOnOff + { + typedef Node > List; + }; + + + /** generate all possible on-off combinations of the given flags */ + template + struct CombineFlags + { + typedef typename Combine::List List; + }; + + + + + } // namespace typelist + +} // namespace lumiera +#endif diff --git a/src/common/meta/util.hpp b/src/common/meta/util.hpp new file mode 100644 index 000000000..b01a412fa --- /dev/null +++ b/src/common/meta/util.hpp @@ -0,0 +1,76 @@ +/* + UTIL.hpp - metaprogramming helpers and utilities + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 LUMIERA_META_UTIL_H +#define LUMIERA_META_UTIL_H + + + +namespace lumiera { + + + /* types for figuring out the overload resolution chosen by the compiler */ + + typedef char Yes_t; + struct No_t { char padding[8]; }; + + + + namespace typelist { + + /** semi-automatic detection if an instantiation is possible. + * Requires help by the template to be tested, which needs to define + * a typedef member \c is_defined. The embedded metafunction Test can be used + * as a predicate for filtering types which may yield a valid instantiation + * of the candidate template in question. + * \par + * A fully automated solution for this problem is impossible by theoretic reasons. + * Any non trivial use of such a \c is_defined trait would break the "One Definition Rule", + * as the state of any type can change from "partially defined" to "fully defined" over + * the course of any translation unit. Thus, even if there may be a \em solution out there, + * we can expect it to break at some point by improvements/fixes to the C++ Language. + */ + template class _CandidateTemplate_> + struct Instantiation + { + + template + class Test + { + typedef _CandidateTemplate_ Instance; + + template + static Yes_t check(typename U::is_defined *); + template + static No_t check(...); + + public: + static const bool value = (sizeof(Yes_t)==sizeof(check(0))); + }; + }; + + + } // namespace typelist + +} // namespace lumiera +#endif diff --git a/src/common/util.hpp b/src/common/util.hpp index 7f8704554..c71ba3b6a 100644 --- a/src/common/util.hpp +++ b/src/common/util.hpp @@ -237,4 +237,8 @@ namespace util * and we probably will enforce this design rule in future. */ #define INSTANCEOF(CLASS, EXPR) (dynamic_cast (EXPR)) +/** the inevitalbe MAX macro, sometimes still necessary in template code */ +#define MAX(A,B) (A < B) ? (B) : (A) + + #endif /*UTIL_HPP_*/ diff --git a/src/common/variant.hpp b/src/common/variant.hpp index 561b7149c..751c2d9fc 100644 --- a/src/common/variant.hpp +++ b/src/common/variant.hpp @@ -41,7 +41,8 @@ #define LUMIERA_VARIANT_H -#include "common/typelistutil.hpp" +#include "common/meta/typelistutil.hpp" +#include "common/meta/generator.hpp" #include diff --git a/src/common/visitor.hpp b/src/common/visitor.hpp index 3d22f11e6..49bbcedb5 100644 --- a/src/common/visitor.hpp +++ b/src/common/visitor.hpp @@ -79,7 +79,7 @@ Credits for many further implementation ideas go to #include "common/visitorpolicies.hpp" #include "common/visitordispatcher.hpp" -#include "common/typelist.hpp" +#include "common/meta/typelist.hpp" namespace lumiera diff --git a/src/common/wrapperptr.hpp b/src/common/wrapperptr.hpp index e17963eff..81afa1177 100644 --- a/src/common/wrapperptr.hpp +++ b/src/common/wrapperptr.hpp @@ -29,7 +29,7 @@ #include "common/variant.hpp" #include "common/accesscasted.hpp" -#include "common/typelist.hpp" +#include "common/meta/typelist.hpp" #include "proc/mobject/placement.hpp" #include "common/p.hpp" diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index b1560e485..db652d99b 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -1,5 +1,5 @@ -# Copyright (C) Lumiera.org -# 2007, Joel Holdsworth +# Copyright (C) Lumiera.org +# 2007, Joel Holdsworth # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -22,74 +22,69 @@ lumigui_srcdir = $(top_srcdir)/src/gui #lumigui_CPPFLAGS = -I$(top_srcdir)/src/ INCLUDES = \ - -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ - -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ - -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ $(GTK_LUMIERA_CFLAGS) bin_PROGRAMS += lumigui -lumigui_SOURCES = \ - $(lumigui_srcdir)/gtk-lumiera.cpp \ - $(lumigui_srcdir)/gtk-lumiera.hpp \ - $(lumigui_srcdir)/window-manager.cpp \ - $(lumigui_srcdir)/window-manager.hpp \ - $(lumigui_srcdir)/workspace/actions.cpp \ - $(lumigui_srcdir)/workspace/actions.hpp \ - $(lumigui_srcdir)/workspace/workspace-window.cpp \ - $(lumigui_srcdir)/workspace/workspace-window.hpp \ - $(lumigui_srcdir)/dialogs/render.cpp \ - $(lumigui_srcdir)/dialogs/render.hpp \ - $(lumigui_srcdir)/dialogs/preferences-dialog.cpp \ - $(lumigui_srcdir)/dialogs/preferences-dialog.hpp \ - $(lumigui_srcdir)/panels/panel.cpp \ - $(lumigui_srcdir)/panels/panel.hpp \ - $(lumigui_srcdir)/panels/timeline-panel.cpp \ - $(lumigui_srcdir)/panels/timeline-panel.hpp \ - $(lumigui_srcdir)/panels/viewer-panel.cpp \ - $(lumigui_srcdir)/panels/viewer-panel.hpp \ - $(lumigui_srcdir)/panels/assets-panel.cpp \ - $(lumigui_srcdir)/panels/asset-panels.hpp \ - $(lumigui_srcdir)/widgets/video-display-widget.cpp \ - $(lumigui_srcdir)/widgets/video-display-widget.hpp \ - $(lumigui_srcdir)/widgets/timeline-widget.cpp \ - $(lumigui_srcdir)/widgets/timeline-widget.hpp \ - $(lumigui_srcdir)/widgets/timeline/header-container.cpp \ - $(lumigui_srcdir)/widgets/timeline/header-container.hpp \ - $(lumigui_srcdir)/widgets/timeline/track.cpp \ - $(lumigui_srcdir)/widgets/timeline/track.hpp \ - $(lumigui_srcdir)/widgets/timeline/video-track.cpp \ - $(lumigui_srcdir)/widgets/timeline/video-track.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-body.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-body.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ruler.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ruler.hpp \ - $(lumigui_srcdir)/model/project.cpp \ - $(lumigui_srcdir)/model/project.hpp \ - $(lumigui_srcdir)/output/displayer.cpp \ - $(lumigui_srcdir)/output/displayer.hpp \ - $(lumigui_srcdir)/output/gdkdisplayer.cpp \ - $(lumigui_srcdir)/output/gdkdisplayer.hpp \ - $(lumigui_srcdir)/output/xvdisplayer.cpp \ - $(lumigui_srcdir)/output/xvdisplayer.hpp +lumigui_SOURCES = \ + $(lumigui_srcdir)/gtk-lumiera.cpp \ + $(lumigui_srcdir)/gtk-lumiera.hpp \ + $(lumigui_srcdir)/window-manager.cpp \ + $(lumigui_srcdir)/window-manager.hpp \ + $(lumigui_srcdir)/workspace/actions.cpp \ + $(lumigui_srcdir)/workspace/actions.hpp \ + $(lumigui_srcdir)/workspace/workspace-window.cpp \ + $(lumigui_srcdir)/workspace/workspace-window.hpp \ + $(lumigui_srcdir)/dialogs/render.cpp \ + $(lumigui_srcdir)/dialogs/render.hpp \ + $(lumigui_srcdir)/dialogs/preferences-dialog.cpp \ + $(lumigui_srcdir)/dialogs/preferences-dialog.hpp \ + $(lumigui_srcdir)/panels/panel.cpp \ + $(lumigui_srcdir)/panels/panel.hpp \ + $(lumigui_srcdir)/panels/timeline-panel.cpp \ + $(lumigui_srcdir)/panels/timeline-panel.hpp \ + $(lumigui_srcdir)/panels/viewer-panel.cpp \ + $(lumigui_srcdir)/panels/viewer-panel.hpp \ + $(lumigui_srcdir)/panels/assets-panel.cpp \ + $(lumigui_srcdir)/panels/asset-panels.hpp \ + $(lumigui_srcdir)/widgets/video-display-widget.cpp \ + $(lumigui_srcdir)/widgets/video-display-widget.hpp \ + $(lumigui_srcdir)/widgets/timeline-widget.cpp \ + $(lumigui_srcdir)/widgets/timeline-widget.hpp \ + $(lumigui_srcdir)/widgets/timeline/header-container.cpp \ + $(lumigui_srcdir)/widgets/timeline/header-container.hpp \ + $(lumigui_srcdir)/widgets/timeline/track.cpp \ + $(lumigui_srcdir)/widgets/timeline/track.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-body.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-body.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-ruler.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-ruler.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-tool.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-tool.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.hpp \ + $(lumigui_srcdir)/model/project.cpp \ + $(lumigui_srcdir)/model/project.hpp \ + $(lumigui_srcdir)/output/displayer.cpp \ + $(lumigui_srcdir)/output/displayer.hpp \ + $(lumigui_srcdir)/output/gdkdisplayer.cpp \ + $(lumigui_srcdir)/output/gdkdisplayer.hpp \ + $(lumigui_srcdir)/output/xvdisplayer.cpp \ + $(lumigui_srcdir)/output/xvdisplayer.hpp lumigui_LDFLAGS = lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumicommon.a liblumi.a -lumigui_DEPENDENCIES = \ - $(top_builddir)/lumiera_ui.rc \ - $(top_builddir)/assets-panel.png \ - $(top_builddir)/timeline-panel.png \ - $(top_builddir)/viewer-panel.png - +lumigui_DEPENDENCIES = \ + $(top_builddir)/lumiera_ui.rc \ + $(top_builddir)/liblumicommon.a \ + $(top_builddir)/liblumi.a + $(top_builddir)/lumiera_ui.rc: cp $(lumigui_srcdir)/lumiera_ui.rc $(top_builddir) -$(top_builddir)/assets-panel.png: - cp $(top_srcdir)/icons/assets-panel.png $(top_builddir) -$(top_builddir)/timeline-panel.png: - cp $(top_srcdir)/icons/timeline-panel.png $(top_builddir) -$(top_builddir)/viewer-panel.png: - cp $(top_srcdir)/icons/viewer-panel.png $(top_builddir) - - diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index 69cfe0a4a..ba11f168a 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -35,6 +35,7 @@ NOBUG_CPP_DEFINE_FLAG(gui); using namespace Gtk; +using namespace Glib; using namespace lumiera::gui; using namespace lumiera::gui::workspace; using namespace lumiera::gui::model; @@ -43,39 +44,47 @@ GtkLumiera the_application; int main (int argc, char *argv[]) - { - return the_application.main(argc, argv); - } +{ + return the_application.main(argc, argv); +} namespace lumiera { namespace gui { - int - GtkLumiera::main(int argc, char *argv[]) - { - NOBUG_INIT; +int +GtkLumiera::main(int argc, char *argv[]) +{ + NOBUG_INIT; + + Main kit(argc, argv); - Main kit(argc, argv); - - Glib::set_application_name(AppTitle); + Glib::set_application_name(AppTitle); - Project project; - WindowManager window_manager; + Project project; + WindowManager window_manager; - window_manager.set_theme("lumiera_ui.rc"); + window_manager.set_theme("lumiera_ui.rc"); - WorkspaceWindow main_window(&project); - - kit.run(main_window); - } + WorkspaceWindow main_window(&project); - GtkLumiera& - application() - { - return the_application; - } + kit.run(main_window); +} + +Glib::ustring +GtkLumiera::get_home_data_path() +{ + const ustring app_name("lumiera"); + const ustring path(Glib::get_home_dir()); + return ustring::compose("%1/.%2", path, app_name); +} + +GtkLumiera& +application() +{ + return the_application; +} } // namespace gui } // namespace lumiera diff --git a/src/gui/gtk-lumiera.hpp b/src/gui/gtk-lumiera.hpp index 793ceb573..d3c59d7ba 100644 --- a/src/gui/gtk-lumiera.hpp +++ b/src/gui/gtk-lumiera.hpp @@ -51,51 +51,93 @@ NOBUG_DECLARE_FLAG(gui); #endif namespace lumiera { + +/** + * The namespace of all GUI code. + */ namespace gui { + +/* ===== Global Constants ===== */ - /** - * The name of the application - */ - static const gchar* AppTitle = "Lumiera"; +/** + * The name of the application + */ +static const gchar* AppTitle = "Lumiera"; - /** - * The version number of the application - */ - static const gchar* AppVersion = N_("0.1-dev"); +/** + * The version number of the application + */ +static const gchar* AppVersion = N_("0.1-dev"); - /** - * The copyright of the application - */ - static const gchar* AppCopyright = N_("© 2008 The Lumiera Team"); +/** + * The copyright of the application + */ +static const gchar* AppCopyright = N_("© 2008 The Lumiera Team"); - /** - * The website of the application - */ - static const gchar* AppWebsite = "www.lumiera.org"; +/** + * The website of the application + */ +static const gchar* AppWebsite = "www.lumiera.org"; - /** - * An alphabetical list of the application's authors - */ - static const gchar* AppAuthors[] = { - "Joel Holdsworth", - "Christian Thaeter", - "Hermann Vosseler", - ""}; +/** + * An alphabetical list of the application's authors + */ +static const gchar* AppAuthors[] = { + "Joel Holdsworth", + "Christian Thaeter", + "Hermann Vosseler", + ""}; + +/* ===== The Application Class ===== */ - /** - * The main application class. - */ - class GtkLumiera - { - public: - int main(int argc, char *argv[]); +/** + * The main application class. + */ +class GtkLumiera +{ +public: + int main(int argc, char *argv[]); + + static Glib::ustring get_home_data_path(); - }; +}; - /** - * Returns a reference to the global application object - */ - GtkLumiera& application(); +/** + * 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 {} } // namespace gui } // namespace lumiera diff --git a/src/gui/lumiera_ui.rc b/src/gui/lumiera_ui.rc index 428b7bed4..02f6d90fc 100644 --- a/src/gui/lumiera_ui.rc +++ b/src/gui/lumiera_ui.rc @@ -124,6 +124,8 @@ class "GtkProgressBar" style:highest "lumiera_progressbars" style "timeline_body" { gtkmm__CustomObject_TimelineBody::background = "#7E838B" + gtkmm__CustomObject_TimelineBody::selection = "#2D2D90" + gtkmm__CustomObject_TimelineBody::selection_alpha = 0.5 } style "timeline_ruler" = "default_base" @@ -137,16 +139,16 @@ style "timeline_ruler" = "default_base" gtkmm__CustomObject_TimelineRuler::annotation_vert_margin = 0 gtkmm__CustomObject_TimelineRuler::min_division_width = 100 gtkmm__CustomObject_TimelineRuler::mouse_chevron_size = 5 + gtkmm__CustomObject_TimelineRuler::selection_chevron_size = 5 + gtkmm__CustomObject_TimelineRuler::playback_arrow_colour = "#2D2D90" + gtkmm__CustomObject_TimelineRuler::playback_arrow_alpha = 0.5 + gtkmm__CustomObject_TimelineRuler::playback_arrow_size = 10 + gtkmm__CustomObject_TimelineRuler::playback_arrow_stem_size = 3 } style "timeline_header_base" = "default_base" { -# fg[NORMAL] = { 0.77, 0.77, 0.72 } -# bg[NORMAL] = { 0.18, 0.19, 0.22 } -# bg[ACTIVE] = { 0.20, 0.20, 0.20 } -# bg[PRELIGHT] = { 0.20, 0.20, 0.20 } -# bg[INSENSITIVE] = { 0.20, 0.20, 0.20 } -# bg[SELECTED] = { 0.20, 0.20, 0.20 } + } class "gtkmm__CustomObject_TimelineBody" style:highest "timeline_body" diff --git a/src/gui/output/displayer.hpp b/src/gui/output/displayer.hpp index 2441c0798..d5bf2a329 100644 --- a/src/gui/output/displayer.hpp +++ b/src/gui/output/displayer.hpp @@ -49,69 +49,74 @@ namespace output { } DisplayerInput; - /** A Displayer is a class which is responsible for rendering an image in some - way (ie: Xvideo, GDK, OpenGL etc). - - All Displayer classes must extend the Displayer class and minimally rewrite: - - + usable() - to indicate if the object can be used, - + format() - to indicate what type of input the put method expects - + put( void * ) - deal with an image of the expected type and size - - By default, all images will be delivered to the put method in a resolution - of IMG_WIDTH * IMG_HEIGHT. If another size is required, then the rewrite - the methods: - - + preferredWidth - + preferredHeight - - If the widget being written to doesn't need a fixed size, then rewrite - the two other put methods as required. + /** + * A Displayer is a class which is responsible for rendering an image + * in some way (ie: Xvideo, GDK, OpenGL etc). + * + * @remarks All Displayer classes must extend the Displayer class and + * minimally rewrite: + * + * + usable() - to indicate if the object can be used, + * + format() - to indicate what type of input the put method expects + * + put( void * ) - deal with an image of the expected type and size + * + * By default, all images will be delivered to the put method in a + * resolution of IMG_WIDTH * IMG_HEIGHT. If another size is required, + * then the rewrite the methods: + * + * + preferredWidth + * + preferredHeight + * + * If the widget being written to doesn't need a fixed size, then + * rewrite the two other put methods as required. */ class Displayer { public: - /** Indicates if an object can be used to render images on the running - system. + /** + * Indicates if an object can be used to render images on the + * running system. */ virtual bool usable(); - /** Indicates the format required by the abstract put method. + /** + * Indicates the format required by the abstract put method. */ virtual DisplayerInput format(); - /** Expected width of input to put. + /** + * Expected width of input to put. */ virtual int preferredWidth(); - /** Expected height of input to put. + /** + * Expected height of input to put. */ virtual int preferredHeight(); /** - * Put an image of a given width and height with the expected input - * format (as indicated by the format method). - * - * @param image image of correct format and specified width/height + * Put an image of a given width and height with the expected input + * format (as indicated by the format method). */ virtual void put( void * ) = 0; protected: /** - * Calculates the coordinates for placing a video image inside a widget + * Calculates the coordinates for placing a video image inside a + * widget * - * @param[in] widget_width The width of the display widget - * @param[in] widget_height The height of the display widget - * @param[in] image_width The width of the video image - * @param[in] image_height The height of the video image - * @param[out] video_x The x-coordinate of the top left corner of - * the scaled video image - * @param[out] video_y The y-coordinate of the top left corner of - * the scaled video image - * @param[out] video_width The width of the scale video image - * @param[out] video_height The height of the scale video image + * @param[in] widget_width The width of the display widget. + * @param[in] widget_height The height of the display widget. + * @param[in] image_width The width of the video image. + * @param[in] image_height The height of the video image. + * @param[out] video_x The x-coordinate of the top left + * corner of the scaled video image. + * @param[out] video_y The y-coordinate of the top left + * corner of the scaled video image. + * @param[out] video_width The width of the scale video image. + * @param[out] video_height The height of the scale video image. */ static void calculateVideoLayout( int widget_width, int widget_height, diff --git a/src/gui/panels/assets-panel.cpp b/src/gui/panels/assets-panel.cpp index 431b92019..58535f0e0 100644 --- a/src/gui/panels/assets-panel.cpp +++ b/src/gui/panels/assets-panel.cpp @@ -28,7 +28,7 @@ namespace gui { namespace panels { AssetsPanel::AssetsPanel() : - Panel("assets", _("Assets"), "assets_panel"), + Panel("assets", _("Assets"), "panel_assets"), placeholder("Placeholder label. Is this supposed to be titled assets\nas in the proc layer? or resources\nas in cinelerra?") { pack_start(placeholder); diff --git a/src/gui/panels/panel.hpp b/src/gui/panels/panel.hpp index 6769f32d7..4c71217c6 100644 --- a/src/gui/panels/panel.hpp +++ b/src/gui/panels/panel.hpp @@ -27,68 +27,68 @@ #ifndef PANEL_HPP #define PANEL_HPP -#include +#include "../gtk-lumiera.hpp" #include namespace lumiera { namespace gui { namespace panels { - /** - * The main lumiera workspace window +/** +* The main lumiera panel window +*/ +class Panel : public Gtk::VBox +{ +protected: + /** + * Constructs a panel object + * @param name The internal name of this panel + * @param long_name The name to display on the caption + * @param behavior The GDL behaviour of this item */ - class Panel : public Gtk::VBox - { - protected: - /** - * Constructs a panel object - * @param name The internal name of this panel - * @param long_name The name to display on the caption - * @param behavior The GDL behaviour of this item - */ - Panel(const gchar *name, const gchar *long_name, - GdlDockItemBehavior behavior = GDL_DOCK_ITEM_BEH_NORMAL); + Panel(const gchar *name, const gchar *long_name, + GdlDockItemBehavior behavior = GDL_DOCK_ITEM_BEH_NORMAL); - /** - * Constructs a panel object with a stock item for a caption - * @param name The internal name of this panel - * @param long_name The name to display on the caption - * @param stock_id The id of the stock item to display on the caption - * @param behavior The GDL behaviour of this item - */ - Panel(const gchar *name, const gchar *long_name, const gchar *stock_id, - GdlDockItemBehavior behavior = GDL_DOCK_ITEM_BEH_NORMAL); + /** + * Constructs a panel object with a stock item for a caption + * @param name The internal name of this panel + * @param long_name The name to display on the caption + * @param stock_id The id of the stock item to display on the caption + * @param behavior The GDL behaviour of this item + */ + Panel(const gchar *name, const gchar *long_name, const gchar *stock_id, + GdlDockItemBehavior behavior = GDL_DOCK_ITEM_BEH_NORMAL); - ~Panel(); + ~Panel(); - public: - /** - * Returns a pointer to the underlying GdlDockItem structure - */ - GdlDockItem* get_dock_item() const; +public: + /** + * Returns a pointer to the underlying GdlDockItem structure + */ + GdlDockItem* get_dock_item() const; - /** - * Shows or hides the panel. - * @param show A value of true will show the panel, - * false will hide it. */ - void show(bool show = true); - - /** - * Returns true if the panel is currently visible. - */ - bool is_shown() const; + /** + * Shows or hides the panel. + * @param show A value of true will show the panel, + * false will hide it. */ + void show(bool show = true); + + /** + * Returns true if the panel is currently visible. + */ + bool is_shown() const; - private: - /** - * @internal Used by both constructors - * The internal constructor for this class, whose purpose - * is to set up the internal container widgets. - */ - void internal_setup(); +private: + /** + * @internal Used by both constructors + * The internal constructor for this class, whose purpose + * is to set up the internal container widgets. + */ + void internal_setup(); - protected: - GdlDockItem* dock_item; - }; +protected: + GdlDockItem* dock_item; +}; } // namespace panels } // namespace gui diff --git a/src/gui/panels/timeline-panel.cpp b/src/gui/panels/timeline-panel.cpp index 3b6bfed84..65e9ae6b7 100644 --- a/src/gui/panels/timeline-panel.cpp +++ b/src/gui/panels/timeline-panel.cpp @@ -23,8 +23,13 @@ #include "../gtk-lumiera.hpp" #include "timeline-panel.hpp" +extern "C" { +#include "../../lib/time.h" +} + using namespace Gtk; using namespace sigc; +using namespace lumiera::gui::widgets; namespace lumiera { namespace gui { @@ -33,27 +38,66 @@ namespace panels { const int TimelinePanel::ZoomToolSteps = 2; // 2 seems comfortable TimelinePanel::TimelinePanel() : - Panel("timeline", _("Timeline"), "timeline_panel"), + Panel("timeline", _("Timeline"), "panel_timeline"), + arrowTool(Gtk::StockID("tool_arrow")), + iBeamTool(Gtk::StockID("tool_i_beam")), zoomIn(Stock::ZOOM_IN), - zoomOut(Stock::ZOOM_OUT) + zoomOut(Stock::ZOOM_OUT), + timeIndicator(), + updatingToolbar(false) { + // Setup the widget + timelineWidget.mouse_hover_signal().connect( + mem_fun(this, &TimelinePanel::on_mouse_hover)); + // Setup the toolbar + timeIndicatorButton.set_label_widget(timeIndicator); + toolbar.append(timeIndicatorButton); + + toolbar.append(seperator1); + + toolbar.append(arrowTool, mem_fun(this, + &TimelinePanel::on_arrow_tool)); + toolbar.append(iBeamTool, mem_fun(this, + &TimelinePanel::on_ibeam_tool)); + toolbar.append(seperator2); toolbar.append(zoomIn, mem_fun(this, &TimelinePanel::on_zoom_in)); toolbar.append(zoomOut, mem_fun(this, &TimelinePanel::on_zoom_out)); - toolbar.set_icon_size(IconSize(ICON_SIZE_SMALL_TOOLBAR)); +// doesn't compile on Etch +// toolbar.set_icon_size(IconSize(ICON_SIZE_LARGE_TOOLBAR)); toolbar.set_toolbar_style(TOOLBAR_ICONS); // Add the toolbar pack_start(toolbar, PACK_SHRINK); pack_start(timelineWidget, PACK_EXPAND_WIDGET); + // Set the initial UI state + update_tool_buttons(); update_zoom_buttons(); + show_time(0); +} + +void +TimelinePanel::on_arrow_tool() +{ + if(updatingToolbar) return; + timelineWidget.set_tool(timeline::Arrow); + update_tool_buttons(); +} + +void +TimelinePanel::on_ibeam_tool() +{ + if(updatingToolbar) return; + timelineWidget.set_tool(timeline::IBeam); + update_tool_buttons(); } void TimelinePanel::on_zoom_in() { + timelineWidget.zoom_view(ZoomToolSteps); update_zoom_buttons(); } @@ -65,6 +109,25 @@ TimelinePanel::on_zoom_out() update_zoom_buttons(); } +void +TimelinePanel::on_mouse_hover(gavl_time_t time) +{ + show_time(time); +} + +void +TimelinePanel::update_tool_buttons() +{ + if(!updatingToolbar) + { + updatingToolbar = true; + const timeline::ToolType tool = timelineWidget.get_tool(); + arrowTool.set_active(tool == timeline::Arrow); + iBeamTool.set_active(tool == timeline::IBeam); + updatingToolbar = false; + } +} + void TimelinePanel::update_zoom_buttons() { @@ -73,6 +136,12 @@ TimelinePanel::update_zoom_buttons() TimelineWidget::MaxScale); } +void +TimelinePanel::show_time(gavl_time_t time) +{ + timeIndicator.set_text(lumiera_tmpbuf_print_time(time)); +} + } // namespace panels } // namespace gui } // namespace lumiera diff --git a/src/gui/panels/timeline-panel.hpp b/src/gui/panels/timeline-panel.hpp index a14288c41..b46218e87 100644 --- a/src/gui/panels/timeline-panel.hpp +++ b/src/gui/panels/timeline-panel.hpp @@ -35,18 +35,35 @@ namespace lumiera { namespace gui { namespace panels { +/** + * The definition of the timeline panel class, which holds timeline + * widgets. + */ class TimelinePanel : public Panel { public: + /** + * Constructor + */ TimelinePanel(); private: //----- Event Handlers -----// + void on_arrow_tool(); + void on_ibeam_tool(); + void on_zoom_in(); void on_zoom_out(); + void on_time_pressed(); + + void on_mouse_hover(gavl_time_t time); + private: + void update_tool_buttons(); void update_zoom_buttons(); + + void show_time(gavl_time_t time); private: @@ -54,12 +71,26 @@ private: // Widgets Gtk::Toolbar toolbar; + Gtk::HBox toolStrip; TimelineWidget timelineWidget; // Toolbar Widgets + Gtk::ToggleToolButton arrowTool; + Gtk::ToggleToolButton iBeamTool; + + Gtk::SeparatorToolItem seperator1; + Gtk::ToolButton zoomIn; Gtk::ToolButton zoomOut; + Gtk::SeparatorToolItem seperator2; + + Gtk::Label timeIndicator; + Gtk::ToolButton timeIndicatorButton; + + // Internals + bool updatingToolbar; + //----- Constants -----// static const int ZoomToolSteps; }; diff --git a/src/gui/panels/viewer-panel.cpp b/src/gui/panels/viewer-panel.cpp index ff64138ed..323859b9a 100644 --- a/src/gui/panels/viewer-panel.cpp +++ b/src/gui/panels/viewer-panel.cpp @@ -31,7 +31,7 @@ namespace gui { namespace panels { ViewerPanel::ViewerPanel() : - Panel("viewer", _("Viewer"), "viewer_panel"), + Panel("viewer", _("Viewer"), "panel_viewer"), previousButton(Stock::MEDIA_PREVIOUS), rewindButton(Stock::MEDIA_REWIND), playPauseButton(Stock::MEDIA_PLAY), diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 5011103ac..c7463768b 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -44,6 +44,10 @@ TimelineWidget::TimelineWidget() : totalHeight(0), horizontalAdjustment(0, 0, 0), verticalAdjustment(0, 0, 0), + selectionStart(0), + selectionEnd(0), + playbackPeriodStart(0), + playbackPeriodEnd(0), horizontalScroll(horizontalAdjustment), verticalScroll(verticalAdjustment) { @@ -51,6 +55,8 @@ TimelineWidget::TimelineWidget() : ENSURE(body != NULL); headerContainer = new HeaderContainer(this); ENSURE(headerContainer != NULL); + ruler = new TimelineRuler(this); + ENSURE(ruler != NULL); horizontalAdjustment.signal_value_changed().connect( sigc::mem_fun( this, &TimelineWidget::on_scroll) ); @@ -58,11 +64,12 @@ TimelineWidget::TimelineWidget() : this, &TimelineWidget::on_scroll) ); body->signal_motion_notify_event().connect( sigc::mem_fun( this, &TimelineWidget::on_motion_in_body_notify_event) ); - + set_time_scale(GAVL_TIME_SCALE / 200); + set_selection(2000000, 4000000); attach(*body, 1, 2, 1, 2, FILL|EXPAND, FILL|EXPAND); - attach(ruler, 1, 2, 0, 1, FILL|EXPAND, SHRINK); + attach(*ruler, 1, 2, 0, 1, FILL|EXPAND, SHRINK); attach(*headerContainer, 0, 1, 1, 2, SHRINK, FILL|EXPAND); attach(horizontalScroll, 1, 2, 2, 3, FILL|EXPAND, SHRINK); attach(verticalScroll, 2, 3, 1, 2, SHRINK, FILL|EXPAND); @@ -71,14 +78,23 @@ TimelineWidget::TimelineWidget() : tracks.push_back(&video2); update_tracks(); + + set_tool(timeline::Arrow); } TimelineWidget::~TimelineWidget() { REQUIRE(body != NULL); - body->unreference(); + if(body != NULL) + body->unreference(); + REQUIRE(headerContainer != NULL); - headerContainer->unreference(); + if(headerContainer != NULL) + headerContainer->unreference(); + + REQUIRE(ruler != NULL); + if(ruler != NULL) + ruler->unreference(); } gavl_time_t @@ -90,9 +106,12 @@ TimelineWidget::get_time_offset() const void TimelineWidget::set_time_offset(gavl_time_t time_offset) { + REQUIRE(ruler != NULL); + timeOffset = time_offset; horizontalAdjustment.set_value(time_offset); - ruler.set_time_offset(time_offset); + + viewChangedSignal.emit(); } int64_t @@ -104,17 +123,14 @@ TimelineWidget::get_time_scale() const void TimelineWidget::set_time_scale(int64_t time_scale) { - timeScale = time_scale; - ruler.set_time_scale(time_scale); -} - -void -TimelineWidget::shift_view(int shift_size) -{ - const int view_width = body->get_allocation().get_width(); + REQUIRE(ruler != NULL); - set_time_offset(get_time_offset() + - shift_size * timeScale * view_width / 16); + timeScale = time_scale; + + const int view_width = body->get_allocation().get_width(); + horizontalAdjustment.set_page_size(timeScale * view_width); + + viewChangedSignal.emit(); } void @@ -148,11 +164,121 @@ TimelineWidget::zoom_view(int point, int zoom_size) set_time_scale(new_time_scale); } +void +TimelineWidget::shift_view(int shift_size) +{ + const int view_width = body->get_allocation().get_width(); + + set_time_offset(get_time_offset() + + shift_size * timeScale * view_width / 256); +} + +gavl_time_t +TimelineWidget::get_selection_start() const +{ + return selectionStart; +} + +gavl_time_t +TimelineWidget::get_selection_end() const +{ + return selectionEnd; +} + +void +TimelineWidget::set_selection(gavl_time_t start, gavl_time_t end, + bool reset_playback_period) +{ + REQUIRE(ruler != NULL); + REQUIRE(body != NULL); + + if(start < end) + { + selectionStart = start; + selectionEnd = end; + } + else + { + // The selection is back-to-front, flip it round + selectionStart = end; + selectionEnd = start; + } + + if(reset_playback_period) + { + playbackPeriodStart = selectionStart; + playbackPeriodEnd = selectionEnd; + } + + ruler->queue_draw(); + body->queue_draw(); +} + +gavl_time_t +TimelineWidget::get_playback_period_start() const +{ + return playbackPeriodStart; +} + +gavl_time_t +TimelineWidget::get_playback_period_end() const +{ + return playbackPeriodEnd; +} + +void +TimelineWidget::set_playback_period(gavl_time_t start, gavl_time_t end) +{ + REQUIRE(ruler != NULL); + REQUIRE(body != NULL); + + if(start < end) + { + playbackPeriodStart = start; + playbackPeriodEnd = end; + } + else + { + // The period is back-to-front, flip it round + playbackPeriodStart = end; + playbackPeriodEnd = start; + } + + ruler->queue_draw(); + body->queue_draw(); +} + +ToolType +TimelineWidget::get_tool() const +{ + REQUIRE(body != NULL); + return body->get_tool(); +} + +void +TimelineWidget::set_tool(ToolType tool_type) +{ + REQUIRE(body != NULL); + body->set_tool(tool_type); +} + +sigc::signal +TimelineWidget::view_changed_signal() const +{ + return viewChangedSignal; +} + +sigc::signal +TimelineWidget::mouse_hover_signal() const +{ + return mouseHoverSignal; +} + void TimelineWidget::on_scroll() { timeOffset = horizontalAdjustment.get_value(); - ruler.set_time_offset(timeOffset); + viewChangedSignal.emit(); } void @@ -163,6 +289,18 @@ TimelineWidget::on_size_allocate(Allocation& allocation) update_scroll(); } +int +TimelineWidget::time_to_x(gavl_time_t time) const +{ + return (int)((time - timeOffset) / timeScale); +} + +gavl_time_t +TimelineWidget::x_to_time(int x) const +{ + return (gavl_time_t)((int64_t)x * timeScale + timeOffset); +} + void TimelineWidget::update_tracks() { @@ -186,9 +324,14 @@ TimelineWidget::update_scroll() //----- Horizontal Scroll ------// + // TEST CODE horizontalAdjustment.set_upper(1000 * GAVL_TIME_SCALE / 200); horizontalAdjustment.set_lower(-1000 * GAVL_TIME_SCALE / 200); + // Set the page size + horizontalAdjustment.set_page_size( + timeScale * body_allocation.get_width()); + //----- Vertical Scroll -----// // Calculate the vertical length that can be scrolled: @@ -204,10 +347,14 @@ TimelineWidget::update_scroll() verticalAdjustment.set_upper(y_scroll_length); // Hide the scrollbar if no scrolling is possible - if(y_scroll_length == 0 && verticalScroll.is_visible()) +#if 0 + // Having this code included seems to cause a layout loop as the + // window is shrunk + if(y_scroll_length <= 0 && verticalScroll.is_visible()) verticalScroll.hide(); - else if(y_scroll_length != 0 && !verticalScroll.is_visible()) + else if(y_scroll_length > 0 && !verticalScroll.is_visible()) verticalScroll.show(); +#endif } int @@ -220,7 +367,8 @@ bool TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event) { REQUIRE(event != NULL); - ruler.set_mouse_chevron_offset(event->x); + ruler->set_mouse_chevron_offset(event->x); + mouseHoverSignal.emit(x_to_time(event->x)); return true; } diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index 669060038..ef13ef556 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -30,13 +30,25 @@ #include "timeline/header-container.hpp" #include "timeline/timeline-body.hpp" #include "timeline/timeline-ruler.hpp" +#include "timeline/timeline-tool.hpp" +#include "timeline/timeline-arrow-tool.hpp" +#include "timeline/timeline-ibeam-tool.hpp" #include "timeline/track.hpp" -#include "timeline/video-track.hpp" namespace lumiera { namespace gui { namespace widgets { + +/** + * The namespace of all timeline widget helper classes. + */ +namespace timeline {} +/** + * The timeline widget class. + * @remarks This widget is a composite of several widgets contained + * within the timeline namespace. + */ class TimelineWidget : public Gtk::Table { public: @@ -91,19 +103,78 @@ public: /** * Scrolls the view horizontally as a proportion of the view area. - * @param shift_size The size of the shift in 1/16ths of the view + * @param shift_size The size of the shift in 1/256ths of the view * width. **/ void shift_view(int shift_size); + /** + * Gets the time at which the selection begins. + */ + gavl_time_t get_selection_start() const; + + /** + * Gets the time at which the selection begins. + */ + gavl_time_t get_selection_end() const; + + /** + * Sets the period of the selection. + * @param start The start time. + * @param end The end time. + * @param reset_playback_period Specifies whether to set the playback + * period to the same as this new selection. + */ + void set_selection(gavl_time_t start, gavl_time_t end, + bool reset_playback_period = true); + + /** + * Gets the time at which the playback period begins. + */ + gavl_time_t get_playback_period_start() const; + + /** + * Gets the time at which the playback period ends. + */ + gavl_time_t get_playback_period_end() const; + + /** + * Sets the playback period. + * @param start The start time. + * @param end The end time. + */ + void set_playback_period(gavl_time_t start, gavl_time_t end); + + /** + * Gets the type of the tool currently active. + */ + timeline::ToolType get_tool() const; + + /** + * Sets the type of the tool currently active. + */ + void set_tool(timeline::ToolType tool_type); + +public: + /* ===== Signals ===== */ + sigc::signal view_changed_signal() const; + + sigc::signal mouse_hover_signal() const; + /* ===== Events ===== */ protected: void on_scroll(); void on_size_allocate(Gtk::Allocation& allocation); + + /* ===== Utilities ===== */ +protected: + int time_to_x(gavl_time_t time) const; + + gavl_time_t x_to_time(int x) const; /* ===== Internals ===== */ -protected: +private: void update_tracks(); @@ -114,25 +185,42 @@ protected: bool on_motion_in_body_notify_event(GdkEventMotion *event); protected: + + // View State gavl_time_t timeOffset; int64_t timeScale; + + // Selection State + gavl_time_t selectionStart; + gavl_time_t selectionEnd; + gavl_time_t playbackPeriodStart; + gavl_time_t playbackPeriodEnd; int totalHeight; - timeline::VideoTrack video1; - timeline::VideoTrack video2; + timeline::Track video1; + timeline::Track video2; std::vector tracks; timeline::HeaderContainer *headerContainer; timeline::TimelineBody *body; - timeline::TimelineRuler ruler; + timeline::TimelineRuler *ruler; Gtk::Adjustment horizontalAdjustment, verticalAdjustment; Gtk::HScrollbar horizontalScroll; Gtk::VScrollbar verticalScroll; + // Signals + sigc::signal viewChangedSignal; + sigc::signal mouseHoverSignal; + /* ===== Constants ===== */ public: + /** + * The maximum scale for timeline display. + * @remarks At MaxScale, every pixel on the timeline is equivalent + * to 30000000 gavl_time_t increments. + */ static const int64_t MaxScale; protected: @@ -142,6 +230,10 @@ protected: friend class timeline::TimelineBody; friend class timeline::HeaderContainer; + friend class timeline::TimelineRuler; + friend class timeline::Tool; + friend class timeline::ArrowTool; + friend class timeline::IBeamTool; }; } // namespace widgets diff --git a/src/gui/widgets/timeline/header-container.cpp b/src/gui/widgets/timeline/header-container.cpp index 5e74da3eb..dfc085fc1 100644 --- a/src/gui/widgets/timeline/header-container.cpp +++ b/src/gui/widgets/timeline/header-container.cpp @@ -39,7 +39,9 @@ HeaderContainer::HeaderContainer(lumiera::gui::widgets::TimelineWidget *timeline { REQUIRE(timeline_widget != NULL); - set_flags(Gtk::NO_WINDOW); // This widget will not have a window at first + // This widget will not have a window at first + set_flags(Gtk::NO_WINDOW); + set_redraw_on_allocate(false); // Connect to the timeline widget's vertical scroll event, diff --git a/src/gui/widgets/timeline/header-container.hpp b/src/gui/widgets/timeline/header-container.hpp index 69d13b953..bc74a9c2a 100644 --- a/src/gui/widgets/timeline/header-container.hpp +++ b/src/gui/widgets/timeline/header-container.hpp @@ -27,7 +27,7 @@ #ifndef HEADER_CONTAINER_HPP #define HEADER_CONTAINER_HPP -#include +#include "../../gtk-lumiera.hpp" #include namespace lumiera { @@ -46,80 +46,105 @@ class Track; * associated with timeline tracks. */ class HeaderContainer : public Gtk::Container +{ +public: + /** + * Constructor + * + * @param[in] timeline_widget A pointer to the owner timeline widget + */ + HeaderContainer(lumiera::gui::widgets::TimelineWidget* + timeline_widget); + + /** + * Attaches the header all the header widgets of root + * tracks to this control. + * + * @note This must be called when the track list changes + * to synchronise the headers with the timeline body and + * the backend. + */ + void update_headers(); + + /* ===== Overrides ===== */ +private: + /** + * And event handler for the window realized signal. + */ + void on_realize(); + + /** + * And event handler for the window unrealized signal. + */ + void on_unrealize(); + + /** + * An event handler that is called to notify this widget to allocate + * a given area for itself. + * @param allocation The area to allocate for this widget. + */ + void on_size_allocate (Gtk::Allocation& allocation); + + /** + * An event handler that is called to offer an allocation to this + * widget. + * @param requisition The area offered for this widget. + */ + void on_size_request (Gtk::Requisition* requisition); + + /** + * Applies a given function to all the widgets in the container. + **/ + void forall_vfunc(gboolean include_internals, GtkCallback callback, + gpointer callback_data); + + /* ===== Events ===== */ +private: + /** + * This event is called when the scroll bar moves. + */ + void on_scroll(); + + /* ===== Internals ===== */ +private: + + /** + * Moves all the header widgets to the correct position + * given scroll, stacking etc. + */ + void layout_headers(); + +private: + + /** + * The owner TimelineWidget of which this class is a helper + */ + lumiera::gui::widgets::TimelineWidget *timelineWidget; + + /** + * A structure to represent a header widget and it's + * associated track + */ + struct RootHeader { - public: - /** - * Constructor - * - * @param[in] timeline_widget A pointer to the owner timeline widget - */ - HeaderContainer(lumiera::gui::widgets::TimelineWidget *timeline_widget); - - /** - * Attaches the header all the header widgets of root - * tracks to this control. - * - * @note This must be called when the track list changes - * to synchronise the headers with the timeline body and - * the backend. - */ - void update_headers(); - - /* ===== Overrides ===== */ - private: - void on_realize(); - void on_unrealize(); - - void on_size_allocate (Gtk::Allocation& allocation); - void on_size_request (Gtk::Requisition* requisition); - - void forall_vfunc(gboolean include_internals, GtkCallback callback, - gpointer callback_data); - - /* ===== Events ===== */ - private: - void on_scroll(); - - /* ===== Internals ===== */ - private: - - /** - * Moves all the header widgets to the correct position - * given scroll, stacking etc. - */ - void layout_headers(); - - private: - - /** - * The owner TimelineWidget of which this class is a helper - */ - lumiera::gui::widgets::TimelineWidget *timelineWidget; - - /** - * A structure to represent a header widget and it's - * associated track - */ - struct RootHeader - { - Glib::RefPtr widget; - Track *track; - }; - - /** - * Contains a list of the root currently present on - * the timeline view - */ - std::vector< RootHeader > rootHeaders; - - /** - * The widget's window object. - * - * @note This is needed for the sake of clipping when - * widgets are scrolled. - */ - Glib::RefPtr gdkWindow; + Glib::RefPtr widget; + Track *track; }; + + /** + * Contains a list of the root currently present on + * the timeline view + */ + std::vector< RootHeader > rootHeaders; + + /** + * The widget's window object. + * + * @note This is needed for the sake of clipping when + * widgets are scrolled. + */ + Glib::RefPtr gdkWindow; +}; } // namespace timeline } // namespace widgets diff --git a/src/gui/widgets/timeline/video-track.cpp b/src/gui/widgets/timeline/timeline-arrow-tool.cpp similarity index 62% rename from src/gui/widgets/timeline/video-track.cpp rename to src/gui/widgets/timeline/timeline-arrow-tool.cpp index 4242f0e3f..109d6190e 100644 --- a/src/gui/widgets/timeline/video-track.cpp +++ b/src/gui/widgets/timeline/timeline-arrow-tool.cpp @@ -1,5 +1,5 @@ /* - video-track.cpp - Implementation of the timeline video track object + timeline-arrow-tool.cpp - Implementation of the ArrowTool class Copyright (C) Lumiera.org 2008, Joel Holdsworth @@ -20,38 +20,48 @@ * *****************************************************/ -#include "video-track.hpp" - -using namespace Gtk; +#include "timeline-arrow-tool.hpp" namespace lumiera { namespace gui { namespace widgets { namespace timeline { -VideoTrack::VideoTrack() : - headerWidget("HeaderTest") - { +ArrowTool::ArrowTool(TimelineBody *timeline_body) : + Tool(timeline_body) +{ - } +} -Gtk::Widget& -VideoTrack::get_header_widget() - { - return headerWidget; - } +ToolType +ArrowTool::get_type() const +{ + return Arrow; +} -int -VideoTrack::get_height() - { - return 100; - } +Gdk::Cursor +ArrowTool::get_cursor() const +{ + return Gdk::Cursor(Gdk::ARROW); +} void -VideoTrack::draw_track(Cairo::RefPtr cairo) - { - - } +ArrowTool::on_button_press_event(GdkEventButton* event) +{ + Tool::on_button_press_event(event); +} + +void +ArrowTool::on_button_release_event(GdkEventButton* event) +{ + Tool::on_button_release_event(event); +} + +void +ArrowTool::on_motion_notify_event(GdkEventMotion *event) +{ + Tool::on_motion_notify_event(event); +} } // namespace timeline } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-arrow-tool.hpp b/src/gui/widgets/timeline/timeline-arrow-tool.hpp new file mode 100644 index 000000000..a6ec1f1bf --- /dev/null +++ b/src/gui/widgets/timeline/timeline-arrow-tool.hpp @@ -0,0 +1,83 @@ +/* + timeline-arrow-tool.hpp - Declaration of the ArrowTool class + + Copyright (C) Lumiera.org + 2008, Joel Holdsworth + + 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-arrow-tool.hpp + ** This file contains the definition of the arrow tool class + */ + +#ifndef TIMELINE_ARROW_TOOL_HPP +#define TIMELINE_ARROW_TOOL_HPP + +#include +#include "timeline-tool.hpp" + +namespace lumiera { +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 + */ + ArrowTool(TimelineBody *timeline_body); + + /** + * Gets the type of tool represented by this class + */ + ToolType get_type() const; + +protected: + + /** + * 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 release events. + */ + void on_button_release_event(GdkEventButton* event); + + /** + * The event handler for mouse move events. + */ + void on_motion_notify_event(GdkEventMotion *event); +}; + +} // namespace timeline +} // namespace widgets +} // namespace gui +} // namespace lumiera + +#endif // TIMELINE_ARROW_TOOL_HPP diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp index d2e711638..a3602572a 100644 --- a/src/gui/widgets/timeline/timeline-body.cpp +++ b/src/gui/widgets/timeline/timeline-body.cpp @@ -27,6 +27,9 @@ #include "../timeline-widget.hpp" #include "../../window-manager.hpp" +#include "timeline-arrow-tool.hpp" +#include "timeline-ibeam-tool.hpp" + using namespace Gtk; using namespace std; using namespace lumiera::gui; @@ -38,30 +41,76 @@ namespace gui { namespace widgets { namespace timeline { -TimelineBody::TimelineBody(lumiera::gui::widgets::TimelineWidget *timeline_widget) : +TimelineBody::TimelineBody(lumiera::gui::widgets::TimelineWidget + *timeline_widget) : Glib::ObjectBase("TimelineBody"), + tool(NULL), dragType(None), mouseDownX(0), mouseDownY(0), beginShiftTimeOffset(0), + selectionAlpha(0.5), timelineWidget(timeline_widget) { REQUIRE(timelineWidget != NULL); // Connect up some events - timelineWidget->horizontalAdjustment.signal_value_changed().connect( - sigc::mem_fun(this, &TimelineBody::on_scroll) ); - timelineWidget->verticalAdjustment.signal_value_changed().connect( - sigc::mem_fun(this, &TimelineBody::on_scroll) ); + timelineWidget->view_changed_signal().connect(sigc::mem_fun( + this, &TimelineBody::on_update_view) ); // Install style properties - gtk_widget_class_install_style_property( - GTK_WIDGET_CLASS(G_OBJECT_GET_CLASS(gobj())), - g_param_spec_boxed("background", - "Track Background", - "The background colour of timeline tracks", - GDK_TYPE_COLOR, G_PARAM_READABLE)); + register_styles(); +} +TimelineBody::~TimelineBody() +{ + REQUIRE(tool != NULL); + if(tool != NULL) + delete tool; +} + +ToolType +TimelineBody::get_tool() const +{ + REQUIRE(tool != NULL); + if(tool != NULL) + return tool->get_type(); + return lumiera::gui::widgets::timeline::None; +} + +void +TimelineBody::set_tool(timeline::ToolType tool_type) +{ + // Tidy up old tool + if(tool != NULL) + { + // Do we need to change tools? + if(tool->get_type() == tool_type) + return; + + delete tool; + } + + // Create the new tool + switch(tool_type) + { + case timeline::Arrow: + tool = new ArrowTool(this); + break; + + case timeline::IBeam: + tool = new IBeamTool(this); + break; + } + + // Apply the cursor if possible + tool->apply_cursor(); +} + +void +TimelineBody::on_update_view() +{ + queue_draw(); } void @@ -69,18 +118,108 @@ TimelineBody::on_realize() { Widget::on_realize(); - // We wish to receive all event notifications + // We wish to receive event notifications add_events( Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); + + // Apply the cursor if possible + tool->apply_cursor(); } -void -TimelineBody::on_scroll() +bool +TimelineBody::on_expose_event(GdkEventExpose* event) { - queue_draw(); + Cairo::Matrix view_matrix; + + REQUIRE(event != NULL); + REQUIRE(timelineWidget != NULL); + + // This is where we draw on the window + Glib::RefPtr window = get_window(); + if(!window) + return false; + + // Makes sure the widget styles have been loaded + read_styles(); + + // Prepare to render via cairo + Glib::RefPtr