From d89e979aa09b7cd9e90848e8eda752ef761bfb8f Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 18 Oct 2008 11:20:02 +0100 Subject: [PATCH 01/59] Renamed HeaderContainer to TimelineHeaderContainer --- src/gui/Makefile.am | 104 +++++++++--------- src/gui/lumiera_ui.rc | 4 +- src/gui/widgets/timeline-widget.cpp | 2 +- src/gui/widgets/timeline-widget.hpp | 6 +- ...iner.cpp => timeline-header-container.cpp} | 33 +++--- ...iner.hpp => timeline-header-container.hpp} | 13 ++- 6 files changed, 82 insertions(+), 80 deletions(-) rename src/gui/widgets/timeline/{header-container.cpp => timeline-header-container.cpp} (88%) rename src/gui/widgets/timeline/{header-container.hpp => timeline-header-container.hpp} (90%) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 79e402310..7e8d356ea 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -21,67 +21,67 @@ lumigui_srcdir = $(top_srcdir)/src/gui #lumigui_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror lumigui_CPPFLAGS = $(AM_CPPFLAGS) \ - -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/assets-panel.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_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/assets-panel.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/timeline-header-container.cpp \ + $(lumigui_srcdir)/widgets/timeline/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 $(NOBUGMT_LUMIERA_LIBS) -lumigui_DEPENDENCIES = \ - $(top_builddir)/lumiera_ui.rc \ - $(top_builddir)/liblumicommon.a \ +lumigui_DEPENDENCIES = \ + $(top_builddir)/lumiera_ui.rc \ + $(top_builddir)/liblumicommon.a \ $(top_builddir)/liblumi.a $(top_builddir)/lumiera_ui.rc: diff --git a/src/gui/lumiera_ui.rc b/src/gui/lumiera_ui.rc index 9d4f4d771..dcce8df48 100644 --- a/src/gui/lumiera_ui.rc +++ b/src/gui/lumiera_ui.rc @@ -152,13 +152,13 @@ style "timeline_ruler" = "default_base" gtkmm__CustomObject_TimelineRuler::playback_period_arrow_stem_size = 3 } -style "header_container" = "default_base" +style "timeline_header_container" = "default_base" { gtkmm__CustomObject_HeaderContainer::heading_margin = 4 } class "gtkmm__CustomObject_TimelineBody" style:highest "timeline_body" class "gtkmm__CustomObject_TimelineRuler" style:highest "timeline_ruler" -class "gtkmm__CustomObject_HeaderContainer" style:highest "header_container" +class "gtkmm__CustomObject_TimelineHeaderContainer" style:highest "timeline_header_container" diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 20014e675..6c397f9f1 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -53,7 +53,7 @@ TimelineWidget::TimelineWidget() : { body = new TimelineBody(this); ENSURE(body != NULL); - headerContainer = new HeaderContainer(this); + headerContainer = new TimelineHeaderContainer(this); ENSURE(headerContainer != NULL); ruler = new TimelineRuler(this); ENSURE(ruler != NULL); diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index 9a43769ed..7785e7bc8 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -27,7 +27,7 @@ #define TIMELINE_WIDGET_HPP #include "../gtk-lumiera.hpp" -#include "timeline/header-container.hpp" +#include "timeline/timeline-header-container.hpp" #include "timeline/timeline-body.hpp" #include "timeline/timeline-ruler.hpp" #include "timeline/timeline-tool.hpp" @@ -228,7 +228,7 @@ protected: std::vector tracks; // Child Widgets - timeline::HeaderContainer *headerContainer; + timeline::TimelineHeaderContainer *headerContainer; timeline::TimelineBody *body; timeline::TimelineRuler *ruler; @@ -257,7 +257,7 @@ protected: static const double ZoomIncrement; friend class timeline::TimelineBody; - friend class timeline::HeaderContainer; + friend class timeline::TimelineHeaderContainer; friend class timeline::TimelineRuler; friend class timeline::Tool; friend class timeline::ArrowTool; diff --git a/src/gui/widgets/timeline/header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp similarity index 88% rename from src/gui/widgets/timeline/header-container.cpp rename to src/gui/widgets/timeline/timeline-header-container.cpp index 27812ccd1..ba8323aab 100644 --- a/src/gui/widgets/timeline/header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -1,5 +1,6 @@ /* - header-container.cpp - Implementation of the header container widget + timeline-header-container.cpp - Implementation of the timeline + header container widget Copyright (C) Lumiera.org 2008, Joel Holdsworth @@ -22,7 +23,7 @@ #include -#include "header-container.hpp" +#include "timeline-header-container.hpp" #include "track.hpp" #include "../timeline-widget.hpp" @@ -33,9 +34,9 @@ namespace gui { namespace widgets { namespace timeline { -HeaderContainer::HeaderContainer(gui::widgets::TimelineWidget +TimelineHeaderContainer::TimelineHeaderContainer(gui::widgets::TimelineWidget *timeline_widget) : - Glib::ObjectBase("HeaderContainer"), + Glib::ObjectBase("TimelineHeaderContainer"), timelineWidget(timeline_widget), margin(-1) { @@ -49,14 +50,14 @@ HeaderContainer::HeaderContainer(gui::widgets::TimelineWidget // Connect to the timeline widget's vertical scroll event, // so that we get notified when the view shifts timelineWidget->verticalAdjustment.signal_value_changed().connect( - sigc::mem_fun(this, &HeaderContainer::on_scroll) ); + sigc::mem_fun(this, &TimelineHeaderContainer::on_scroll) ); // Install style properties register_styles(); } void -HeaderContainer::update_headers() +TimelineHeaderContainer::update_headers() { REQUIRE(timelineWidget != NULL); @@ -83,7 +84,7 @@ HeaderContainer::update_headers() } void -HeaderContainer::on_realize() +TimelineHeaderContainer::on_realize() { set_flags(Gtk::NO_WINDOW); @@ -119,7 +120,7 @@ HeaderContainer::on_realize() } void -HeaderContainer::on_unrealize() +TimelineHeaderContainer::on_unrealize() { // Unreference any window we may have created gdkWindow.clear(); @@ -129,7 +130,7 @@ HeaderContainer::on_unrealize() } void -HeaderContainer::on_size_request (Requisition* requisition) +TimelineHeaderContainer::on_size_request (Requisition* requisition) { // Initialize the output parameter: *requisition = Gtk::Requisition(); @@ -148,7 +149,7 @@ HeaderContainer::on_size_request (Requisition* requisition) } void -HeaderContainer::on_size_allocate (Allocation& allocation) +TimelineHeaderContainer::on_size_allocate (Allocation& allocation) { // Use the offered allocation for this container: set_allocation(allocation); @@ -162,7 +163,7 @@ HeaderContainer::on_size_allocate (Allocation& allocation) } void -HeaderContainer::forall_vfunc(gboolean /* include_internals */, +TimelineHeaderContainer::forall_vfunc(gboolean /* include_internals */, GtkCallback callback, gpointer callback_data) { BOOST_FOREACH( RootHeader &header, rootHeaders ) @@ -173,7 +174,7 @@ HeaderContainer::forall_vfunc(gboolean /* include_internals */, } bool -HeaderContainer::on_expose_event(GdkEventExpose *event) +TimelineHeaderContainer::on_expose_event(GdkEventExpose *event) { if(gdkWindow) { @@ -211,7 +212,7 @@ HeaderContainer::on_expose_event(GdkEventExpose *event) } void -HeaderContainer::on_scroll() +TimelineHeaderContainer::on_scroll() { // If the scroll has changed, we will have to shift all the // header widgets @@ -219,7 +220,7 @@ HeaderContainer::on_scroll() } void -HeaderContainer::layout_headers() +TimelineHeaderContainer::layout_headers() { ASSERT(timelineWidget != NULL); @@ -261,7 +262,7 @@ HeaderContainer::layout_headers() } void -HeaderContainer::register_styles() const +TimelineHeaderContainer::register_styles() const { GtkWidgetClass *klass = GTK_WIDGET_CLASS(G_OBJECT_GET_CLASS(gobj())); @@ -273,7 +274,7 @@ HeaderContainer::register_styles() const } void -HeaderContainer::read_styles() +TimelineHeaderContainer::read_styles() { if(margin <= 0) get_style_property("heading_margin", margin); diff --git a/src/gui/widgets/timeline/header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp similarity index 90% rename from src/gui/widgets/timeline/header-container.hpp rename to src/gui/widgets/timeline/timeline-header-container.hpp index 84f15116d..480ab6cde 100644 --- a/src/gui/widgets/timeline/header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -1,5 +1,6 @@ /* - header-container.hpp - Declaration of the header container widget + timeline-header-container.cpp - Declaration of the timeline + header container widget Copyright (C) Lumiera.org 2008, Joel Holdsworth @@ -19,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/** @file header-container.hpp +/** @file timeline-header-container.hpp ** This file contains the definition of the header container ** widget */ @@ -40,11 +41,11 @@ namespace timeline { class Track; /** - * A helper class for the TimelineWidget. HeaderContainer is - * container widget for all the left-hand-side header widgets + * A helper class for the TimelineWidget. TimelineHeaderContainer + * is container widget for all the left-hand-side header widgets * associated with timeline tracks. */ -class HeaderContainer : public Gtk::Container +class TimelineHeaderContainer : public Gtk::Container { public: /** @@ -52,7 +53,7 @@ public: * * @param[in] timeline_widget A pointer to the owner timeline widget */ - HeaderContainer(gui::widgets::TimelineWidget* timeline_widget); + TimelineHeaderContainer(gui::widgets::TimelineWidget* timeline_widget); /** * Attaches the header all the header widgets of root From 3a4175868275f615456442e1c9a9383825c0f0fb Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 18 Oct 2008 12:25:18 +0100 Subject: [PATCH 02/59] Changed the "delete" variable name to "del" to satisfy the C++ compiler --- src/lib/psplay.c | 18 +++++++++--------- src/lib/psplay.h | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lib/psplay.c b/src/lib/psplay.c index 7647fd905..1d2d4dd27 100644 --- a/src/lib/psplay.c +++ b/src/lib/psplay.c @@ -66,7 +66,7 @@ static inline uint32_t psplay_fast_prng () PSplay -psplay_init (PSplay self, psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn delete) +psplay_init (PSplay self, psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn del) { NOBUG_INIT_FLAG (psplay); TRACE (psplay); @@ -79,7 +79,7 @@ psplay_init (PSplay self, psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn self->found_parent = &self->tree; self->cmp = cmp; self->key = key; - self->delete = delete; + self->del = del; self->elem_cnt = 0; self->log2 = 0; } @@ -88,12 +88,12 @@ psplay_init (PSplay self, psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn PSplay -psplay_new (psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn delete) +psplay_new (psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn del) { PSplay self = malloc (sizeof *self); if (self) { - psplay_init (self , cmp, key, delete); + psplay_init (self , cmp, key, del); } return self; } @@ -107,8 +107,8 @@ psplay_destroy (PSplay self) if (self) while (self->tree) { PSplaynode n = psplay_remove (self, self->tree); - if (self->delete) - self->delete (n); + if (self->del) + self->del (n); } return self; } @@ -400,7 +400,7 @@ void psplay_delete_node (PSplay self, PSplaynode node) { if (node) - self->delete (psplay_remove (self, node)); + self->del (psplay_remove (self, node)); } @@ -428,8 +428,8 @@ psplay_handle (PSplay self, PSplaynode node, psplay_delete_fn res) else if (res == PSPLAY_REMOVE) { psplay_remove (self, node); - if (self->delete) - self->delete (node); + if (self->del) + self->del (node); } else { diff --git a/src/lib/psplay.h b/src/lib/psplay.h index b3c016c52..70c450fe3 100644 --- a/src/lib/psplay.h +++ b/src/lib/psplay.h @@ -94,7 +94,7 @@ struct psplay_struct PSplaynode* found_parent; /* maybe direct parent of last found node, used for fast remove */ psplay_cmp_fn cmp; psplay_key_fn key; - psplay_delete_fn delete; + psplay_delete_fn del; size_t elem_cnt; unsigned log2; /* roughly log2 of the elem_cnt*/ @@ -122,7 +122,7 @@ psplay_nelements (PSplay self) * @return self */ PSplay -psplay_init (PSplay self, psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn delete); +psplay_init (PSplay self, psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn del); /** @@ -142,7 +142,7 @@ psplay_destroy (PSplay self); * @return allcoated splay tree or NULL on error */ PSplay -psplay_new (psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn delete); +psplay_new (psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn del); /** From f75af1dec3a13ab9c586bdd1fafe8a1fad75731f Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sat, 18 Oct 2008 18:03:35 +0200 Subject: [PATCH 03/59] liblumiprocmobjectcontroller.a is not needed anymore in tests --- tests/common/Makefile.am | 1 - tests/components/Makefile.am | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/common/Makefile.am b/tests/common/Makefile.am index 55393df9c..f10134e33 100644 --- a/tests/common/Makefile.am +++ b/tests/common/Makefile.am @@ -27,7 +27,6 @@ test_common_LDADD = \ liblumiprocmobjectsession.a \ liblumiprocasset.a \ liblumiprocmobject.a \ - liblumiprocmobjectcontroller.a \ liblumi.a \ liblumicommon.a \ liblumibackend.a \ diff --git a/tests/components/Makefile.am b/tests/components/Makefile.am index 733737580..657b51f85 100644 --- a/tests/components/Makefile.am +++ b/tests/components/Makefile.am @@ -27,7 +27,6 @@ test_components_LDADD = \ liblumiprocmobjectsession.a \ liblumiprocasset.a \ liblumiprocmobject.a \ - liblumiprocmobjectcontroller.a \ liblumi.a \ liblumicommon.a \ liblumibackend.a \ From d880b341b45e96e724d69b1a04abff7cfb5e298c Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Mon, 20 Oct 2008 18:50:37 +0100 Subject: [PATCH 04/59] Showed some love to viewer panel --- src/gui/panels/viewer-panel.cpp | 16 ++++------------ src/gui/panels/viewer-panel.hpp | 24 ++++++++++++++++-------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/gui/panels/viewer-panel.cpp b/src/gui/panels/viewer-panel.cpp index 4ebd3d0cb..e280694f3 100644 --- a/src/gui/panels/viewer-panel.cpp +++ b/src/gui/panels/viewer-panel.cpp @@ -31,18 +31,10 @@ namespace panels { ViewerPanel::ViewerPanel() : Panel("viewer", _("Viewer"), "panel_viewer") - { - //----- Set up the Tool Bar -----// - // Add the commands - - - // Configure the toolbar - toolBar.set_toolbar_style(TOOLBAR_ICONS); - - //----- Pack in the Widgets -----// - pack_start(display, PACK_EXPAND_WIDGET); - pack_start(toolBar, PACK_SHRINK); - } +{ + //----- Pack in the Widgets -----// + pack_start(display, PACK_EXPAND_WIDGET); +} } // namespace panels } // namespace gui diff --git a/src/gui/panels/viewer-panel.hpp b/src/gui/panels/viewer-panel.hpp index 0185e6d4a..a53e30561 100644 --- a/src/gui/panels/viewer-panel.hpp +++ b/src/gui/panels/viewer-panel.hpp @@ -34,16 +34,24 @@ namespace gui { namespace panels { - class ViewerPanel : public Panel - { - public: - ViewerPanel(); +/** + * A panel to display the video output. + **/ +class ViewerPanel : public Panel +{ +public: + /** + * Contructor. + **/ + ViewerPanel(); - protected: +protected: - gui::widgets::VideoDisplayWidget display; - Gtk::Toolbar toolBar; - }; + /** + * The video display widget, which will display the video. + **/ + gui::widgets::VideoDisplayWidget display; +}; } // namespace panels } // namespace gui From 6396323e9e89d45467424234234fdbec838ab219 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Mon, 20 Oct 2008 18:51:46 +0100 Subject: [PATCH 05/59] Added the backend as a lib, and included the interface header --- src/gui/Makefile.am | 3 ++- src/gui/gtk-lumiera.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 7e8d356ea..4b7504ef1 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -77,7 +77,8 @@ lumigui_SOURCES = \ $(lumigui_srcdir)/output/xvdisplayer.hpp lumigui_LDFLAGS = -lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumicommon.a liblumi.a $(NOBUGMT_LUMIERA_LIBS) +lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumibackend.a liblumicommon.a \ + liblumi.a $(NOBUGMT_LUMIERA_LIBS) lumigui_DEPENDENCIES = \ $(top_builddir)/lumiera_ui.rc \ diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index 1a895084f..c73e45977 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -32,6 +32,10 @@ #include "workspace/workspace-window.hpp" #include "model/project.hpp" +extern "C" { +#include "backend/interface.h" +} + NOBUG_CPP_DEFINE_FLAG(gui); using namespace Gtk; From ee6fac5914ece1a63fb96e9b833daeeafa127e7b Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Mon, 20 Oct 2008 19:19:06 +0100 Subject: [PATCH 06/59] Made GtkLumiera and WindowManager boost::noncopyable --- src/gui/gtk-lumiera.hpp | 3 ++- src/gui/window-manager.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/gtk-lumiera.hpp b/src/gui/gtk-lumiera.hpp index 180148f7f..a25927712 100644 --- a/src/gui/gtk-lumiera.hpp +++ b/src/gui/gtk-lumiera.hpp @@ -31,6 +31,7 @@ #include #include #include +#include extern "C" { #include @@ -91,7 +92,7 @@ static const gchar* AppAuthors[] = { /** * The main application class. */ -class GtkLumiera +class GtkLumiera : private boost::noncopyable { public: int main(int argc, char *argv[]); diff --git a/src/gui/window-manager.hpp b/src/gui/window-manager.hpp index c25a763ef..49c69ea50 100644 --- a/src/gui/window-manager.hpp +++ b/src/gui/window-manager.hpp @@ -35,7 +35,7 @@ namespace gui { /** * The centralised manager of all lumiera-gui's windows. **/ -class WindowManager +class WindowManager : private boost::noncopyable { public: /** From 1e3df8028841508528ea71f0832b32f2a853a76b Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Mon, 20 Oct 2008 19:28:29 +0100 Subject: [PATCH 07/59] Added linkage to the proc layer --- src/gui/Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 4b7504ef1..835e5f1a5 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -29,9 +29,9 @@ lumigui_CPPFLAGS = $(AM_CPPFLAGS) \ bin_PROGRAMS += lumigui lumigui_SOURCES = \ - $(lumigui_srcdir)/gtk-lumiera.cpp \ + $(lumigui_srcdir)/gtk-lumiera.cpp \ $(lumigui_srcdir)/gtk-lumiera.hpp \ - $(lumigui_srcdir)/window-manager.cpp \ + $(lumigui_srcdir)/window-manager.cpp \ $(lumigui_srcdir)/window-manager.hpp \ $(lumigui_srcdir)/workspace/actions.cpp \ $(lumigui_srcdir)/workspace/actions.hpp \ @@ -77,8 +77,8 @@ lumigui_SOURCES = \ $(lumigui_srcdir)/output/xvdisplayer.hpp lumigui_LDFLAGS = -lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumibackend.a liblumicommon.a \ - liblumi.a $(NOBUGMT_LUMIERA_LIBS) +lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumiproc.a liblumibackend.a \ + liblumicommon.a liblumi.a $(NOBUGMT_LUMIERA_LIBS) lumigui_DEPENDENCIES = \ $(top_builddir)/lumiera_ui.rc \ From 0e5a13ec31257dc0d0b2aac2628874d156cb3270 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 15 Oct 2008 23:04:02 +0200 Subject: [PATCH 08/59] give a warning when using experimental interfaces --- src/backend/interface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backend/interface.c b/src/backend/interface.c index 58d0d0c0f..917c663d9 100644 --- a/src/backend/interface.c +++ b/src/backend/interface.c @@ -49,6 +49,7 @@ lumiera_interface_open (const char* interface, unsigned version, size_t minminor { LumieraInterfacenode self = NULL; TRACE (interface, "%s", name); + WARN_IF (version == 0, interface, "opening experimental interface: %s_%d_%s", interface, version, name); LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex) { From 23508f3f745e57f15247c149db1f16dfd9612226 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 21 Oct 2008 06:19:52 +0200 Subject: [PATCH 09/59] Nice, follow scons, name it liblumiera.a too --- src/lib/Makefile.am | 56 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 55d88e71a..3dbdbab9f 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -15,36 +15,36 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -liblumi_a_srcdir = $(top_srcdir)/src/lib -noinst_LIBRARIES += liblumi.a +liblumiera_a_srcdir = $(top_srcdir)/src/lib +noinst_LIBRARIES += liblumiera.a -liblumi_a_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror +liblumiera_a_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror -liblumi_a_SOURCES = \ - $(liblumi_a_srcdir)/error.c \ - $(liblumi_a_srcdir)/mutex.c \ - $(liblumi_a_srcdir)/rwlock.c \ - $(liblumi_a_srcdir)/condition.c \ - $(liblumi_a_srcdir)/luid.c \ - $(liblumi_a_srcdir)/safeclib.c \ - $(liblumi_a_srcdir)/cuckoo.c \ - $(liblumi_a_srcdir)/psplay.c \ - $(liblumi_a_srcdir)/mrucache.c \ - $(liblumi_a_srcdir)/time.c \ - $(liblumi_a_srcdir)/appconfig.cpp +liblumiera_a_SOURCES = \ + $(liblumiera_a_srcdir)/error.c \ + $(liblumiera_a_srcdir)/mutex.c \ + $(liblumiera_a_srcdir)/rwlock.c \ + $(liblumiera_a_srcdir)/condition.c \ + $(liblumiera_a_srcdir)/luid.c \ + $(liblumiera_a_srcdir)/safeclib.c \ + $(liblumiera_a_srcdir)/cuckoo.c \ + $(liblumiera_a_srcdir)/psplay.c \ + $(liblumiera_a_srcdir)/mrucache.c \ + $(liblumiera_a_srcdir)/time.c \ + $(liblumiera_a_srcdir)/appconfig.cpp noinst_HEADERS += \ - $(liblumi_a_srcdir)/error.h \ - $(liblumi_a_srcdir)/mutex.h \ - $(liblumi_a_srcdir)/rwlock.h \ - $(liblumi_a_srcdir)/condition.h \ - $(liblumi_a_srcdir)/luid.h \ - $(liblumi_a_srcdir)/safeclib.h \ - $(liblumi_a_srcdir)/cuckoo.h \ - $(liblumi_a_srcdir)/psplay.h \ - $(liblumi_a_srcdir)/mrucache.h \ - $(liblumi_a_srcdir)/time.h \ - $(liblumi_a_srcdir)/ppmpl.h \ - $(liblumi_a_srcdir)/appconfig.hpp \ - $(liblumi_a_srcdir)/lifecycleregistry.hpp + $(liblumiera_a_srcdir)/error.h \ + $(liblumiera_a_srcdir)/mutex.h \ + $(liblumiera_a_srcdir)/rwlock.h \ + $(liblumiera_a_srcdir)/condition.h \ + $(liblumiera_a_srcdir)/luid.h \ + $(liblumiera_a_srcdir)/safeclib.h \ + $(liblumiera_a_srcdir)/cuckoo.h \ + $(liblumiera_a_srcdir)/psplay.h \ + $(liblumiera_a_srcdir)/mrucache.h \ + $(liblumiera_a_srcdir)/time.h \ + $(liblumiera_a_srcdir)/ppmpl.h \ + $(liblumiera_a_srcdir)/appconfig.hpp \ + $(liblumiera_a_srcdir)/lifecycleregistry.hpp From a95a40613ca643d2708a6fabeba772845b2b64ff Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 21 Oct 2008 06:48:59 +0200 Subject: [PATCH 10/59] Fix: oops some more liblumi to liblumiera renames --- src/gui/Makefile.am | 2 +- tests/Makefile.am | 20 ++++++++++---------- tests/common/Makefile.am | 2 +- tests/components/Makefile.am | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 79e402310..16e907e44 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -82,7 +82,7 @@ lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumicommon.a liblumi.a $(NOBUGMT_LUMIERA_ lumigui_DEPENDENCIES = \ $(top_builddir)/lumiera_ui.rc \ $(top_builddir)/liblumicommon.a \ - $(top_builddir)/liblumi.a + $(top_builddir)/liblumiera.a $(top_builddir)/lumiera_ui.rc: cp $(lumigui_srcdir)/lumiera_ui.rc $(top_builddir) diff --git a/tests/Makefile.am b/tests/Makefile.am index 0c7f80f12..10cdeed10 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,51 +21,51 @@ tests_srcdir = $(top_srcdir)/tests check_PROGRAMS += test-error test_error_SOURCES = $(tests_srcdir)/error/errortest.c test_error_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_error_LDADD = liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl +test_error_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl check_PROGRAMS += test-locking test_locking_SOURCES = $(tests_srcdir)/library/test-locking.c test_locking_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_locking_LDADD = liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_locking_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm check_PROGRAMS += test-llist test_llist_SOURCES = $(tests_srcdir)/library/test-llist.c test_llist_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_llist_LDADD = liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_llist_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm check_PROGRAMS += test-psplay test_psplay_SOURCES = $(tests_srcdir)/library/test-psplay.c test_psplay_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ -test_psplay_LDADD = liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_psplay_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm check_PROGRAMS += test-safeclib test_safeclib_SOURCES = $(tests_srcdir)/library/test-safeclib.c test_safeclib_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_safeclib_LDADD = liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_safeclib_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm check_PROGRAMS += test-luid test_luid_SOURCES = $(tests_srcdir)/library/test-luid.c test_luid_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_luid_LDADD = liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_luid_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm check_PROGRAMS += test-interfaces test_interfaces_SOURCES = $(tests_srcdir)/backend/test-interfaces.c test_interfaces_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_interfaces_LDADD = liblumibackend.a liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_interfaces_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm check_PROGRAMS += test-filedescriptors test_filedescriptors_SOURCES = $(tests_srcdir)/backend/test-filedescriptors.c test_filedescriptors_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_filedescriptors_LDADD = liblumibackend.a liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_filedescriptors_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm check_PROGRAMS += test-filehandles test_filehandles_SOURCES = $(tests_srcdir)/backend/test-filehandles.c test_filehandles_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_filehandles_LDADD = liblumibackend.a liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_filehandles_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm check_PROGRAMS += test-config test_config_SOURCES = $(tests_srcdir)/backend/test-config.c test_config_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ -test_config_LDADD = liblumibackend.a liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_config_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm TESTS = $(tests_srcdir)/test.sh diff --git a/tests/common/Makefile.am b/tests/common/Makefile.am index f10134e33..8582b26f2 100644 --- a/tests/common/Makefile.am +++ b/tests/common/Makefile.am @@ -27,7 +27,7 @@ test_common_LDADD = \ liblumiprocmobjectsession.a \ liblumiprocasset.a \ liblumiprocmobject.a \ - liblumi.a \ + liblumiera.a \ liblumicommon.a \ liblumibackend.a \ $(NOBUGMT_LUMIERA_LIBS) -ldl -lboost_program_options-mt -lboost_regex-mt diff --git a/tests/components/Makefile.am b/tests/components/Makefile.am index 657b51f85..43503640a 100644 --- a/tests/components/Makefile.am +++ b/tests/components/Makefile.am @@ -27,7 +27,7 @@ test_components_LDADD = \ liblumiprocmobjectsession.a \ liblumiprocasset.a \ liblumiprocmobject.a \ - liblumi.a \ + liblumiera.a \ liblumicommon.a \ liblumibackend.a \ $(NOBUGMT_LUMIERA_LIBS) -ldl -lboost_program_options-mt -lboost_regex-mt From 7a68692c4fda3a342fe49b5d1f77e213cbc27c83 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 22 Oct 2008 03:30:13 +0200 Subject: [PATCH 11/59] Fix: $(iconcommand) depends on rsvg-convert --- icons/Makefile.am | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/icons/Makefile.am b/icons/Makefile.am index 6693b6d1d..a7338d306 100644 --- a/icons/Makefile.am +++ b/icons/Makefile.am @@ -33,33 +33,34 @@ iconcommand = python $(top_srcdir)/admin/render-icon.py 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 + + +$(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png : $(svgdir)/tool-arrow.svg $(top_builddir)/rsvg-convert $(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 +$(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 $(top_builddir)/rsvg-convert $(iconcommand) $< $(icondir) -$(16x16)/panel-assets.png: +$(16x16)/panel-assets.png: $(top_builddir)/rsvg-convert 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: +$(22x22)/panel-assets.png: $(top_builddir)/rsvg-convert + cp $(22x22pre)/panel-assets.png $(22x22) +$(32x32)/panel-assets.png: $(top_builddir)/rsvg-convert + cp $(32x32pre)/panel-assets.png $(32x32) + +$(16x16)/panel-timeline.png: $(top_builddir)/rsvg-convert cp $(16x16pre)/panel-timeline.png $(16x16) -$(16x16)/panel-viewer.png: +$(16x16)/panel-viewer.png: $(top_builddir)/rsvg-convert cp $(16x16pre)/panel-viewer.png $(16x16) -$(22x22)/panel-viewer.png: +$(22x22)/panel-viewer.png: $(top_builddir)/rsvg-convert cp $(22x22pre)/panel-viewer.png $(22x22) -$(32x32)/panel-viewer.png: +$(32x32)/panel-viewer.png: $(top_builddir)/rsvg-convert cp $(32x32pre)/panel-viewer.png $(32x32) From 691dc8fd4ea8f8ae4a771f20d8b32350dd38e0d4 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 22 Oct 2008 03:42:15 +0200 Subject: [PATCH 12/59] Does this ever end? found 2 more liblumi.a --- admin/Makefile.am | 2 +- src/tool/Makefile.am | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/admin/Makefile.am b/admin/Makefile.am index f2c9c0636..da1c244a7 100644 --- a/admin/Makefile.am +++ b/admin/Makefile.am @@ -20,7 +20,7 @@ admin_srcdir = $(top_srcdir)/admin noinst_PROGRAMS += vgsuppression vgsuppression_SOURCES = $(admin_srcdir)/vgsuppression.c vgsuppression_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -vgsuppression_LDADD = liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl +vgsuppression_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl noinst_PROGRAMS += rsvg-convert rsvg_convert_SOURCES = $(admin_srcdir)/rsvg-convert.c diff --git a/src/tool/Makefile.am b/src/tool/Makefile.am index 69c4a7f25..8a4234c05 100644 --- a/src/tool/Makefile.am +++ b/src/tool/Makefile.am @@ -24,5 +24,4 @@ luidgen_CPPFLAGS = -I$(top_srcdir)/src/ luidgen_SOURCES = \ $(lumitool_srcdir)/luidgen.c -luidgen_LDADD = liblumi.a - +luidgen_LDADD = liblumiera.a From ca0cea1c16df703429d3a0aa0a1c1786acba717f Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 22 Oct 2008 03:50:00 +0200 Subject: [PATCH 13/59] no, it doesn't end ... --- src/gui/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 16e907e44..316887403 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -77,7 +77,7 @@ lumigui_SOURCES = \ $(lumigui_srcdir)/output/xvdisplayer.hpp lumigui_LDFLAGS = -lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumicommon.a liblumi.a $(NOBUGMT_LUMIERA_LIBS) +lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumicommon.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) lumigui_DEPENDENCIES = \ $(top_builddir)/lumiera_ui.rc \ From a3030515bef5b7e725f1b61ec2ed23a8878d55f8 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 22 Oct 2008 22:23:04 +0100 Subject: [PATCH 14/59] Corrected a selection rendering bug in TimelineBody --- src/gui/widgets/timeline/timeline-body.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp index 11c3b2b73..7fa0881c5 100644 --- a/src/gui/widgets/timeline/timeline-body.cpp +++ b/src/gui/widgets/timeline/timeline-body.cpp @@ -147,11 +147,8 @@ TimelineBody::on_expose_event(GdkEventExpose* event) Cairo::RefPtr cr = window->create_cairo_context(); REQUIRE(cr); - - // Translate the view by the scroll distance - cr->translate(0, -get_vertical_offset()); - - // Draw the view + + //----- Draw the view -----// draw_tracks(cr); draw_selection(cr); draw_playback_point(cr); @@ -272,6 +269,9 @@ TimelineBody::draw_tracks(Cairo::RefPtr cr) Cairo::Matrix view_matrix; cr->get_matrix(view_matrix); + // Translate the view by the scroll distance + cr->translate(0, -get_vertical_offset()); + // Interate drawing each track BOOST_FOREACH( Track* track, timelineWidget->tracks ) { From efd9ab771b02e731b0327ea509c2466f76ca2cbc Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 22 Oct 2008 23:11:23 +0100 Subject: [PATCH 15/59] Added track tree support and added widgets to headers --- icons/Makefile.am | 34 +- icons/svg/track-disabled.svg | 663 ++++++++++++ icons/svg/track-enabled.svg | 967 ++++++++++++++++++ icons/svg/track-locked.svg | 866 ++++++++++++++++ icons/svg/track-unlocked.svg | 655 ++++++++++++ src/gui/widgets/timeline-widget.cpp | 19 +- src/gui/widgets/timeline-widget.hpp | 8 +- src/gui/widgets/timeline/timeline-body.cpp | 49 +- src/gui/widgets/timeline/timeline-body.hpp | 6 + .../timeline/timeline-header-container.cpp | 139 ++- .../timeline/timeline-header-container.hpp | 33 +- src/gui/widgets/timeline/track.cpp | 42 +- src/gui/widgets/timeline/track.hpp | 35 +- src/gui/window-manager.cpp | 7 +- 14 files changed, 3405 insertions(+), 118 deletions(-) create mode 100644 icons/svg/track-disabled.svg create mode 100644 icons/svg/track-enabled.svg create mode 100644 icons/svg/track-locked.svg create mode 100644 icons/svg/track-unlocked.svg diff --git a/icons/Makefile.am b/icons/Makefile.am index 6693b6d1d..281901e78 100644 --- a/icons/Makefile.am +++ b/icons/Makefile.am @@ -33,18 +33,40 @@ iconcommand = python $(top_srcdir)/admin/render-icon.py 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 + 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)/track-disabled.png \ + $(16x16)/track-enabled.png \ + $(16x16)/track-locked.png \ + $(16x16)/track-unlocked.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 + +# ========== SVG Icons ========== + +# Timeline Tools $(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) +# Timeline Tracks +$(16x16)/track-disabled.png : $(svgdir)/track-disabled.svg + $(iconcommand) $< $(icondir) +$(16x16)/track-enabled.png : $(svgdir)/track-enabled.svg + $(iconcommand) $< $(icondir) +$(16x16)/track-locked.png : $(svgdir)/track-locked.svg + $(iconcommand) $< $(icondir) +$(16x16)/track-unlocked.png : $(svgdir)/track-unlocked.svg + $(iconcommand) $< $(icondir) + +# ========== Prerendered Icons ========== + +# Panels + $(16x16)/panel-assets.png: cp $(16x16pre)/panel-assets.png $(16x16) $(22x22)/panel-assets.png: diff --git a/icons/svg/track-disabled.svg b/icons/svg/track-disabled.svg new file mode 100644 index 000000000..04e87768e --- /dev/null +++ b/icons/svg/track-disabled.svg @@ -0,0 +1,663 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/icons/svg/track-enabled.svg b/icons/svg/track-enabled.svg new file mode 100644 index 000000000..ab6af9f53 --- /dev/null +++ b/icons/svg/track-enabled.svg @@ -0,0 +1,967 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/icons/svg/track-locked.svg b/icons/svg/track-locked.svg new file mode 100644 index 000000000..3ff1d34a4 --- /dev/null +++ b/icons/svg/track-locked.svg @@ -0,0 +1,866 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/icons/svg/track-unlocked.svg b/icons/svg/track-unlocked.svg new file mode 100644 index 000000000..beea19846 --- /dev/null +++ b/icons/svg/track-unlocked.svg @@ -0,0 +1,655 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 6c397f9f1..40d0ad09f 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -69,6 +69,9 @@ TimelineWidget::TimelineWidget() : set_selection(2000000, 4000000); tracks.push_back(&video1); + video1.add_child_track(&video1a); + video1.add_child_track(&video1b); + video1b.add_child_track(&video1ba); tracks.push_back(&video2); update_tracks(); @@ -332,7 +335,7 @@ TimelineWidget::update_tracks() BOOST_FOREACH( Track* track, tracks ) { ASSERT(track != NULL); - totalHeight += track->get_height() + TrackPadding; + totalHeight += measure_branch_height(track); } } @@ -378,6 +381,20 @@ TimelineWidget::update_scroll() } +int +TimelineWidget::measure_branch_height(Track* track) +{ + REQUIRE(track != NULL); + + int height = track->get_height(); + + // Recurse through all the children + BOOST_FOREACH( Track* child, track->get_child_tracks() ) + height += measure_branch_height(child); + + return height; +} + int TimelineWidget::get_y_scroll_offset() const { diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index 7785e7bc8..b1b3b0600 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -202,6 +202,8 @@ private: void update_scroll(); + static int measure_branch_height(timeline::Track* track); + int get_y_scroll_offset() const; bool on_motion_in_body_notify_event(GdkEventMotion *event); @@ -224,6 +226,9 @@ protected: int totalHeight; timeline::Track video1; + timeline::Track video1a; + timeline::Track video1b; + timeline::Track video1ba; timeline::Track video2; std::vector tracks; @@ -239,8 +244,7 @@ protected: // Signals sigc::signal viewChangedSignal; sigc::signal mouseHoverSignal; - sigc::signal - playbackPeriodDragReleasedSignal; + sigc::signal playbackPeriodDragReleasedSignal; /* ===== Constants ===== */ public: diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp index 7fa0881c5..72d56fd24 100644 --- a/src/gui/widgets/timeline/timeline-body.cpp +++ b/src/gui/widgets/timeline/timeline-body.cpp @@ -276,28 +276,45 @@ TimelineBody::draw_tracks(Cairo::RefPtr cr) BOOST_FOREACH( Track* track, timelineWidget->tracks ) { ASSERT(track != NULL); - - const int height = track->get_height(); - ASSERT(height >= 0); - - // Draw the track background - cr->rectangle(0, 0, allocation.get_width(), height); - gdk_cairo_set_source_color(cr->cobj(), &backgroundColour); - cr->fill(); - - // Render the track - cr->save(); - track->draw_track(cr); - cr->restore(); - - // Shift for the next track - cr->translate(0, height + TimelineWidget::TrackPadding); + draw_track_recursive(cr, track, allocation.get_width()); } // Restore the view matrix cr->set_matrix(view_matrix); } +void +TimelineBody::draw_track_recursive(Cairo::RefPtr cr, + const Track *track, const int view_width) const +{ + REQUIRE(cr); + REQUIRE(track != NULL); + + const int height = track->get_height(); + ASSERT(height >= 0); + + // Draw the track background + cr->rectangle(0, 0, view_width, + height - TimelineWidget::TrackPadding); + GdkColor colour = backgroundColour; // Needed to preserve const qualifier + gdk_cairo_set_source_color(cr->cobj(), &colour); + cr->fill(); + + // Render the track + cr->save(); + track->draw_track(cr); + cr->restore(); + + // Shift for the next track + cr->translate(0, height); + + BOOST_FOREACH( Track* child, track->get_child_tracks() ) + { + ASSERT(track != NULL); + draw_track_recursive(cr, child, view_width); + } +} + void TimelineBody::draw_selection(Cairo::RefPtr cr) { diff --git a/src/gui/widgets/timeline/timeline-body.hpp b/src/gui/widgets/timeline/timeline-body.hpp index 894cb9f09..9ce48f5e1 100644 --- a/src/gui/widgets/timeline/timeline-body.hpp +++ b/src/gui/widgets/timeline/timeline-body.hpp @@ -36,6 +36,8 @@ class TimelineWidget; namespace timeline { +class Track; + /** * Implementation of the timeline body subwidget. This widget is * displayed in the centre of the timeline widget, and displays the @@ -111,6 +113,10 @@ private: */ void draw_tracks(Cairo::RefPtr cr); + void draw_track_recursive(Cairo::RefPtr cr, + const gui::widgets::timeline::Track *track, + const int view_width) const; + /** * Draws the selected timeline period. * @param cr The cairo context to draw into. diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index ba8323aab..3c16d912e 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -55,32 +55,15 @@ TimelineHeaderContainer::TimelineHeaderContainer(gui::widgets::TimelineWidget // Install style properties register_styles(); } - + void TimelineHeaderContainer::update_headers() { REQUIRE(timelineWidget != NULL); - - // Remove any pre-exisitng headers - BOOST_FOREACH( RootHeader header, rootHeaders ) - { - header.widget->unparent(); - } - rootHeaders.clear(); - // Add fresh headers BOOST_FOREACH( Track* track, timelineWidget->tracks ) - { - ASSERT(track != NULL); - - const RootHeader header = { &track->get_header_widget(), track }; - header.widget->set_parent(*this); - - rootHeaders.push_back(header); - } - - layout_headers(); + set_parent_recursive(track); } void @@ -132,18 +115,14 @@ TimelineHeaderContainer::on_unrealize() void TimelineHeaderContainer::on_size_request (Requisition* requisition) { - // Initialize the output parameter: - *requisition = Gtk::Requisition(); - // We don't care about the size of all the child widgets, but if we // don't send the size request down the tree, some widgets fail to - // calculate their text layout correctly. - BOOST_FOREACH( RootHeader header, rootHeaders ) - { - if(header.widget != NULL && header.widget->is_visible()) - header.widget->size_request(); - } - + // calculate their text layout correctly. + BOOST_FOREACH( Track* track, timelineWidget->tracks ) + size_request_recursive(track); + + // Initialize the output parameter: + *requisition = Gtk::Requisition(); requisition->width = TimelineWidget::HeaderWidth; requisition->height = 0; } @@ -166,10 +145,12 @@ void TimelineHeaderContainer::forall_vfunc(gboolean /* include_internals */, GtkCallback callback, gpointer callback_data) { - BOOST_FOREACH( RootHeader &header, rootHeaders ) + REQUIRE(callback != NULL); + + BOOST_FOREACH( Track* track, timelineWidget->tracks ) { - ASSERT(header.widget); - callback(header.widget->gobj(), callback_data); + ASSERT(track != NULL); + forall_vfunc_recursive(track, callback, callback_data); } } @@ -187,12 +168,12 @@ TimelineHeaderContainer::on_expose_event(GdkEventExpose *event) read_styles(); // Paint a border underneath all the root headers - BOOST_FOREACH( RootHeader &header, rootHeaders ) + BOOST_FOREACH( Track* track, timelineWidget->tracks ) { - ASSERT(header.widget); - ASSERT(header.track != NULL); + ASSERT(track != NULL); - const int height = header.track->get_height(); + const int height = TimelineWidget::measure_branch_height( + track); ASSERT(height >= 0); style->paint_box( @@ -237,30 +218,82 @@ TimelineHeaderContainer::layout_headers() const int header_width = container_allocation.get_width () - margin * 2; - BOOST_FOREACH( RootHeader &header, rootHeaders ) + BOOST_FOREACH( Track* track, timelineWidget->tracks ) { - ASSERT(header.widget); - ASSERT(header.track != NULL); - - const int height = header.track->get_height(); - ASSERT(height >= 0); - - Gtk::Allocation header_allocation; - header_allocation.set_x (margin); - header_allocation.set_y (offset - y_scroll_offset + margin); - header_allocation.set_width (header_width); - header_allocation.set_height (height - margin * 2); - - if(header.widget->is_visible()) - header.widget->size_allocate (header_allocation); - - offset += height + TimelineWidget::TrackPadding; + ASSERT(track != NULL); + layout_headers_recursive(track, y_scroll_offset, offset, + header_width, 0); } // Repaint the background of our parenting queue_draw (); } +void +TimelineHeaderContainer::layout_headers_recursive(Track *track, + const int y_scroll_offset, int &offset, + const int header_width, int depth) const +{ + const int height = track->get_height(); + ASSERT(height >= 0); + + const int indent = depth * 10; + + Allocation header_allocation; + header_allocation.set_x (margin + indent); + header_allocation.set_y (offset - y_scroll_offset + margin); + header_allocation.set_width (header_width - indent); + header_allocation.set_height (height - margin * 2); + + Widget &widget = track->get_header_widget(); + if(widget.is_visible()) + widget.size_allocate (header_allocation); + + offset += height + TimelineWidget::TrackPadding; + + // Recurse through all the children + BOOST_FOREACH( Track* child, track->get_child_tracks() ) + layout_headers_recursive(child, y_scroll_offset, offset, + header_width, depth + 1); +} + +void +TimelineHeaderContainer::set_parent_recursive(Track *track) +{ + REQUIRE(track != NULL); + track->get_header_widget().set_parent(*this); + + // Recurse through all the children + BOOST_FOREACH( Track* child, track->get_child_tracks() ) + set_parent_recursive(child); +} + +void +TimelineHeaderContainer::size_request_recursive(Track *track) +{ + REQUIRE(track != NULL); + if(track->get_header_widget().is_visible()) + track->get_header_widget().size_request(); + + // Recurse through all the children + BOOST_FOREACH( Track* child, track->get_child_tracks() ) + size_request_recursive(child); +} + +void +TimelineHeaderContainer::forall_vfunc_recursive(Track* track, + GtkCallback callback, gpointer callback_data) +{ + REQUIRE(track != NULL); + REQUIRE(callback != NULL); + + callback(track->get_header_widget().gobj(), callback_data); + + // Recurse through all the children + BOOST_FOREACH( Track* child, track->get_child_tracks() ) + forall_vfunc_recursive(child, callback, callback_data); +} + void TimelineHeaderContainer::register_styles() const { diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index 480ab6cde..d287f2056 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -119,6 +119,21 @@ private: */ void layout_headers(); + void layout_headers_recursive(Track *track, + const int y_scroll_offset, int &offset, + const int header_width, int depth) const; + + /** + * Recursively sets all the track header widgets to be child widgets + * of this widget. + **/ + void set_parent_recursive(Track *track); + + static void size_request_recursive(Track *track); + + static void forall_vfunc_recursive(Track* track, + GtkCallback callback, gpointer callback_data); + /** * Registers all the styles that this class will respond to. */ @@ -143,24 +158,6 @@ private: * widgets are scrolled. */ Glib::RefPtr gdkWindow; - - //----- Header List -----// - - /** - * A structure to represent a header widget and it's - * associated track - */ - struct RootHeader - { - Gtk::Widget *widget; - Track *track; - }; - - /** - * Contains a list of the root currently present on - * the timeline view - */ - std::vector< RootHeader > rootHeaders; //----- Style Values -----// diff --git a/src/gui/widgets/timeline/track.cpp b/src/gui/widgets/timeline/track.cpp index f8acb35de..bac443ced 100644 --- a/src/gui/widgets/timeline/track.cpp +++ b/src/gui/widgets/timeline/track.cpp @@ -29,12 +29,30 @@ namespace widgets { namespace timeline { Track::Track() : - label1("test1"), label2("test2"), label3("test3"), label4("test4") + enableButton(Gtk::StockID("track_enabled")), + lockButton(Gtk::StockID("track_unlocked")) { - headerWidget.pack_start(label1, PACK_EXPAND_WIDGET); - headerWidget.pack_start(label2, PACK_EXPAND_WIDGET); - headerWidget.pack_start(label3, PACK_EXPAND_WIDGET); - headerWidget.pack_start(label4, PACK_EXPAND_WIDGET); + buttonBar.append(enableButton); + buttonBar.append(lockButton); + + buttonBar.set_toolbar_style(TOOLBAR_ICONS); + buttonBar.set_icon_size(ICON_SIZE_MENU); + + headerWidget.pack_start(titleBox, PACK_SHRINK); + headerWidget.pack_start(buttonBar, PACK_SHRINK); +} + +void +Track::add_child_track(timeline::Track* child) +{ + REQUIRE(child != NULL); + children.push_back(child); +} + +const std::vector& +Track::get_child_tracks() const +{ + return children; } Gtk::Widget& @@ -43,20 +61,20 @@ Track::get_header_widget() return headerWidget; } +int +Track::get_height() const +{ + return 100; +} + Glib::ustring Track::get_title() { return "Hello"; } -int -Track::get_height() -{ - return 100; -} - void -Track::draw_track(Cairo::RefPtr cairo) +Track::draw_track(Cairo::RefPtr cairo) const { } diff --git a/src/gui/widgets/timeline/track.hpp b/src/gui/widgets/timeline/track.hpp index a1b6d48e8..9f7277dd1 100644 --- a/src/gui/widgets/timeline/track.hpp +++ b/src/gui/widgets/timeline/track.hpp @@ -32,25 +32,42 @@ namespace gui { namespace widgets { namespace timeline { +class Clip; + class Track { public: Track(); + void add_child_track(timeline::Track* child); + + const std::vector& get_child_tracks() const; + + Gtk::Widget& get_header_widget(); + + int get_height() const; + Glib::ustring get_title(); - Gtk::Widget& get_header_widget(); + void draw_track(Cairo::RefPtr cairo) const; + +private: + +private: - int get_height(); + //----- Data -----// + std::vector children; + std::vector clips; - void draw_track(Cairo::RefPtr cairo); - -protected: + //----- Header Widgets ------// + Gtk::VBox headerWidget; - Gtk::Label label1; - Gtk::Label label2; - Gtk::CheckButton label3; - Gtk::Button label4; + + Gtk::ToolButton enableButton; + Gtk::ToolButton lockButton; + + Gtk::Entry titleBox; + Gtk::Toolbar buttonBar; }; diff --git a/src/gui/window-manager.cpp b/src/gui/window-manager.cpp index 4a89158d7..c7cbb3c32 100644 --- a/src/gui/window-manager.cpp +++ b/src/gui/window-manager.cpp @@ -92,7 +92,12 @@ WindowManager::register_stock_items() add_stock_icon_set(factory, "panel-viewer", "panel_viewer", _("_Viewer")); add_stock_icon_set(factory, "tool-arrow", "tool_arrow", _("_Arrow")); - add_stock_icon_set(factory, "tool-i-beam", "tool_i_beam", _("_I-Beam")); + add_stock_icon_set(factory, "tool-i-beam", "tool_i_beam", _("_I-Beam")); + + add_stock_icon_set(factory, "track-disabled", "track_disabled", _("Track Disabled")); + add_stock_icon_set(factory, "track-enabled", "track_enabled", _("Track Enabled")); + add_stock_icon_set(factory, "track-locked", "track_locked", _("Track Locked")); + add_stock_icon_set(factory, "track-unlocked", "track_unlocked", _("Track Unlocked")); factory->add_default(); //Add factory to list of factories. } From 7dcfa84d6a5b89c292f36ae82946c94a1396590f Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Thu, 23 Oct 2008 00:38:47 +0100 Subject: [PATCH 16/59] Correct a liblumi to liblumiera --- src/gui/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 835e5f1a5..e6c3ed16d 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -78,7 +78,7 @@ lumigui_SOURCES = \ lumigui_LDFLAGS = lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumiproc.a liblumibackend.a \ - liblumicommon.a liblumi.a $(NOBUGMT_LUMIERA_LIBS) + liblumicommon.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) lumigui_DEPENDENCIES = \ $(top_builddir)/lumiera_ui.rc \ From 6e12b74d9ed40ccd7f0b0a7302afc16965aa71c2 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 23 Oct 2008 04:02:12 +0200 Subject: [PATCH 17/59] rename the proc-layer tests to comply with the numbering scheme --- tests/{50components.tests => 40components.tests} | 0 tests/{51asset.tests => 41asset.tests} | 0 tests/{52query.tests => 42query.tests} | 0 tests/{53session.tests => 43session.tests} | 0 tests/{54builder.tests => 44builder.tests} | 0 tests/{55controller.tests => 45controller.tests} | 0 tests/{56engine.tests => 46engine.tests} | 0 tests/{58proc-operate.tests => 48proc-operate.tests} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename tests/{50components.tests => 40components.tests} (100%) rename tests/{51asset.tests => 41asset.tests} (100%) rename tests/{52query.tests => 42query.tests} (100%) rename tests/{53session.tests => 43session.tests} (100%) rename tests/{54builder.tests => 44builder.tests} (100%) rename tests/{55controller.tests => 45controller.tests} (100%) rename tests/{56engine.tests => 46engine.tests} (100%) rename tests/{58proc-operate.tests => 48proc-operate.tests} (100%) diff --git a/tests/50components.tests b/tests/40components.tests similarity index 100% rename from tests/50components.tests rename to tests/40components.tests diff --git a/tests/51asset.tests b/tests/41asset.tests similarity index 100% rename from tests/51asset.tests rename to tests/41asset.tests diff --git a/tests/52query.tests b/tests/42query.tests similarity index 100% rename from tests/52query.tests rename to tests/42query.tests diff --git a/tests/53session.tests b/tests/43session.tests similarity index 100% rename from tests/53session.tests rename to tests/43session.tests diff --git a/tests/54builder.tests b/tests/44builder.tests similarity index 100% rename from tests/54builder.tests rename to tests/44builder.tests diff --git a/tests/55controller.tests b/tests/45controller.tests similarity index 100% rename from tests/55controller.tests rename to tests/45controller.tests diff --git a/tests/56engine.tests b/tests/46engine.tests similarity index 100% rename from tests/56engine.tests rename to tests/46engine.tests diff --git a/tests/58proc-operate.tests b/tests/48proc-operate.tests similarity index 100% rename from tests/58proc-operate.tests rename to tests/48proc-operate.tests From 850f49904e3fd640cd697c621ce87d264260a389 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 23 Oct 2008 04:53:50 +0200 Subject: [PATCH 18/59] SCons: options for controling testsuite execution --- SConstruct | 4 +++- tests/SConscript | 12 ++++++++++-- tests/test.sh | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/SConstruct b/SConstruct index 07b791cb0..567f6fadc 100644 --- a/SConstruct +++ b/SConstruct @@ -102,7 +102,7 @@ def appendVal(env,var,targetVar,val=None): def handleNoBugSwitches(env): """ set the build level for NoBug. Release builds imply no DEBUG - wheras ALPHA and BETA require DEBUG + whereas ALPHA and BETA require DEBUG """ level = env['BUILDLEVEL'] if level in ['ALPHA', 'BETA']: @@ -128,6 +128,8 @@ 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('VALGRIND', 'Run Testsuite under valgrind control', False) + ,('TESTSUITES', 'Run only Testsuites matching the given pattern', '') # ,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) diff --git a/tests/SConscript b/tests/SConscript index 9fa09ae9e..f115d152b 100644 --- a/tests/SConscript +++ b/tests/SConscript @@ -3,6 +3,7 @@ ## SConscript - SCons buildscript for the Testsuite (called by SConstruct) ## +import os from os import path from Buildhelper import srcSubtree from Buildhelper import scanSubtree @@ -92,9 +93,16 @@ artifacts['testsuite'] = ts = ( [ testExecutable(env, dir) for dir in moduledirs # # - the product of running the Testsuite is the ",testlog" # - it depends on all artifacts defined as "ts" above +# - if not set via options switch, the environment variable TESTSUITES +# is explicitly propagated to test.sh # testEnv = env.Clone() -testEnv.Append(ENV = {'VALGRINDFLAGS' : 'DISABLE'}) +if not env['VALGRIND']: + testEnv.Append(ENV = {'VALGRINDFLAGS' : 'DISABLE'}) +testsuites = env['TESTSUITES'] or os.environ.get('TESTSUITES') +if testsuites: + testEnv['ENV']['TESTSUITES'] = testsuites + testDir = env.Dir('#$BINDIR') runTest = env.File("test.sh").abspath @@ -110,5 +118,5 @@ runTs = testEnv.Command(',testlog', ts, runTest, chdir=testDir) env.Alias('testcode', ts ) env.Alias('check', runTs ) -# declare tempfiles of test.sh as cleanable +# allow tempfiles of test.sh to be cleaned env.Clean ('check', [',testlog.pre',',expect_stdout',',stdout',',stderr',',testtmp','.libs']) diff --git a/tests/test.sh b/tests/test.sh index e2d5159b7..31c92da5b 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -200,7 +200,8 @@ function RUNTESTS() echo "$t" done | sort | uniq | { while read i; do - echo $i >&2 + echo + echo "### $i" >&2 if test -f $i; then source $i fi From d7398d4f8f453530ba87fa9195d5511a9b9d79aa Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 26 Oct 2008 22:47:49 +0100 Subject: [PATCH 19/59] oops... should run testsuite with Valgrind by default --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 567f6fadc..19063b865 100644 --- a/SConstruct +++ b/SConstruct @@ -128,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('VALGRIND', 'Run Testsuite under valgrind control', False) + ,BoolOption('VALGRIND', 'Run Testsuite under valgrind control', True) ,('TESTSUITES', 'Run only Testsuites matching the given pattern', '') # ,BoolOption('OPENGL', 'Include support for OpenGL preview rendering', False) # ,EnumOption('DIST_TARGET', 'Build target architecture', 'auto', From e61c25a34af4f101f3e844759b767a08cfae8ab0 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sat, 25 Oct 2008 06:38:56 +0200 Subject: [PATCH 20/59] define an 'LUIDGEN' macro as uuid containing only zeros This *must* be replaced by a real luid with a upcoming luidgen tool ASAP, luids starting with zeros are invalid. For the time until this luidgen tool is not ready we just leave it this way. Later it will be changed to give a compile error. --- src/lib/luid.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/luid.h b/src/lib/luid.h index 553d22765..9d699cfcb 100644 --- a/src/lib/luid.h +++ b/src/lib/luid.h @@ -48,6 +48,11 @@ typedef lumiera_uid* LumieraUid; #define LUMIERA_UID_INITIALIZER(l) l #endif +/** + * LUIDGEN will be replaced by the 'luidgen' tool with a random uuid + */ +#define LUIDGEN "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + /** * Retrieve a generic pointer stored in a luid */ From 99e3e79fe6d940fd4b7029a1a6b7bc96c9a8d9b7 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sat, 25 Oct 2008 06:41:38 +0200 Subject: [PATCH 21/59] Complete the interface descriptor declaration After a discussion with ichthyo and some further thinking this should be mostly finished now. Nevertheless it is still experimental until we gain experience with it. --- src/backend/interfacedescriptor.h | 40 ++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/backend/interfacedescriptor.h b/src/backend/interfacedescriptor.h index 468bd2e80..513a783a7 100644 --- a/src/backend/interfacedescriptor.h +++ b/src/backend/interfacedescriptor.h @@ -23,17 +23,51 @@ #include "backend/interface.h" + /** - * WIP: interface descriptor, needs some generic metadata interface + * Release state of an interface implementation. + * The interfase subsystem must be able to categorize implementation to present possible + * upgrade paths to the user. This is done by the tagging it to a certain state in concert + * with the version and the user supplied version compare function. The respective numbers + * are choosen in a way that a higher value indicates precedence when selecting an implementation. + * Note that 'BETA' is higher than 'DEPRECATED' (we make the assumption that BETA is at least + * maintained code and something gets deprecated for some reason), for common practice it is still + * suggested to make a stable release before declaring its predcessor version as deprecated. + */ +enum lumiera_interface_state { + /** some known bugs exist which won't be fixed, don't use this */ + LUMIERA_INTERFACE_BROKEN = -1, + /** Not finished development code */ + LUMIERA_INTERFACE_EXPERIMENTAL = 0, + /** Old implementation which is now unmaintained and will be removed soon */ + LUMIERA_INTERFACE_DEPRECATED = 1, + /** Finished but not finally released implementation for open testing */ + LUMIERA_INTERFACE_BETA = 2, + /** Finished, released and maintained implementation */ + LUMIERA_INTERFACE_STABLE = 3 +}; + + +/** + * Interface descriptor. + * This defines an interface for querying metadata common to all interface implementations */ LUMIERA_INTERFACE_DECLARE (lumieraorg_interfacedescriptor, 0, /* The following slots are some human-readable descriptions of certain properties */ LUMIERA_INTERFACE_SLOT (const char*, name, (LumieraInterface)), + LUMIERA_INTERFACE_SLOT (const char*, brief, (LumieraInterface)), + LUMIERA_INTERFACE_SLOT (const char*, homepage, (LumieraInterface)), LUMIERA_INTERFACE_SLOT (const char*, version, (LumieraInterface)), LUMIERA_INTERFACE_SLOT (const char*, author, (LumieraInterface)), + LUMIERA_INTERFACE_SLOT (const char*, email, (LumieraInterface)), LUMIERA_INTERFACE_SLOT (const char*, copyright, (LumieraInterface)), - LUMIERA_INTERFACE_SLOT (const char*, license, (LumieraInterface)) - /* TODO add more things here, dependencies, provisions etc */ + LUMIERA_INTERFACE_SLOT (const char*, license, (LumieraInterface)), + + /* some flags for properties */ + LUMIERA_INTERFACE_SLOT (int, state, (LumieraInterface)), + + /* compare 2 version strings in a custom way */ + LUMIERA_INTERFACE_SLOT (int, versioncmp, (const char*, const char*)) ); From 41ec9edd6f3ebb1781d30d711a8a4f687b35f657 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sat, 25 Oct 2008 06:42:30 +0200 Subject: [PATCH 22/59] fix tests to adhere with the new interface descriptor --- tests/backend/test-interfaces.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/backend/test-interfaces.c b/tests/backend/test-interfaces.c index 09fa25afa..b27bf7227 100644 --- a/tests/backend/test-interfaces.c +++ b/tests/backend/test-interfaces.c @@ -79,16 +79,28 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, testacquire, testrelease, LUMIERA_INTERFACE_INLINE (name, "\073\003\054\127\344\046\324\321\221\262\232\026\376\123\125\243", + const char*, (LumieraInterface iface), + {return "LumieraTest";} + ), + LUMIERA_INTERFACE_INLINE (brief, LUIDGEN, const char*, (LumieraInterface iface), {return "Lumiera Test suite examples";} ), + LUMIERA_INTERFACE_INLINE (homepage, LUIDGEN, + const char*, (LumieraInterface iface), + {return "http://www.lumiera.org/develompent.html";} + ), LUMIERA_INTERFACE_INLINE (version, "\271\330\345\066\304\217\211\065\157\120\031\365\304\363\364\074", const char*, (LumieraInterface iface), {return "No Version";} ), LUMIERA_INTERFACE_INLINE (author, "\367\160\342\065\147\007\237\371\141\335\371\131\025\030\257\232", const char*, (LumieraInterface iface), - {return "Christian Thaeter ";} + {return "Christian Thaeter";} + ), + LUMIERA_INTERFACE_INLINE (email, LUIDGEN, + const char*, (LumieraInterface iface), + {return "ct@pipapo.org";} ), LUMIERA_INTERFACE_INLINE (copyright, "\163\106\344\014\251\125\111\252\236\322\174\120\335\225\333\245", const char*, (LumieraInterface iface), @@ -116,6 +128,16 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, "along with this program; if not, write to the Free Software\n" "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"; } + ), + + LUMIERA_INTERFACE_INLINE (state, LUIDGEN, + int, (LumieraInterface iface), + {return LUMIERA_INTERFACE_EXPERIMENTAL;} + ), + + LUMIERA_INTERFACE_INLINE (versioncmp, LUIDGEN, + int, (const char* a, const char* b), + {return 0;} ) ); From 1886f41bf57f14a164ce5e5da05152b77e4c75cb Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sat, 25 Oct 2008 07:00:21 +0200 Subject: [PATCH 23/59] WIP: testsuite for interfaces --- tests/30interfaces.tests | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/30interfaces.tests diff --git a/tests/30interfaces.tests b/tests/30interfaces.tests new file mode 100644 index 000000000..efc9f1148 --- /dev/null +++ b/tests/30interfaces.tests @@ -0,0 +1,38 @@ +TESTING "test interfaces" ./test-interfaces + +TEST "Basic operations" basic < Date: Sun, 26 Oct 2008 03:11:02 +0100 Subject: [PATCH 24/59] Complete the luidgen tool calling 'luidgen' with a list of filenames replaces the word LUIDGEN in each of this files with a octal escaped string consisting a unique identifier add luid formatter help macros to luid.h let compilation of files which contain the word 'LUIDGEN' fail with a hopefully self-explaining error message --- src/lib/luid.h | 18 +++++++++- src/tool/Makefile.am | 2 +- src/tool/luidgen.c | 83 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 96 insertions(+), 7 deletions(-) diff --git a/src/lib/luid.h b/src/lib/luid.h index 9d699cfcb..0986e5580 100644 --- a/src/lib/luid.h +++ b/src/lib/luid.h @@ -48,10 +48,26 @@ typedef lumiera_uid* LumieraUid; #define LUMIERA_UID_INITIALIZER(l) l #endif +#define LUMIERA_UID_FMT \ + "\\%.3hho\\%.3hho\\%.3hho\\%.3hho" \ + "\\%.3hho\\%.3hho\\%.3hho\\%.3hho" \ + "\\%.3hho\\%.3hho\\%.3hho\\%.3hho" \ + "\\%.3hho\\%.3hho\\%.3hho\\%.3hho" + +#define LUMIERA_UID_CHAR(l,n) ((unsigned char*)l)[n] + + +#define LUMIERA_UID_ELEMENTS(l) \ + LUMIERA_UID_CHAR(l,0), LUMIERA_UID_CHAR(l,1), LUMIERA_UID_CHAR(l,2), LUMIERA_UID_CHAR(l,3), \ + LUMIERA_UID_CHAR(l,4), LUMIERA_UID_CHAR(l,5), LUMIERA_UID_CHAR(l,6), LUMIERA_UID_CHAR(l,7), \ + LUMIERA_UID_CHAR(l,8), LUMIERA_UID_CHAR(l,9), LUMIERA_UID_CHAR(l,10), LUMIERA_UID_CHAR(l,11), \ + LUMIERA_UID_CHAR(l,12), LUMIERA_UID_CHAR(l,13), LUMIERA_UID_CHAR(l,14), LUMIERA_UID_CHAR(l,15) + /** * LUIDGEN will be replaced by the 'luidgen' tool with a random uuid */ -#define LUIDGEN "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" +#define LUIDGEN PLEASE_RUN_THE_LUIDGEN_TOOL_ON_THIS_FILE + /** * Retrieve a generic pointer stored in a luid diff --git a/src/tool/Makefile.am b/src/tool/Makefile.am index 8a4234c05..a48bf0cea 100644 --- a/src/tool/Makefile.am +++ b/src/tool/Makefile.am @@ -24,4 +24,4 @@ luidgen_CPPFLAGS = -I$(top_srcdir)/src/ luidgen_SOURCES = \ $(lumitool_srcdir)/luidgen.c -luidgen_LDADD = liblumiera.a +luidgen_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) diff --git a/src/tool/luidgen.c b/src/tool/luidgen.c index 41081ca97..730395b6c 100644 --- a/src/tool/luidgen.c +++ b/src/tool/luidgen.c @@ -19,25 +19,98 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "lib/safeclib.h" #include "lib/luid.h" +#include +#include +#include #include +#include +#include /** * @file * Generate amd print a Lumiera uid as octal escaped string + * or process a file replaceing 'LUIDGEN' with a octal escaped string */ + int main (int argc, char** argv) { + NOBUG_INIT; lumiera_uid luid; - lumiera_uid_gen (&luid); - printf ("\""); - for (int i = 0; i < 16; ++i) - printf ("\\%.3hho", *(((char*)&luid)+i)); - printf ("\"\n"); + if (argc == 1) + { + lumiera_uid_gen (&luid); + printf ("\""); + for (int i = 0; i < 16; ++i) + printf ("\\%.3hho", *(((char*)&luid)+i)); + printf ("\"\n"); + } + else + { + for (int i = 1; i < argc; ++i) + { + FILE* in = fopen (argv[i], "r"); + if (!in) + { + fprintf (stderr, "Failed to open file %s for reading: %s\n", argv[i], strerror (errno)); + continue; + } + + char* outname = lumiera_tmpbuf_snprintf (SIZE_MAX, "%s.luidgen", argv[i]); + FILE* out = fopen (outname, "wx"); + if (!out) + { + fprintf (stderr, "Failed to open file %s for writing: %s\n", outname, strerror (errno)); + fclose (in); + continue; + } + + char buf[4096]; + char luidbuf[67]; + + printf ("Luidgen %s ", argv[i]); fflush (stdout); + + while (fgets (buf, 4096, in)) + { + char* pos; + while ((pos = strstr(buf, "LUIDGEN"))) + { + memmove (pos+66, pos+7, strlen (pos+7)+1); + lumiera_uid_gen (&luid); + sprintf (luidbuf, "\""LUMIERA_UID_FMT"\"", LUMIERA_UID_ELEMENTS(luid)); + memcpy (pos, luidbuf, 66); + putchar ('.'); fflush (stdout); + } + fputs (buf, out); + } + + fclose (out); + fclose (in); + + char* backup = lumiera_tmpbuf_snprintf (SIZE_MAX, "%s~", argv[i]); + unlink (backup); + + if (!!rename (argv[i], backup)) + { + fprintf (stderr, "Failed to create backupfile %s: %s\n", backup, strerror (errno)); + continue; + } + + if (!!rename (outname, argv[i])) + { + fprintf (stderr, "Renaming %s to %s failed: %s\n", outname, argv[i], strerror (errno)); + rename (backup, argv[i]); + continue; + } + + printf (" done\n"); + } + } return 0; } From 33c8e79ccb259d09ddb1bcf6364b471e7e6ad968 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 26 Oct 2008 03:08:23 +0100 Subject: [PATCH 25/59] ran luidgen on test-interfaces.c --- tests/backend/test-interfaces.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/backend/test-interfaces.c b/tests/backend/test-interfaces.c index b27bf7227..8d7c377e8 100644 --- a/tests/backend/test-interfaces.c +++ b/tests/backend/test-interfaces.c @@ -82,11 +82,11 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, const char*, (LumieraInterface iface), {return "LumieraTest";} ), - LUMIERA_INTERFACE_INLINE (brief, LUIDGEN, + LUMIERA_INTERFACE_INLINE (brief, "\241\337\035\172\323\377\355\036\171\326\323\163\177\242\364\172", const char*, (LumieraInterface iface), {return "Lumiera Test suite examples";} ), - LUMIERA_INTERFACE_INLINE (homepage, LUIDGEN, + LUMIERA_INTERFACE_INLINE (homepage, "\030\374\031\152\024\167\154\346\303\372\177\353\304\306\275\247", const char*, (LumieraInterface iface), {return "http://www.lumiera.org/develompent.html";} ), @@ -98,7 +98,7 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, const char*, (LumieraInterface iface), {return "Christian Thaeter";} ), - LUMIERA_INTERFACE_INLINE (email, LUIDGEN, + LUMIERA_INTERFACE_INLINE (email, "\334\272\125\312\140\347\121\020\155\047\226\352\244\141\107\363", const char*, (LumieraInterface iface), {return "ct@pipapo.org";} ), @@ -130,12 +130,12 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, } ), - LUMIERA_INTERFACE_INLINE (state, LUIDGEN, + LUMIERA_INTERFACE_INLINE (state, "\364\002\115\170\361\321\301\244\350\322\270\362\010\231\207\334", int, (LumieraInterface iface), {return LUMIERA_INTERFACE_EXPERIMENTAL;} ), - LUMIERA_INTERFACE_INLINE (versioncmp, LUIDGEN, + LUMIERA_INTERFACE_INLINE (versioncmp, "\136\037\234\304\100\247\244\342\324\353\072\060\161\053\077\263", int, (const char* a, const char* b), {return 0;} ) From 84df01893153999b7bfa865429eda0300283e39f Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 26 Oct 2008 05:04:44 +0100 Subject: [PATCH 26/59] some cosmetics and a copy'n'paste interfacedescriptor example --- src/backend/interfacedescriptor.h | 65 +++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/src/backend/interfacedescriptor.h b/src/backend/interfacedescriptor.h index 513a783a7..29894c686 100644 --- a/src/backend/interfacedescriptor.h +++ b/src/backend/interfacedescriptor.h @@ -26,12 +26,12 @@ /** * Release state of an interface implementation. - * The interfase subsystem must be able to categorize implementation to present possible + * The interface subsystem must be able to categorize implementations to present possible * upgrade paths to the user. This is done by the tagging it to a certain state in concert * with the version and the user supplied version compare function. The respective numbers * are choosen in a way that a higher value indicates precedence when selecting an implementation. - * Note that 'BETA' is higher than 'DEPRECATED' (we make the assumption that BETA is at least - * maintained code and something gets deprecated for some reason), for common practice it is still + * Note that 'BETA' is higher than 'DEPRECATED', we make the assumption that BETA is at least + * maintained code and something gets deprecated for some reason. For common practice it is * suggested to make a stable release before declaring its predcessor version as deprecated. */ enum lumiera_interface_state { @@ -71,6 +71,65 @@ LUMIERA_INTERFACE_DECLARE (lumieraorg_interfacedescriptor, 0, ); +#if 0 +/** + * For convinience, a copy'n'paste descriptor + */ +LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, + /*IDENTIFIER*/, + NULL, NULL, NULL, + LUMIERA_INTERFACE_INLINE (name, LUIDGEN, + const char*, (LumieraInterface iface), + {return /*NAME*/;} + ), + LUMIERA_INTERFACE_INLINE (brief, LUIDGEN, + const char*, (LumieraInterface iface), + {return /*BRIEF*/;} + ), + LUMIERA_INTERFACE_INLINE (homepage, LUIDGEN, + const char*, (LumieraInterface iface), + {return /*HOMEPAGE*/;} + ), + LUMIERA_INTERFACE_INLINE (version, LUIDGEN, + const char*, (LumieraInterface iface), + {return /*VERSION*/;} + ), + LUMIERA_INTERFACE_INLINE (author, LUIDGEN, + const char*, (LumieraInterface iface), + {return /*AUTHOR*/;} + ), + LUMIERA_INTERFACE_INLINE (email, LUIDGEN, + const char*, (LumieraInterface iface), + {return /*EMAIL*/;} + ), + LUMIERA_INTERFACE_INLINE (copyright, LUIDGEN, + const char*, (LumieraInterface iface), + { + return + "Copyright (C) "/*ORGANIZATION*/"\n" + " "/*YEARS*/" "/*AUTHOR*/" <"/*EMAIL*/">"; + } + ), + LUMIERA_INTERFACE_INLINE (license, LUIDGEN, + const char*, (LumieraInterface iface), + { + return + /*LICENSE*/; + } + ), + + LUMIERA_INTERFACE_INLINE (state, LUIDGEN, + int, (LumieraInterface iface), + {return /*LUMIERA_INTERFACE_EXPERIMENTAL*/;} + ), + + LUMIERA_INTERFACE_INLINE (versioncmp, LUIDGEN, + int, (const char* a, const char* b), + {return /*COMPARERESULT*/;} + ) + ); +#endif + #endif /* LUMIERA_INTERFACEDESCRIPTORS_H */ /* From ab3d3823f6941da7ea522cc9014e25e4ab248550 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 26 Oct 2008 05:38:06 +0100 Subject: [PATCH 27/59] autotools fixes for the plugin system don't link the tests with -ldl Renamed GTK_LUMIERA_* to LUMIERA_GUI_* and include all gui relevant config results here. Set it explicit, don't add the results to CFLAGS or LIBS, the default behaviour linked all LIBS in, even in plugins, that was not intended. --- admin/Makefile.am | 2 +- configure.ac | 29 +++++++++++++---------------- src/gui/Makefile.am | 9 +++++---- tests/Makefile.am | 20 ++++++++++---------- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/admin/Makefile.am b/admin/Makefile.am index da1c244a7..9160c34ee 100644 --- a/admin/Makefile.am +++ b/admin/Makefile.am @@ -24,5 +24,5 @@ vgsuppression_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl noinst_PROGRAMS += rsvg-convert rsvg_convert_SOURCES = $(admin_srcdir)/rsvg-convert.c -rsvg_convert_CPPFLAGS = $(AM_CPPFLAGS) $(GTK_LUMIERA_CFLAGS) -std=gnu99 -Wall -Werror +rsvg_convert_CPPFLAGS = $(AM_CPPFLAGS) $(LUMIERA_GUI_CFLAGS) -std=gnu99 -Wall -Werror rsvg_convert_LDADD = -lcairo -lglib-2.0 -lgthread-2.0 -lrsvg-2 diff --git a/configure.ac b/configure.ac index 4df50f245..6aafc1a2c 100644 --- a/configure.ac +++ b/configure.ac @@ -124,15 +124,19 @@ AC_LANG_POP([C++]) # END Internatinalization +############## Gtk Dependancies +PKG_CHECK_MODULES(LUMIERA_GUI, [ + 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]) + +# END Gtk Dependancies ############## X11 Dependancies AC_PATH_X AC_PATH_XTRA -# CFLAGS="$CFLAGS $X_CFLAGS" -LIBS="$LIBS $X_PRE_LIBS $X_LIBS $X_EXTRA_LIBS" AC_CHECK_HEADERS([X11/Xlib.h X11/Xutil.h],[], - [AC_MSG_ERROR([Xlib.h or Xutil.h not found install xdevel])]) + [AC_MSG_ERROR([Xlib.h or Xutil.h not found install xdevel])]) AC_CHECK_HEADERS([sys/ipc.h sys/shm.h],, [AC_MSG_ERROR([Required header not found. Please check that it is installed])] @@ -142,25 +146,18 @@ AC_CHECK_HEADERS([X11/extensions/Xvlib.h X11/extensions/XShm.h],, [#include ] ) -AC_CHECK_LIB(Xext, XInitExtension, , - [AC_MSG_ERROR([Could not link with libXext. Check that you have libXext installed])], -lX11 +AC_CHECK_LIB(Xext, XInitExtension, [LUMIERA_GUI_LIBS="$LUMIERA_GUI_LIBS -lXext"], + [AC_MSG_ERROR([Could not link with libXext. Check that you have libXext installed])], -lX11 ) -AC_CHECK_LIB(Xv, XvQueryAdaptors, , - [AC_MSG_ERROR([Could not link with libXv. Check that you have libXv installed])] +AC_CHECK_LIB(Xv, XvQueryAdaptors, [LUMIERA_GUI_LIBS="$LUMIERA_GUI_LIBS -lXv"], + [AC_MSG_ERROR([Could not link with libXv. Check that you have libXv installed])] ) # END X11 Dependancies -############## Gtk 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 librsvg-2.0 >= 2.18.1]) - -AC_SUBST(GTK_LUMIERA_CFLAGS) -AC_SUBST(GTK_LUMIERA_LIBS) - -# END Gtk Dependancies +AC_SUBST(LUMIERA_GUI_CFLAGS) +AC_SUBST(LUMIERA_GUI_LIBS) ############## Nobug Dependancies diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 316887403..928f42a9b 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -24,7 +24,7 @@ lumigui_CPPFLAGS = $(AM_CPPFLAGS) \ -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ - $(GTK_LUMIERA_CFLAGS) + $(LUMIERA_GUI_CFLAGS) bin_PROGRAMS += lumigui @@ -76,14 +76,15 @@ lumigui_SOURCES = \ $(lumigui_srcdir)/output/xvdisplayer.cpp \ $(lumigui_srcdir)/output/xvdisplayer.hpp -lumigui_LDFLAGS = -lumigui_LDADD = $(GTK_LUMIERA_LIBS) liblumicommon.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) +lumigui_LDFLAGS = +# $(LIBS) $(X_PRE_LIBS) $(X_LIBS) $(X_EXTRA_LIBS) +lumigui_LDADD = $(LUMIERA_GUI_LIBS) liblumicommon.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) lumigui_DEPENDENCIES = \ $(top_builddir)/lumiera_ui.rc \ $(top_builddir)/liblumicommon.a \ $(top_builddir)/liblumiera.a - + $(top_builddir)/lumiera_ui.rc: cp $(lumigui_srcdir)/lumiera_ui.rc $(top_builddir) diff --git a/tests/Makefile.am b/tests/Makefile.am index 10cdeed10..5554c0dc3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,51 +21,51 @@ tests_srcdir = $(top_srcdir)/tests check_PROGRAMS += test-error test_error_SOURCES = $(tests_srcdir)/error/errortest.c test_error_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_error_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl +test_error_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) check_PROGRAMS += test-locking test_locking_SOURCES = $(tests_srcdir)/library/test-locking.c test_locking_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_locking_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_locking_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm check_PROGRAMS += test-llist test_llist_SOURCES = $(tests_srcdir)/library/test-llist.c test_llist_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_llist_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_llist_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm check_PROGRAMS += test-psplay test_psplay_SOURCES = $(tests_srcdir)/library/test-psplay.c test_psplay_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ -test_psplay_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_psplay_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm check_PROGRAMS += test-safeclib test_safeclib_SOURCES = $(tests_srcdir)/library/test-safeclib.c test_safeclib_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_safeclib_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_safeclib_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm check_PROGRAMS += test-luid test_luid_SOURCES = $(tests_srcdir)/library/test-luid.c test_luid_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_luid_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_luid_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm check_PROGRAMS += test-interfaces test_interfaces_SOURCES = $(tests_srcdir)/backend/test-interfaces.c test_interfaces_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_interfaces_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_interfaces_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm check_PROGRAMS += test-filedescriptors test_filedescriptors_SOURCES = $(tests_srcdir)/backend/test-filedescriptors.c test_filedescriptors_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_filedescriptors_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_filedescriptors_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm check_PROGRAMS += test-filehandles test_filehandles_SOURCES = $(tests_srcdir)/backend/test-filehandles.c test_filehandles_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_filehandles_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_filehandles_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm check_PROGRAMS += test-config test_config_SOURCES = $(tests_srcdir)/backend/test-config.c test_config_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ -test_config_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm +test_config_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm TESTS = $(tests_srcdir)/test.sh From a4c028bd34eb84d57c01d2c2372167f4b75baf38 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 26 Oct 2008 22:00:02 +0100 Subject: [PATCH 28/59] Prepare autotools for plugins --- Makefile.am | 4 +++- configure.ac | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index d236fbfd8..068388274 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,11 +19,13 @@ ACLOCAL_AMFLAGS = -I m4 bin_PROGRAMS = -lib_LTLIBRARIES = noinst_PROGRAMS = check_PROGRAMS = noinst_LIBRARIES = +lib_LTLIBRARIES = check_LTLIBRARIES = +pkglib_LTLIBRARIES = +noinst_LTLIBRARIES = noinst_HEADERS = BUILT_SOURCES = EXTRA_DIST = diff --git a/configure.ac b/configure.ac index 6aafc1a2c..ae9f0d79b 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,11 @@ AC_COPYRIGHT([ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ]) +# +# Global configuration +# AC_GNU_SOURCE +AC_DISABLE_STATIC # # Required programs From b242f3359be50fa3aa94c38dcb5a194b0d63e873 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 26 Oct 2008 22:03:10 +0100 Subject: [PATCH 29/59] Fix/Wip: LUMIERA_PLUGIN definition There where some bugs slipped in (not yet tested code) removed the descriptor from the plugin itself, lets see if we can remove the acquire and release functions later too. Declare the plugin interface itself in its first experimental state --- src/backend/interface.h | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/backend/interface.h b/src/backend/interface.h index ef13e40e1..7b97fd82e 100644 --- a/src/backend/interface.h +++ b/src/backend/interface.h @@ -291,17 +291,15 @@ queryfunc (void) \ * lumiera uuid generator tool (to be written) over the source file to generate luid's automatically * @param ... list of LUMIERA_INTERFACE_DEFINE() for all interfaces this plugin provides. */ -#define LUMIERA_PLUGIN(descriptor, acquire, release, luid, ...) \ +#define LUMIERA_PLUGIN(acquire, release, luid, ...) \ LUMIERA_EXPORT(plugin_interfaces, __VA_ARGS__) \ -LUMIERA_INTERFACE_DEFINE (lumieraorg_plugin, 0, \ - lumieraorg_plugin_0, \ - NULL, \ - NULL, \ - NULL, \ - LUMIERA_INTERFACE_MAP (plugin_interfaces, plugin_interfaces, luid) \ - ) - - +LUMIERA_INTERFACE_INSTANCE (lumieraorg_plugin, 0, \ + lumieraorg_plugin, \ + NULL, \ + acquire, \ + release, \ + LUMIERA_INTERFACE_MAP (plugin_interfaces, luid, plugin_interfaces) \ + ); /** * create a handle for a interface (WIP) @@ -372,6 +370,15 @@ struct lumiera_interface_struct #endif }; + +/** + * Plugin interface + */ +LUMIERA_INTERFACE_DECLARE (lumieraorg_plugin, 0, + LUMIERA_INTERFACE_SLOT (LumieraInterface*, plugin_interfaces, (void)), +); + + /* API to handle interfaces */ From 0dc8a68afba80c740acd075508c00640bdb9029c Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 26 Oct 2008 22:04:58 +0100 Subject: [PATCH 30/59] Reinstantiated the first test plugin --- tests/Makefile.am | 16 ++++-- tests/backend/example_plugin.c | 97 ++++++++++++++++++++++++++++++--- tests/backend/hello_interface.h | 10 ++-- 3 files changed, 106 insertions(+), 17 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 5554c0dc3..66367ffb4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -48,11 +48,6 @@ test_luid_SOURCES = $(tests_srcdir)/library/test-luid.c test_luid_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror test_luid_LDADD = liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm -check_PROGRAMS += test-interfaces -test_interfaces_SOURCES = $(tests_srcdir)/backend/test-interfaces.c -test_interfaces_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -test_interfaces_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm - check_PROGRAMS += test-filedescriptors test_filedescriptors_SOURCES = $(tests_srcdir)/backend/test-filedescriptors.c test_filedescriptors_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror @@ -68,4 +63,15 @@ test_config_SOURCES = $(tests_srcdir)/backend/test-config.c test_config_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ test_config_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm +check_LTLIBRARIES += examplepluginc.la +examplepluginc_la_SOURCES = $(tests_srcdir)/backend/example_plugin.c +examplepluginc_la_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ +examplepluginc_la_LDFLAGS = -module -avoid-version -no-undefined -rpath /dev/null + +check_PROGRAMS += test-interfaces +test_interfaces_SOURCES = $(tests_srcdir)/backend/test-interfaces.c +test_interfaces_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror +test_interfaces_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm +test_interfaces_DEPENDENCIES = examplepluginc.la + TESTS = $(tests_srcdir)/test.sh diff --git a/tests/backend/example_plugin.c b/tests/backend/example_plugin.c index 7540aa35d..346585190 100644 --- a/tests/backend/example_plugin.c +++ b/tests/backend/example_plugin.c @@ -1,6 +1,7 @@ #include #include "hello_interface.h" +#include "backend/interfacedescriptor.h" int myopen(void) { @@ -34,12 +35,94 @@ void bye(const char* m) printf("Bye %s\n", m); } -LUMIERA_INTERFACE_IMPLEMENT(hello, 1, german, myopen, myclose, - hallo, - tschuess + +LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, + lumieraorg_exampleplugin_descriptor, + NULL, NULL, NULL, + LUMIERA_INTERFACE_INLINE (name, "\003\307\005\305\201\304\175\377\120\105\332\016\136\354\251\022", + const char*, (LumieraInterface iface), + {return "LumieraTest";} + ), + LUMIERA_INTERFACE_INLINE (brief, "\303\047\265\010\242\210\365\340\024\030\350\310\067\171\170\260", + const char*, (LumieraInterface iface), + {return "Lumiera Test suite examples";} + ), + LUMIERA_INTERFACE_INLINE (homepage, "\363\125\352\312\056\255\274\322\351\245\051\350\120\024\115\263", + const char*, (LumieraInterface iface), + {return "http://www.lumiera.org/develompent.html";} + ), + LUMIERA_INTERFACE_INLINE (version, "\114\043\133\175\354\011\232\002\117\240\107\141\234\157\217\176", + const char*, (LumieraInterface iface), + {return "No Version";} + ), + LUMIERA_INTERFACE_INLINE (author, "\313\300\055\156\126\320\144\247\140\023\261\002\270\367\017\267", + const char*, (LumieraInterface iface), + {return "Christian Thaeter";} + ), + LUMIERA_INTERFACE_INLINE (email, "\163\051\312\276\137\317\267\305\237\274\133\012\276\006\255\160", + const char*, (LumieraInterface iface), + {return "ct@pipapo.org";} + ), + LUMIERA_INTERFACE_INLINE (copyright, "\160\246\161\204\123\262\375\351\157\276\333\073\355\036\062\341", + const char*, (LumieraInterface iface), + { + return + "Copyright (C) Lumiera.org\n" + " 2008 Christian Thaeter "; + } + ), + LUMIERA_INTERFACE_INLINE (license, "\007\311\044\214\064\223\201\326\331\111\233\356\055\264\211\201", + const char*, (LumieraInterface iface), + { + return + "This program is free software; you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation; either version 2 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with this program; if not, write to the Free Software\n" + "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"; + } + ), + + LUMIERA_INTERFACE_INLINE (state, "\331\353\126\162\067\376\340\242\232\175\167\105\122\177\306\354", + int, (LumieraInterface iface), + {return LUMIERA_INTERFACE_EXPERIMENTAL;} + ), + + LUMIERA_INTERFACE_INLINE (versioncmp, "\363\145\363\224\325\104\177\057\344\023\367\111\376\221\152\135", + int, (const char* a, const char* b), + {return 0;} + ) ); -LUMIERA_INTERFACE_IMPLEMENT(hello, 1, english, myopen, myclose, - hello, - bye - ); + +LUMIERA_PLUGIN (NULL, NULL, + "\046\150\040\062\077\110\134\143\236\244\346\365\072\377\371\263", + LUMIERA_INTERFACE_DEFINE (lumieraorg_testhello, 0, + lumieraorg_hello_german, + LUMIERA_INTERFACE_REF (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor), + NULL, + NULL, + LUMIERA_INTERFACE_MAP (hello, "\167\012\306\023\031\151\006\362\026\003\125\017\170\022\100\333", + hallo), + LUMIERA_INTERFACE_MAP (goodbye, "\324\267\214\166\340\213\155\053\157\125\064\264\167\235\020\223", + tschuess) + ), + LUMIERA_INTERFACE_DEFINE (lumieraorg_testhello, 0, + lumieraorg_hello_english, + LUMIERA_INTERFACE_REF (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor), + NULL, + NULL, + LUMIERA_INTERFACE_MAP (hello, "\326\247\370\247\032\103\223\357\262\007\356\042\051\330\073\116", + hello), + LUMIERA_INTERFACE_MAP (goodbye, "\365\141\371\047\101\230\050\106\071\231\022\235\325\112\354\241", + bye) + ) + ) diff --git a/tests/backend/hello_interface.h b/tests/backend/hello_interface.h index d5cf99ea5..097861c01 100644 --- a/tests/backend/hello_interface.h +++ b/tests/backend/hello_interface.h @@ -1,6 +1,6 @@ -#include "lib/plugin.h" +#include "backend/interface.h" -LUMIERA_INTERFACE(hello, 1, - LUMIERA_INTERFACE_PROTO(void, hello, (void)) - LUMIERA_INTERFACE_PROTO(void, goodbye, (const char*)) - ); +LUMIERA_INTERFACE_DECLARE (lumieraorg_testhello, 0, + LUMIERA_INTERFACE_SLOT (void, hello, (void)), + LUMIERA_INTERFACE_SLOT (void, goodbye, (const char*)), +); From 9f8f0c7c20bbf245738bd7fe4e02d7bfe2b184e6 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 28 Oct 2008 01:10:16 +0100 Subject: [PATCH 31/59] temp. fix to make it compile on Etch based system --- src/gui/widgets/timeline/track.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/timeline/track.cpp b/src/gui/widgets/timeline/track.cpp index bac443ced..6d619b231 100644 --- a/src/gui/widgets/timeline/track.cpp +++ b/src/gui/widgets/timeline/track.cpp @@ -36,7 +36,8 @@ Track::Track() : buttonBar.append(lockButton); buttonBar.set_toolbar_style(TOOLBAR_ICONS); - buttonBar.set_icon_size(ICON_SIZE_MENU); +// buttonBar.set_icon_size(ICON_SIZE_MENU); /////TODO: commented out because it makes compile fail on Etch based system + headerWidget.pack_start(titleBox, PACK_SHRINK); headerWidget.pack_start(buttonBar, PACK_SHRINK); From 91d10cb44b38811f174f308862a952e0842decd3 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 28 Oct 2008 01:54:45 +0100 Subject: [PATCH 32/59] aligned the Xlib checks to match autotools build --- SConstruct | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SConstruct b/SConstruct index 19063b865..c6b0e0e66 100644 --- a/SConstruct +++ b/SConstruct @@ -215,7 +215,6 @@ def configurePlatform(env): if not conf.CheckLibWithHeader('boost_regex-mt','boost/regex.hpp','C++'): problems.append('We need the boost regular expression lib (incl. binary lib for linking).') -# if not conf.CheckLibWithHeader('gavl', ['gavlconfig.h', 'gavl/gavl.h'], 'C'): if not conf.CheckPkgConfig('gavl', 1.0): problems.append('Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html].') @@ -232,13 +231,16 @@ def configurePlatform(env): problems.append('Unable to configure Cairo--, exiting.') if not conf.CheckPkgConfig('gdl-1.0', '0.6.1'): - problems.append('Unable to configure the GNOME DevTool Library, exiting.') + problems.append('Unable to configure the GNOME DevTool Library.') 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.CheckCHeader(['X11/Xutil.h', 'X11/Xlib.h'],'<>'): + problems.append('Xlib.h and Xutil.h required. Please install libx11-dev.') + + if not conf.CheckPkgConfig('xv') : problems.append('Need libXv...') + if not conf.CheckPkgConfig('xext'): problems.append('Need libXext.') # if not conf.CheckPkgConfig('sm'): Exit(1) # # obviously not needed? From a912159d700e8934b088feee9eef1ca88bfd065f Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 28 Oct 2008 01:55:45 +0100 Subject: [PATCH 33/59] re-enabled building of the testpluginc.so --- admin/SConscript | 2 +- tests/SConscript | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/admin/SConscript b/admin/SConscript index d0ad7b84e..2737bab7e 100644 --- a/admin/SConscript +++ b/admin/SConscript @@ -8,7 +8,7 @@ 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 +artifacts['tools'] += [ vgsuppr ## for suppressing false valgrind alarms + rsvg ## for rendering SVG icons (uses librsvg) ] diff --git a/tests/SConscript b/tests/SConscript index f115d152b..d28b70218 100644 --- a/tests/SConscript +++ b/tests/SConscript @@ -52,15 +52,12 @@ def treatPluginTestcase(env): prfx = path.join(tree,'example_plugin') oC = env.SharedObject(prfx, prfx+'.c') oCPP = env.SharedObject(prfx+'_cpp', prfx+'.cpp') - testplugin = ( env.SharedLibrary('#$BINDIR/.libs/example_plugin', oC, SHLIBPREFIX='') - + env.SharedLibrary('#$BINDIR/.libs/example_plugin_cpp', oCPP, SHLIBPREFIX='') + testplugin = ( env.SharedLibrary('#$BINDIR/.libs/examplepluginc', oC, SHLIBPREFIX='') + +# doesn't compile yet... +# + env.SharedLibrary('#$BINDIR/.libs/exampleplugincpp', oCPP, SHLIBPREFIX='') ) -# testExe = env.Program('#$BINDIR/test-plugin', ['plugin/plugin_main.c'] + core) -# env.Depends(testExe, testplugin) -# return testExe - - # 10/2008 example_plugin moved to backend directory. - # ...we should try to find some convention here + return testplugin #-- it depends (at the moment) on a specific isolated test-plugin, # which is not integrated in the "normal procedure" for building Plugins @@ -78,7 +75,7 @@ specials = ['plugin','library','backend'] artifacts['testsuite'] = ts = ( [ testExecutable(env, dir) for dir in moduledirs if not dir in specials] -# + treatPluginTestcase(env) + + treatPluginTestcase(env) + testCollection(env, 'library') + testCollection(env, 'backend') ) From 7be18d63446503d938108b87aff0fee5cfd6b5f1 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Fri, 31 Oct 2008 06:29:55 +0100 Subject: [PATCH 34/59] Adding explicit delimiters to the config wordlist feature This greatly simplifies the task where we want to handle colon separated paths within the config. --- src/backend/config.h | 12 ++++++--- src/backend/config_wordlist.c | 49 ++++++++++++++--------------------- 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/backend/config.h b/src/backend/config.h index 4e3acd9a9..445ed6e23 100644 --- a/src/backend/config.h +++ b/src/backend/config.h @@ -228,20 +228,22 @@ LUMIERA_CONFIG_TYPES * Get nth word of a wordlist. * @param key key under which this wordlist is stored * @param nth index of the word to get, starting with 0 + * @param delims a string literal listing all characters which are treated as delimiters * @return pointer to a tempbuf holding the nth word or NULL in case of error */ const char* -lumiera_config_wordlist_get_nth (const char* key, unsigned nth); +lumiera_config_wordlist_get_nth (const char* key, unsigned nth, const char* delims); /** * Find the index of a word in a wordlist. * @param key key under which this wordlist is stored * @param value word to find + * @param delims a string literal listing all characters which are treated as delimiters * @return index of the first occurence of the word or -1 in case of failure */ int -lumiera_config_wordlist_find (const char* key, const char* value); +lumiera_config_wordlist_find (const char* key, const char* value, const char* delims); /** @@ -254,20 +256,22 @@ lumiera_config_wordlist_find (const char* key, const char* value); * @param value word to be replaced * @param subst1 first replacement word * @param subst2 second replacement word + * @param delims a string literal listing all characters which are treated as delimiters * @return internal representation of the wordlist in a tmpbuf or NULL in case of an error */ const char* -lumiera_config_wordlist_replace (const char* key, const char* value, const char* subst1, const char* subst2); +lumiera_config_wordlist_replace (const char* key, const char* value, const char* subst1, const char* subst2, const char* delims); /** * Add a word to the end of a wordlist if it doesnt exist already * @param key key under which this wordlist is stored * @param value new word to add + * @param delims a string literal listing all characters which are treated as delimiters * @return internal representation of the wordlist in a tmpbuf or NULL in case of an error */ const char* -lumiera_config_wordlist_add (const char* key, const char* value); +lumiera_config_wordlist_add (const char* key, const char* value, const char* delims); // * {{{ lumiera_config_TYPE_set (const char* key, TYPE*value, const char* fmt) }}} // Highlevel interface for different types, fmt is a printf format specifier for the desired format, when NULL, defaults apply. diff --git a/src/backend/config_wordlist.c b/src/backend/config_wordlist.c index 6cd0389a7..47232f483 100644 --- a/src/backend/config_wordlist.c +++ b/src/backend/config_wordlist.c @@ -19,25 +19,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -//TODO: Support library includes// #include "lib/error.h" #include "lib/safeclib.h" -//TODO: Lumiera header includes// #include "backend/config.h" -//TODO: internal/static forward declarations// extern LumieraConfig lumiera_global_config; -//TODO: System includes// - /** * return nth word of a wordlist */ const char* -lumiera_config_wordlist_get_nth (const char* key, unsigned nth) +lumiera_config_wordlist_get_nth (const char* key, unsigned nth, const char* delims) { const char* value; size_t len; @@ -47,8 +42,8 @@ lumiera_config_wordlist_get_nth (const char* key, unsigned nth) for (;;) { - value += strspn (value, " \t,;"); - len = strcspn (value, " \t,;"); + value += strspn (value, delims); + len = strcspn (value, delims); if (!nth && *value) break; @@ -64,7 +59,7 @@ lumiera_config_wordlist_get_nth (const char* key, unsigned nth) int -lumiera_config_wordlist_find (const char* key, const char* value) +lumiera_config_wordlist_find (const char* key, const char* value, const char* delims) { const char* itr; size_t vlen = strlen (value); @@ -75,8 +70,8 @@ lumiera_config_wordlist_find (const char* key, const char* value) for (int idx = 0; *itr; itr += len, ++idx) { - itr += strspn (itr, " \t,;"); - len = strcspn (itr, " \t,;"); + itr += strspn (itr, delims); + len = strcspn (itr, delims); if (len == vlen && !strncmp (itr, value, vlen)) return idx; @@ -87,7 +82,7 @@ lumiera_config_wordlist_find (const char* key, const char* value) const char* -lumiera_config_wordlist_replace (const char* key, const char* value, const char* subst1, const char* subst2) +lumiera_config_wordlist_replace (const char* key, const char* value, const char* subst1, const char* subst2, const char* delims) { const char* wordlist; const char* str = NULL; @@ -106,28 +101,25 @@ lumiera_config_wordlist_replace (const char* key, const char* value, const char* for (const char* itr = start; *itr; itr += len) { const char* left_end = itr; - itr += strspn (itr, " \t,;"); - len = strcspn (itr, " \t,;"); + itr += strspn (itr, delims); + len = strcspn (itr, delims); if (len == vlen && !strncmp (itr, value, vlen)) { - TODO ("figure delimiter from original string out"); - const char* delim = " "; - /* step over the word */ itr += len; - itr += strspn (itr, " \t,;"); + itr += strspn (itr, delims); /* getting the delimiters right for the corner cases looks ugly, want to refactor it? just do it */ str = lumiera_tmpbuf_snprintf (SIZE_MAX, - "%.*s%.*s%s%s%s%s%s%s", + "%.*s%.*s%.1s%s%.1s%s%.1s%s", start - wordlist, wordlist, left_end - start, start, - (left_end - start && subst1 && *subst1) ? delim : "", + (left_end - start && subst1 && *subst1) ? delims : "", (subst1 && *subst1) ? subst1 : "", - ((left_end - start || (subst1 && *subst1)) && subst2 && *subst2) ? delim : "", + ((left_end - start || (subst1 && *subst1)) && subst2 && *subst2) ? delims : "", (subst2 && *subst2) ? subst2 : "", - ((left_end - start || (subst1 && *subst1) || (subst2 && *subst2)) && *itr) ? delim : "", + ((left_end - start || (subst1 && *subst1) || (subst2 && *subst2)) && *itr) ? delims : "", itr ); @@ -145,7 +137,7 @@ lumiera_config_wordlist_replace (const char* key, const char* value, const char* const char* -lumiera_config_wordlist_add (const char* key, const char* value) +lumiera_config_wordlist_add (const char* key, const char* value, const char* delims) { const char* wordlist = NULL; @@ -160,19 +152,16 @@ lumiera_config_wordlist_add (const char* key, const char* value) for (const char* itr = wordlist; *itr; itr += len) { - itr += strspn (itr, " \t,;"); - len = strcspn (itr, " \t,;"); + itr += strspn (itr, delims); + len = strcspn (itr, delims); if (len == vlen && !strncmp (itr, value, vlen)) goto end; } - TODO ("figure delimiter from original string out"); - const char* delim = " "; - - wordlist = lumiera_tmpbuf_snprintf (SIZE_MAX, "%s%s%s", + wordlist = lumiera_tmpbuf_snprintf (SIZE_MAX, "%s%.1s%s", wordlist, - wordlist[strspn (wordlist, " \t,;")]?delim:"", + wordlist[strspn (wordlist, delims)] ? delims : "", value); if (!lumiera_config_set (key, lumiera_tmpbuf_snprintf (SIZE_MAX, "=%s", wordlist))) From 48778cf3d7d35bd97fcf0ba89d1cca228948ea04 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Fri, 31 Oct 2008 06:42:53 +0100 Subject: [PATCH 35/59] WIP: new plugin.h header This ditches the old 'proof of concept' implementation, interfaces and plugins are internally separate now and publically only accessed over the 'interfaces' api. The interface registry now gets an additional 'plugin' member to backreference plugins from interfaces. --- src/backend/interfaceregistry.c | 13 ++-- src/backend/interfaceregistry.h | 9 ++- src/backend/plugin.h | 134 +++++++++----------------------- 3 files changed, 52 insertions(+), 104 deletions(-) diff --git a/src/backend/interfaceregistry.c b/src/backend/interfaceregistry.c index ffa979340..cc175dd0a 100644 --- a/src/backend/interfaceregistry.c +++ b/src/backend/interfaceregistry.c @@ -53,13 +53,15 @@ key_fn (const PSplaynode node); static LumieraInterfacenode -lumiera_interfacenode_new (LumieraInterface iface) +lumiera_interfacenode_new (LumieraInterface iface, LumieraPlugin plugin) { LumieraInterfacenode self = lumiera_malloc (sizeof (*self)); psplaynode_init (&self->node); self->interface = iface; self->refcnt = 0; + self->plugin = plugin; + FIXME ("plugin handling (refcnt, atime)"); self->lnk = NULL; self->deps_size = 0; self->deps = NULL; @@ -74,6 +76,7 @@ lumiera_interfacenode_delete (LumieraInterfacenode self) if (self) { REQUIRE (self->refcnt == 0); + FIXME ("plugin handling"); lumiera_free (self->deps); lumiera_free (self); } @@ -115,7 +118,7 @@ lumiera_interfaceregistry_destroy (void) void -lumiera_interfaceregistry_register_interface (LumieraInterface self) +lumiera_interfaceregistry_register_interface (LumieraInterface self, LumieraPlugin plugin) { TRACE (interfaceregistry); REQUIRE (self); @@ -123,13 +126,13 @@ lumiera_interfaceregistry_register_interface (LumieraInterface self) LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex) { TRACE (interfaceregistry, "interface %s, version %d, instance %s", self->interface, self->version, self->name); - psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (self)->node, 100); + psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (self, plugin)->node, 100); } } void -lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self) +lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self, LumieraPlugin plugin) { TRACE (interfaceregistry); REQUIRE (self); @@ -139,7 +142,7 @@ lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self) while (*self) { TRACE (interfaceregistry, "interface %s, version %d, instance %s", (*self)->interface, (*self)->version, (*self)->name); - psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (*self)->node, 100); + psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (*self, plugin)->node, 100); ++self; } } diff --git a/src/backend/interfaceregistry.h b/src/backend/interfaceregistry.h index 02481072d..54ede293a 100644 --- a/src/backend/interfaceregistry.h +++ b/src/backend/interfaceregistry.h @@ -25,6 +25,7 @@ #include "lib/psplay.h" #include "backend/interface.h" +#include "backend/plugin.h" #include @@ -62,6 +63,10 @@ struct lumiera_interfacenode_struct /** reference counters and link used for internal reference management */ unsigned refcnt; + + /** backreference to its plugin if it comes from a plugin, else NULL */ + LumieraPlugin plugin; + /** temporary used to stack interfaces when recursively opening/closing them */ LumieraInterfacenode lnk; /** allocated size of the following deps table */ @@ -84,10 +89,10 @@ lumiera_interfaceregistry_destroy (void); void -lumiera_interfaceregistry_register_interface (LumieraInterface self); +lumiera_interfaceregistry_register_interface (LumieraInterface self, LumieraPlugin plugin); void -lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self); +lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self, LumieraPlugin plugin); void lumiera_interfaceregistry_remove_interface (LumieraInterface self); diff --git a/src/backend/plugin.h b/src/backend/plugin.h index 7e17afc18..6696e395f 100644 --- a/src/backend/plugin.h +++ b/src/backend/plugin.h @@ -21,111 +21,68 @@ #ifndef LUMIERA_PLUGIN_H #define LUMIERA_PLUGIN_H -#ifdef __cplusplus -extern "C" { -#elif 0 -} /*eek, fixes emacs indenting for now*/ -#endif #include #include -#include "error.h" +#include "lib/error.h" /** * @file - * Plugin loader, header. + * Lumiera plugins defines 'interfaces' as shown in interface.h, the plugin system handles the loading + * of all kinds of plugins under the hood, invoked from the interface system. Anything defined here is + * called internally and should not be used by other parts of the application. */ -NOBUG_DECLARE_FLAG (lumiera_plugin); +LUMIERA_ERROR_DECLARE(PLUGIN_DLOPEN); + + +NOBUG_DECLARE_FLAG (plugin); /* tool macros*/ -#define LUMIERA_INTERFACE_TYPE(name, version) struct lumiera_interface_##name##_##version -#define LUMIERA_INTERFACE_CAST(name, version) (LUMIERA_INTERFACE_TYPE(name, version)*) - -/* Interface definition */ -#define LUMIERA_INTERFACE(name, version, ...) \ -LUMIERA_INTERFACE_TYPE(name, version) \ -{ \ - struct lumiera_interface interface_header_; \ - __VA_ARGS__ \ -} - -#define LUMIERA_INTERFACE_PROTO(ret, name, params) ret (*name) params; - -/* Interface instantiation */ -#define LUMIERA_INTERFACE_IMPLEMENT(iname, version, name, open, close, ...) \ -LUMIERA_INTERFACE_TYPE(iname, version) name##_##version = \ -{ \ - { \ - version, \ - sizeof(LUMIERA_INTERFACE_TYPE(iname, version)), \ - NULL, \ - 0, \ - open, \ - close \ - }, \ - __VA_ARGS__ \ -} +struct lumiera_plugin_struct; +typedef struct lumiera_plugin_struct lumiera_plugin; +typedef lumiera_plugin* LumieraPlugin; -/* internally used */ -struct lumiera_plugin; - -/** - * This is the header for any interface exported by plugins. - * Real interfaces append their functions at the end. There are few standard functions on each Interface - * Every function is required to be implemnted. - */ -struct lumiera_interface -{ - /// interface version number - unsigned version; - /// size of the full structure is used to determine the revision (adding a new function increments the size) - size_t size; - /// back reference to plugin - struct lumiera_plugin* plugin; - /// incremented for each user of this interface and decremented when closed - unsigned use_count; - - /// called for each open of this interface - int (*open)(void); - /// called for each close of this interface - int (*close)(void); -}; /** * Initialize the plugin system. * always succeeds or aborts */ void -lumiera_init_plugin (void); - +lumiera_pluginregistry_init (void); /** - * Make an interface available. - * To use an interface provided by a plugin it must be opened first. It is allowed to open an interface - * more than once. Each open must be paired with a close. - * @param name name of the plugin to use. - * @param interface name of the interface to open. - * @param min_revision the size of the interface structure is used as measure of a minimal required - * revision (new functions are appended at the end) - * @return handle to the interface or NULL in case of a error. The application shall cast this handle to - * the actual interface type. - */ -struct lumiera_interface* -lumiera_interface_open (const char* plugin, const char* name, size_t min_revision); - - -/** - * Close an interface. Does not free associated resources - * Calling this function with self==NULL is legal. Every interface handle must be closed only once. - * @param ptr interface to be closed + * destroy the plugin system, free all resources */ void -lumiera_interface_close (void* self); +lumiera_pluginregistry_destroy (void); + + +LumieraPlugin +lumiera_plugin_load (const char* plugin); + + +int +lumiera_plugin_register (LumieraPlugin); + + +/** + * discover new plugins + * traverses the configured plugin dirs and calls the callback_load function for any plugin + * not actually loaded. If callback_load returns a plugin (and not NULL) then this is feed to + * the callback_register function. + */ +int +lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), + int (*callback_register) (LumieraPlugin)); + + + + /** * Tries to unload a plugin. @@ -136,22 +93,5 @@ lumiera_interface_close (void* self); int lumiera_plugin_unload (const char* plugin); -/** - * Tries to unload plugins which are not in use. - * Calls lumiera_plugin_unload() for each Plugin which is not used for more than age seconds. - * This function might be infrequently called by the scheduler to remove things which are not needed. - * @param age timeout in seconds when to unload plugins - */ -void -lumiera_plugin_expire (time_t age); -LUMIERA_ERROR_DECLARE(PLUGIN_DLOPEN); -LUMIERA_ERROR_DECLARE(PLUGIN_HOOK); -LUMIERA_ERROR_DECLARE(PLUGIN_NFILE); -LUMIERA_ERROR_DECLARE(PLUGIN_NIFACE); -LUMIERA_ERROR_DECLARE(PLUGIN_REVISION); - -#ifdef __cplusplus -} /* extern "C" */ -#endif #endif /* LUMIERA_PLUGIN_H */ From d510ade5c3cb48426da8370fe1407150f493f74e Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Fri, 31 Oct 2008 06:43:54 +0100 Subject: [PATCH 36/59] fix wordlist tests to use explicit delimiters --- tests/backend/test-config.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/backend/test-config.c b/tests/backend/test-config.c index 506801454..120fc57d7 100644 --- a/tests/backend/test-config.c +++ b/tests/backend/test-config.c @@ -330,7 +330,7 @@ TEST ("wordlist_get_nth") if (!lumiera_config_wordlist_set (argv[2], &argv[3])) printf ("failed setting word '%s=%s': %s\n", argv[2], argv[3], lumiera_error ()); - const char* word = lumiera_config_wordlist_get_nth (argv[2], atoi (argv[4])); + const char* word = lumiera_config_wordlist_get_nth (argv[2], atoi (argv[4]), " \t,;"); printf ("'%s'\n", word?word:"NULL"); @@ -349,7 +349,7 @@ TEST ("wordlist_find") if (!lumiera_config_wordlist_set (argv[2], &argv[3])) printf ("failed setting word '%s=%s': %s\n", argv[2], argv[3], lumiera_error ()); - int n = lumiera_config_wordlist_find (argv[2], argv[4]); + int n = lumiera_config_wordlist_find (argv[2], argv[4], " \t,;"); printf ("'%d'\n", n); @@ -370,7 +370,7 @@ TEST ("wordlist_replace") if (!lumiera_config_wordlist_set (argv[2], &argv[3])) printf ("failed setting word '%s=%s': %s\n", argv[2], argv[3], lumiera_error ()); - const char* wordlist = lumiera_config_wordlist_replace (argv[2], argv[4], *argv[5]?argv[5]:NULL, *argv[6]?argv[6]:NULL); + const char* wordlist = lumiera_config_wordlist_replace (argv[2], argv[4], *argv[5]?argv[5]:NULL, *argv[6]?argv[6]:NULL, " \t,;"); if (wordlist) printf ("'%s'\n", wordlist); @@ -393,13 +393,13 @@ TEST ("wordlist_add") if (!lumiera_config_wordlist_set (argv[2], &argv[3])) printf ("failed setting word '%s=%s': %s\n", argv[2], argv[3], lumiera_error ()); - const char* wordlist = lumiera_config_wordlist_add (argv[2], argv[4]); + const char* wordlist = lumiera_config_wordlist_add (argv[2], argv[4], " \t,;"); if (wordlist) printf ("'%s'\n", wordlist); else printf ("%s\n", lumiera_error ()); - wordlist = lumiera_config_wordlist_add (argv[2], argv[5]); + wordlist = lumiera_config_wordlist_add (argv[2], argv[5], " \t,;"); if (wordlist) printf ("'%s'\n", wordlist); else From 10e22c74f7c8cc84e8d13cf762dcab77bce0d898 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Fri, 31 Oct 2008 06:44:27 +0100 Subject: [PATCH 37/59] fix test-interfaces for new plugin parameter --- tests/backend/test-interfaces.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/backend/test-interfaces.c b/tests/backend/test-interfaces.c index 8d7c377e8..110c6a855 100644 --- a/tests/backend/test-interfaces.c +++ b/tests/backend/test-interfaces.c @@ -298,7 +298,7 @@ TEST ("basic") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (interfaces_defined_here()); + lumiera_interfaceregistry_bulkregister_interfaces (interfaces_defined_here(), NULL); /* some ugly lowlevel handling tests */ @@ -321,7 +321,7 @@ TEST ("basic") TEST ("open_close") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (interfaces_defined_here()); + lumiera_interfaceregistry_bulkregister_interfaces (interfaces_defined_here(), NULL); LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_one, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_one, 0, 0, lumieraorg_first_test); @@ -338,7 +338,7 @@ TEST ("open_close") TEST ("dependencies_one") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests()); + lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_one); @@ -356,7 +356,7 @@ TEST ("dependencies_one") TEST ("dependencies_two") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests()); + lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two); @@ -373,7 +373,7 @@ TEST ("dependencies_two") TEST ("dependencies_three") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests()); + lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_three); @@ -391,7 +391,7 @@ TEST ("dependencies_three") TEST ("dependencies_four") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests()); + lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_four); @@ -410,7 +410,7 @@ TEST ("dependencies_four") TEST ("dependencies_all") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests()); + lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); TRACE (tests, "OPEN one"); LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle_one = From 1da6e70d549086ad1aa08680a9989a99e6ee8510 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 1 Nov 2008 19:54:59 +0100 Subject: [PATCH 38/59] draft for a solution how to relate project, timeline(s) and EDLs --- wiki/renderengine.html | 91 +++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 19 deletions(-) diff --git a/wiki/renderengine.html b/wiki/renderengine.html index bb22c2320..26659922d 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -514,6 +514,20 @@ ColorPalette SiteUrl +
+
Memory management facility for the low-level model (render nodes network). The model is organised into temporal segments, which are considered to be structurally constant and uniform. The objects within each segment are strongly interconnected, and thus each segment is being built in a single build process and is replaced or released as a whole. __~AllocationCluster__ implements memory management to support this usage pattern. He owns a number of object families of various types.[>img[draw/AllocationCluster.png]]
+* [[processing nodes|ProcNode]] &mdash; probably with several subclasses (?)
+* [[wiring descriptors|WiringDescriptor]]
+* the input/output descriptor arrays used by the latter
+
+To Each of those families we can expect an initially undetermined (but rather large) number of individual objects, which can be expected to be allocated within a short timespan and which are to be released cleanly on destruction of the AllocationCluster.
+
+''Problem of calling the dtors''
+Even if the low-level memory manager(s) may use raw storage, we require that the allocated object's destructors be called. This means keeping track at least of the number of objects allocated (without wasting too much memory for bookkeeping). Besides, as the objects are expected to be interconnected, it may be dangerous to destroy a given family of objects while another family of objects may rely on the former in its destructor. //If we happen do get into this situation,// we need to define a priority order on the types and assure the destruction sequence is respected.
+
+&rarr; see MemoryManagement
+
+
Asset management is a subsystem on its own. Assets are "things" that can be loaded into a session, like Media, Clips, Effects, Transitions. It is the "bookkeeping view", while the EDL is the "manipulation and process view". Some Assets can be //loaded// and a collection of Assets is saved with each Session. Besides, there is a collection of basic Assets always available by default.
 
@@ -1107,8 +1121,16 @@ The main tool used to implement this separation is the [[Builder Pattern|http://
 Another pertinent theme is to make the basic building blocks simpler, while on the other hand gaining much more flexibility for combining these building blocks. For example we try to unfold any "internal-multi" effects into separate instances (e.g. the possibility of having an arbitrary number of single masks at any point of the pipeline instead of having one special masking facility encompassing multiple sub-masks. Similarly, we treat the Objects in the EDL in a more uniform manner and gain the possibility to [[place|Placement]] them in various ways.
 
-
-
''EDL'' is a short-hand for __E__dit __D__ecision __L__ist. The use of this term can be confusing; for the usual meaning see the definition in [[Wikipedia|http://en.wikipedia.org/wiki/Edit_decision_list]]
+
+
<<<
+{{red{WARNING: Naming is currently being discussed (11/08)}}}
+* [[EDL]] probably will be called ''Sequence'' (or maybe ''Arrangement'')
+* [[Session]] maybe renamed to ''Project''
+* there seems to be a new entity called [[Timeline]] which holds the global Pipes
+<<<
+
+
+''EDL'' is a short-hand for __E__dit __D__ecision __L__ist. The use of this term can be confusing; for the usual meaning see the definition in [[Wikipedia|http://en.wikipedia.org/wiki/Edit_decision_list]]
 
 Cinelerra uses this term in a related manner but with a somewhat shifted focus (and we just stick to this usage here): In Lumiera the EDL is comprised of the whole set of clips and other media objects parametrized and placed onto the tracks by the user. It is the result of the user's //editing efforts.//
 
@@ -1379,7 +1401,7 @@ Besides routing to a global pipe, wiring plugs can also connect to the source po
 Finally, this example shows an ''automation'' data set controlling some parameter of an effect contained in one of the global pipes. From the effect's POV, the automation is simply a ParamProvider, i.e a function yielding a scalar value over time. The automation data set may be implemented as a bézier curve, or by a mathematical function (e.g. sine or fractal pseudo random) or by some captured and interpolated data values. Interestingly, in this example the automation data set has been placed relatively to the meta clip (albeit on another track), thus it will follow and adjust when the latter is moved.
 
-
+
This wiki page is the entry point to detail notes covering some technical decisions, details and problems encountered in the course of the implementation of the Lumiera Renderengine, the Builder and the related parts.
 
 * [[Packages, Interfaces and Namespaces|InterfaceNamespaces]]
@@ -1398,6 +1420,7 @@ Finally, this example shows an ''automation'' data set controlling some paramete
 * [[how to handle »attached placement«|AttachedPlacementProblem]]
 * working out the [[basic building situations|BuilderPrimitives]] and [[mechanics of rendering|RenderMechanics]]
 * how to classify and [[describe media stream types|StreamType]] and how to [[use them|StreamTypeUse]]
+* the relation of [[Project, Timelines and Sequences|TimelineSequences]]
 
@@ -1782,7 +1805,7 @@ From experiences with other middle scale projects, I prefer having the test code * {{red{and what else?}}}
-
+
The ~MObjects Subsystem contains everything related to the [[EDL]] and the various Media Objects placed within. It is complemented by the Asset Management (see &rarr; [[Asset]]). Examples for [[MObjects|MObject]] being:
 * audio/video clips
 * effects and plugins
@@ -1826,10 +1849,10 @@ This Design strives to achieve a StrongSeparation between the low-level Structur
 {{red{let's see if this approach works...}}}
 
-
-
Contrary to the &rarr;[[Assets and MObjects|ManagementAssetRelation]], the usage pattern for [[render nodes|ProcNode]] is quite simple: All nodes are created together every time a new segment of the network is being build and are all needed together until this segment is re-built, at which point they can be thrown away altogether. While it would be easy to handle the nodes automatically by smart-ptr (the creation is accessible only by use of the {{{NodeFactory}}} anyways), it //seems advisable to care for a bulk allocation/deallocation here.// The reason being not so much the amount of memory (which is expected to be moderate), but the fact, that the build process can be triggered repeatedly several times a second when tweaking the EDL, which could lead to fragmentation and memory pressure.
+
+
Contrary to the &rarr;[[Assets and MObjects|ManagementAssetRelation]], the usage pattern for [[render nodes|ProcNode]] is quite simple: All nodes are created together every time a new segment of the network is being build and are all needed together until this segment is re-built, at which point they can be thrown away altogether. While it would be easy to handle the nodes automatically by smart-ptr (the creation is accessible only by use of the {{{NodeFactory}}} anyways), it //seems advisable to care for a bulk allocation/deallocation here.// The reason being not so much the amount of memory (which is expected to be moderate), but the fact the build process can be triggered repeatedly several times a second when tweaking the EDL, which could lead to fragmentation and memory pressure.
 
-__5/2008__: the allocation mechanism can surely be improved later, but for now I am going for a simple implementation based on keeping all nodes of one kind together in a vector. The list of possible node kinds is hard wired, allowing to generate the object holding a chunk of nodes for one segment, mostly relying on the runtime system for the management.
+__10/2008__: the allocation mechanism can surely be improved later, but for now I am going for a simple implementation based on heap allocated objects owned by a vector or smart-ptrs. For each segment of the render nodes network, we have several families of objects, each of with will be maintained by a separate low-level memory manager (as said, for now implemented as vector of smart-ptrs). Together, they form an AllocationCluster; all objects contained in such a cluster will be destroyed together.
 
@@ -2787,13 +2810,14 @@ Besides, they provide an important __inward interface__ for the [[ProcNode]]s, w
-
+
The Render Engine is the part of the application doing the actual video calculations. Its operations are guided by the Objects and Parameters edited by the user in [[the EDL|EDL]] and it retrieves the raw audio and video data from the [[Data backend|backend.html]]. Because the inner workings of the Render Engine are closely related to the structures used in the EDL, this design covers [[the aspect of objects placed into the EDL|MObjects]] as well.
 <<<
 ''Status'': started out as design draft in summer '07, Ichthyo is now in the middle of a implementing the foundations and main structures in C++
 * basic [[AssetManager]] working
 * [[Builder]] implementation is on the way (&rarr;[[more|BuilderPrimitives]])
 * made a first draft of how to wire and operate procesing nodes (&rarr;[[more|RenderMechanics]])
+* working out the relation of [[Project, Timelines and Sequences|TimelineSequences]]
 <<<
 
 !Summary
@@ -3239,12 +3263,22 @@ The Session object is a singleton &mdash; actually it is a »~PImpl«-Facade
 * a collection of ''global Pipes''
 * the ''Fixture'' with a possibility to [[(re)build it|PlanningBuildFixture]]
-
-
The [[Session]] (sometimes also called //Project// ) contains all informations and objects to be edited by the User. It can be saved and loaded. The individual Objects within the Session, i.e. Clips, Media, Effects, are contained in one (or several) collections within the Session, which we call [[EDL (Edit Decision List)|EDL]]. Moreover, the sesion contains references to all the Media files used, and it contains various default or user defined configuration, all being represented as [[Asset]]. At any given time, there is //only one current session// opened within the application.
-The Session is close to what is visible in the GUI. From a user's perspective, you'll find a timeline-like structure, where various Media Objects are arranged and placed. The available building blocks and the rules how they can be combined together form Lumiera's [[high-level data model|HighLevelModel]]. Basically, besides the [[media objects|MObjects]] there are data connections and all processing is organized around processing chains or [[pipes|Pipe]], which can be either global (in the Session) or local (in real or virtual clips)
+
+
<<<
+{{red{WARNING: Naming is currently being discussed (11/08)}}}
+* [[EDL]] probably will be called ''Sequence'' (or maybe ''Arrangement'')
+* [[Session]] maybe renamed to ''Project''
+* there seems to be a new entity called [[Timeline]] which holds the global Pipes
+<<<
+The [[Session]] (sometimes also called //Project// ) contains all informations and objects to be edited by the User. It can be saved and loaded. The individual Objects within the Session, i.e. Clips, Media, Effects, are contained in one (or several) collections within the Session, which we call [[EDL (Edit Decision List)|EDL]]. Moreover, the sesion contains references to all the Media files used, and it contains various default or user defined configuration, all being represented as [[Asset]]. At any given time, there is //only one current session// opened within the application.
+The Session is close to what is visible in the GUI. From a user's perspective, you'll find a [[Timeline]]-like structure, containing an [[EDL (or Sequence)|EDL]], where various Media Objects are arranged and placed. The available building blocks and the rules how they can be combined together form Lumiera's [[high-level data model|HighLevelModel]]. Basically, besides the [[media objects|MObjects]] there are data connections and all processing is organized around processing chains or [[pipes|Pipe]], which can be either global (in the Session) or local (in real or virtual clips)
 
 !!!larger projects
-For larger editing projects the simple structure of a session containing "the" timeline is not sufficient. Rather, we have several timelines, e.g. one for each scene. Or we could have several layered or nested timelines (compositional work, multimedia productions). To support these cases without making the default case more complicated, Lumiera introduces a //focus// for selecting the //current EDL,// which will receive all editing operations.
+For larger editing projects the simple structure of a session containing "the" timeline is not sufficient. Rather
+* we may have several [[EDLs (=Sequences)|EDL]], e.g. one for each scene. These sequences can be even layered or nested (compositional work).
+* within one project, there may be multiple, //independant Timelines// &mdash; each of which may have an associated Viewer or Monitor
+To support these cases without making the default case more complicated, Lumiera introduces a //focus// for selecting the //current EDL,// which will receive all editing operations. [[Timelines|Timeline]] on the other hand are always top-level objects and can't be combined further. You can render a given timeline to output.
+&rarr; see [[Relation of Project, Timelines and Sequences|TimelineSequences]]
 
 !!!the definitive state
 With all the structural complexities possible within such a session, we need an isolation layer to provide __one__ definitive state where all configuration has been made explicit. Thus the session manages one special object list, the [[Fixture]], which can be seen as all currently active objects placed onto a single timeline.
@@ -3260,6 +3294,8 @@ While all these possibilities may seem daunting, there is a simple default confi
 It will contain a global video and audio out pipe, just one EDL with a single track; this track will have a internal video and audio pipe (bus) configured with one fading device sending to the global output ports. So, by adding some clip with a simple absolute placement to this track and some time position, the clip gets connected and rendered, after [[(re)building|PlanningBuildFixture]] the [[Fixture]] and passing the result to the [[Builder]] &mdash; and using the resulting render nodes network (Render Engine).
 
 &rarr; [[anatomy of the high-level model|HighLevelModel]]
+&rarr; considerations regarding [[Tracks and Pipes within the EDL|TrackPipeEDL]]
+&rarr; see [[Relation of Project, Timelines and Sequences|TimelineSequences]]
 
@@ -4717,20 +4753,37 @@ function addKeyDownHandlers(e)
http://tiddlywiki.com/
-
-
Timeline is the name of a specific facility located in the [[Fixture]] (EDL): It is a ordered list of ExplicitPlacement.s of MObjects. By traversing the Playlist you get at all elements actually to be rendered; the [[Builder]] uses this Timeline-list to construct actual Render Engine configurations to carry out the calculations.
+
+
Timeline is the top level element within the [[Session (Project)|Session]]. It is visible within a //timeline view// in the GUI and represents the definitive arrangement of media objects, to be rendered for output or viewed in a Monitor (viewer window). A timeline is comprised of:
+* a time axis in abolute time (WIP: not clear if this is an entity or just a conceptual definition) 
+* a PlayControler
+* a list of global Pipes representing the possible outputs
+* //exactly one// top-level [[EDL (Sequence)|EDL]], which in turn may contain further nested ~EDLs (Sequences).
+Please note especially that following this design //a timeline doesn't define tracks.// [[Tracks form a Tree|Track]] and are part of the individual ~EDLs (Sequences), together with the media objects placed to these tracks.
 
+Within the Project, there may be ''multiple timelines'', to be viewed and rendered independently. But, being the top-level entities, multiple timelines may not be combined further. You can always just render (or view) one specific timeline. A given sequence may be referred directly or indirectly from multiple timelines though.
+
+''Note'': in early drafts of the design (2007) there was an entity called "Timeline" within the [[Fixture]]. This entity seems superfluous and has been dropped. It never got any relevance in existing code and at most was used in some code comments.
 
-
-
Tracks are just a structure used to organize the Media Objects within the EDL. They form a grid, and besides that, they have no special meaning. They are grouping devices, not first-class entities. A track doesn't "have" a port or pipe or "is" a video track and the like; it can be configured to behave in such manner by using placements.
+
+
Each Project can contain ''multiple timelines'', to be viewed and rendered independently. But, being the top-level entities, multiple timelines may not be combined further. You can always just render (or view) one specific timeline. Of course it is possible to use ~Sub-EDLs (~Sub-Sequences) within the top-level Sequence within a timeline to organize a movie into several scenes or chapters. 
 
-Tracks are assets on their own, but they can be found within a given EDL. So, several ~EDLs can share a single track or each EDL can have its own, separate tracks. 
-* Like most ~MObjects, tracks have a asset view: you can find a track asset in the asset manager.
-* and they have an object view: there is an track MObject which can be [[placed|Placement]], thus defining properties of this track within one EDL
+As stated in the [[definition|Timeline]], a timeline refers to exactly one EDL (Sequence), and the latter defines a tree of [[tracks|Track]] and a bunch of media objects placed to these tracks. A Sequence may optionally also contain nested sequences as [[meta-clips|MetaClip]]. Moreover, obviously several timelines (top-level entities) may refer to the same Sequence without problems.
+This is because the top-level entities (Timelines) are not permitted to be combined further. You may play or render a given timeline, you may even play several timelines simultanously in different monitor windows, and these different timelines may incorporate the same sequence in a different way
+
+
+
+
Tracks are just a structure used to organize the Media Objects within the EDL. Tracks are associated allways to a specific EDL and the Tracks of an EDL form a //tree.// They can be considered to be an organizing grid, and besides that, they have no special meaning. They are grouping devices, not first-class entities. A track doesn't "have" a port or pipe or "is" a video track and the like; it can be configured to behave in such manner by using placements.
+
+The ~Track-IDs are assets on their own, but they can be found within a given EDL. So, several ~EDLs can share a single track or each EDL can have tracks with their own, separate identity. (the latter is the default)
+* Like most ~MObjects, tracks have a asset view: you can find a track asset (a track ID) in the asset manager.
+* and they have an object view: there is an track MObject which can be [[placed|Placement]], thus defining properties of this track within one EDL, e.g. the starting point in time
 Of course, we can place other ~MObjects relative to some track (that's the main reason why we want to have tracks). In this sense, the [[handling of Tracks|TrackHandling]] is somewhat special: the placement of some track can be found directly within the EDL (and not within the general collection of placed objects which form the contents of any EDL). This placement defines properties of the track, which will be inherited if necessary by all ~MObjects placed to this track. For example, if placing (=plugging) a track to some global [[Pipe]], and if placing a clip to this track, without placing the clip directly to another pipe, the associated-to-pipe information of the track will be fetched by the builder when needed to make the output connection of the clip.
 &rarr; [[Handling of Tracks|TrackHandling]]
 &rarr; [[Handling of Pipes|PipeHandling]]
+
+&rarr; [[Anatomy of the high-level model|HighLevelModel]]
 
From 0d1dbac28fdfa00677487dcb8dce1df415ba6a4c Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 2 Nov 2008 23:19:37 +0100 Subject: [PATCH 39/59] UML drawing and further description of Timeline, Sequence, Output --- doc/devel/uml/class128005.html | 2 +- doc/devel/uml/class128133.html | 6 +- doc/devel/uml/class128261.html | 4 +- doc/devel/uml/class128389.html | 2 +- doc/devel/uml/class128517.html | 2 +- doc/devel/uml/class128901.html | 6 +- doc/devel/uml/class129029.html | 6 +- doc/devel/uml/class129669.html | 2 +- doc/devel/uml/class139653.html | 2 +- doc/devel/uml/classdiagrams.html | 2 + doc/devel/uml/classes.html | 16 +- doc/devel/uml/classes_list.html | 16 +- doc/devel/uml/fig128133.png | Bin 67880 -> 64556 bytes doc/devel/uml/fig132485.png | Bin 0 -> 6985 bytes doc/devel/uml/fig132741.png | Bin 0 -> 25229 bytes doc/devel/uml/index.html | 306 +++++++++++++++------------ doc/devel/uml/index_60.html | 4 +- doc/devel/uml/index_65.html | 6 +- doc/devel/uml/index_67.html | 50 ++--- doc/devel/uml/index_69.html | 2 +- doc/devel/uml/index_70.html | 2 +- doc/devel/uml/index_71.html | 1 + doc/devel/uml/index_73.html | 5 +- doc/devel/uml/index_77.html | 2 + doc/devel/uml/index_80.html | 7 +- doc/devel/uml/index_82.html | 1 + doc/devel/uml/index_83.html | 13 +- doc/devel/uml/index_84.html | 17 +- doc/devel/uml/index_86.html | 12 +- doc/devel/uml/packages.html | 6 +- doc/devel/uml/public_operations.html | 4 +- uml/lumiera/128005 | 208 +++++++++++++++++- uml/lumiera/128133.diagram | 33 ++- uml/lumiera/128261 | 146 +++++++++++-- uml/lumiera/129029 | 2 +- uml/lumiera/129285 | 16 +- uml/lumiera/5.session | 25 ++- uml/lumiera/lumiera.prj | 2 +- wiki/renderengine.html | 23 +- 39 files changed, 676 insertions(+), 283 deletions(-) create mode 100644 doc/devel/uml/fig132485.png create mode 100644 doc/devel/uml/fig132741.png diff --git a/doc/devel/uml/class128005.html b/doc/devel/uml/class128005.html index 06db277ae..d033a8de1 100644 --- a/doc/devel/uml/class128005.html +++ b/doc/devel/uml/class128005.html @@ -18,7 +18,7 @@

Declaration :

  • C++ : class SessionImpl : public Session

Implementation class for the Session interface

Artifact : sessionimpl, Component(s) : Session

-
Relation edls (<directional aggregation by value>)

Declaration :

  • Uml : # edls : EDL, multiplicity : 1..*
  • C++ : protected: <EDL> edls
+
Relation edls (<directional aggregation by value>)

Declaration :

  • Uml : # edls : Seq, multiplicity : 1..*
  • C++ : protected: <Seq> edls
Relation theFixture (<unidirectional association>)

Declaration :

  • Uml : # theFixture : Fixture, multiplicity : 1
  • C++ : protected: Fixture * theFixture
Relation pipes (<directional aggregation>)

Declaration :

  • Uml : # pipes : Pipe, multiplicity : *
  • C++ : protected: Pipe* pipes

the global ports (busses) of the session

All public operations : currEDL , getFixture

diff --git a/doc/devel/uml/class128133.html b/doc/devel/uml/class128133.html index caa5c3e37..175eb30d6 100644 --- a/doc/devel/uml/class128133.html +++ b/doc/devel/uml/class128133.html @@ -4,19 +4,19 @@ -Class EDL +Class Seq -
Class EDL
+
Class Seq

-

Declaration :

  • C++ : class EDL

Directly inherited by : Fixture

+

Declaration :

  • C++ : class Seq

Directly inherited by : Fixture

Artifact : edl, Component(s) : Session

Relation clips (<directional aggregation>)

Declaration :

  • Uml : # clips : MObject, multiplicity : *
  • C++ : protected: list<MObject *> clips
diff --git a/doc/devel/uml/class128261.html b/doc/devel/uml/class128261.html index 0d8043e71..f02717863 100644 --- a/doc/devel/uml/class128261.html +++ b/doc/devel/uml/class128261.html @@ -16,9 +16,9 @@ -

Declaration :

  • C++ : class Fixture : public EDL

Artifact : fixture, Component(s) : Session

+

Declaration :

  • C++ : class Fixture : public Seq

Artifact : fixture, Component(s) : Session

-
Relation theTimeline (<directional aggregation by value>)

Declaration :

+
Relation effectiveTimeline (<directional aggregation by value>)

Declaration :

Operation getPlaylistForRender

Declaration :

  • Uml : + getPlaylistForRender() : list<ExplicitPlacement [ProcessingLayer::MObject]>
  • C++ : public: list<ExplicitPlacement [ProcessingLayer::MObject]> getPlaylistForRender ()
Operation getAutomation

Declaration :

  • Uml : + getAutomation() : Auto [ProcessingLayer::MObject]*
  • C++ : public: Auto [ProcessingLayer::MObject]* getAutomation ()
Relation track (<unidirectional association>)

Declaration :

  • Uml : # track : Track
  • C++ : protected: Track* track
diff --git a/doc/devel/uml/class128389.html b/doc/devel/uml/class128389.html index 222aa9902..1adc7425d 100644 --- a/doc/devel/uml/class128389.html +++ b/doc/devel/uml/class128389.html @@ -16,7 +16,7 @@ -

Declaration :

  • C++ : class Track : public Meta

Artifact : track, Diagram : Session structure

+

Declaration :

Artifact : track, Diagram : Session structure

Relation subTracks (<directional aggregation by value>)

Declaration :

  • Uml : + subTracks : Track, multiplicity : *
  • C++ : public: Track subTracks

Child tracks in a tree structure

All public operations : apply , apply , dispatchOp

diff --git a/doc/devel/uml/class128517.html b/doc/devel/uml/class128517.html index 9b18007fc..892d720be 100644 --- a/doc/devel/uml/class128517.html +++ b/doc/devel/uml/class128517.html @@ -16,7 +16,7 @@ -

Declaration :

  • C++ : class MObject : public Buildable
  • Java : public interface MObject

Directly inherited by : AbstractMO

+

Declaration :

  • C++ : class MObject : public Buildable
  • Java : public interface MObject

Directly inherited by : AbstractMO Clip Effect Label Track

Artifact : mobject, Component(s) : Session

Attribut length
diff --git a/doc/devel/uml/class128901.html b/doc/devel/uml/class128901.html index 3258b0d8f..9cc9def6f 100644 --- a/doc/devel/uml/class128901.html +++ b/doc/devel/uml/class128901.html @@ -16,11 +16,9 @@ -

Declaration :

Directly inherited by : CompoundClip SimpleClip

+

Declaration :

Directly inherited by : CompoundClip SimpleClip

Artifact : clip

- -
Attribut start
-

Declaration :

  • Uml : # start : Time
  • C++ : protected: Time start

startpos in source

+
Relation source (<unidirectional association>)

Declaration :

  • Uml : # source : Media, multiplicity : 1
  • C++ : protected: Media* source

the media source this clip referes to

All public operations : apply , apply , dispatchOp

diff --git a/doc/devel/uml/class129029.html b/doc/devel/uml/class129029.html index f9a14681d..b04d54df7 100644 --- a/doc/devel/uml/class129029.html +++ b/doc/devel/uml/class129029.html @@ -16,10 +16,10 @@ -

Declaration :

Artifact : effect

+

Declaration :

Artifact : effect

-
Attribut plugID
-

Declaration :

  • Uml : # plugID : string
  • C++ : protected: string plugID

Identifier of the Plugin to be used

+
Attribut plugin
+

Declaration :

  • Uml : # plugin : string
  • C++ : protected: string plugin

Identifier of the Plugin to be used

All public operations : apply , apply , dispatchOp

diff --git a/doc/devel/uml/class129669.html b/doc/devel/uml/class129669.html index 8653baa45..199b5d53f 100644 --- a/doc/devel/uml/class129669.html +++ b/doc/devel/uml/class129669.html @@ -16,7 +16,7 @@ -

Declaration :

  • C++ : class Label : public Meta

Artifact : label

+

Declaration :

Artifact : label

All public operations : apply , apply , dispatchOp

diff --git a/doc/devel/uml/class139653.html b/doc/devel/uml/class139653.html index 641046544..076a6ee5b 100644 --- a/doc/devel/uml/class139653.html +++ b/doc/devel/uml/class139653.html @@ -19,7 +19,7 @@

Declaration :

  • C++ : class Session

Directly inherited by : SessionImpl

Primary 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.

Artifact : session

-
Operation currEDL

Declaration :

  • Uml : + currEDL() : EDL
  • C++ : public: EDL currEDL ()

The EDL currently in focus. In most cases, Session and EDL are almost the same, just EDL emphasizes the collection aspect. But generally (for larger editing projects) one Session can contain several EDLs, which may even be nested. At any given time, only one of these EDLs has focus and recieves the editing commands.

+
Operation currEDL

Declaration :

  • Uml : + currEDL() : Seq
  • C++ : public: Seq currEDL ()

The EDL currently in focus. In most cases, Session and EDL are almost the same, just EDL emphasizes the collection aspect. But generally (for larger editing projects) one Session can contain several EDLs, which may even be nested. At any given time, only one of these EDLs has focus and recieves the editing commands.

Operation getFixture

Declaration :

  • Uml : + getFixture() : Fixture&
  • C++ : public: Fixture& getFixture ()

While the session can be comprised of several EDLs,
there is only one Fixture, which represents the actual
configuration of all Objects to be rendered

Relation current (<unidirectional association>)

Declaration :

Standard access path to get at the current session via the Session Manager, which acts as a "PImpl" smart pointer

Relation defaults (<unidirectional association>)

Declaration :

diff --git a/doc/devel/uml/classdiagrams.html b/doc/devel/uml/classdiagrams.html index e1289d57d..f66c12462 100644 --- a/doc/devel/uml/classdiagrams.html +++ b/doc/devel/uml/classdiagrams.html @@ -31,7 +31,9 @@ Rules access Session structure StateAdapter composition +Stream Type Framework Struct-Asset Relations +TimelineSequences diff --git a/doc/devel/uml/classes.html b/doc/devel/uml/classes.html index 319577971..63214df7b 100644 --- a/doc/devel/uml/classes.html +++ b/doc/devel/uml/classes.html @@ -52,7 +52,6 @@ DefaultsRegistry DoAttach DoRecurse -EDL EffectEffect or media processing component Effect Error @@ -75,6 +74,7 @@ FrameDescriptorinterfaceA FrameDescriptor implements the higher level interfaces for frames. Further refinements are made by subclassing and policy classes FrameReference GLBuf +ImplFacade InterpolatorProvides the implementation for getting the acutal value of a time varying or automated effect/plugin parameter Invalid Invocation @@ -88,9 +88,11 @@ Mediakey abstraction: media-like assets MediaAccessFacadeboundaryprovides functions for querying (opening) a media file, detecting the channels or streams found within this file, etc. Delegating to the actual backend functions MediaFactoryspecialized Asset Factory for configuring (new) media asset instances based on existing media files on disk; can create placeholder assets as well +MediaKindenum Metakey abstraction: metadata and organisational asset Meta MObjectinterface +Monitor 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 @@ -100,6 +102,8 @@ PathManagerWhile building a render engine, this Strategy class decides on the actual render strategy in accordance to the current controller settings (system state) Pipestructural asset representing a basic building block within the high level model: a port for building a processing chain and generating media output Placementinterfaceused to specify the position of a MObject in the EDL. This can be done in various ways (absolute, relative).
Placement at the same time acts as (refcounting) smart pointer for accessing the MObject. +PlayControl +PlayheadCursor Plug PluginAdapterAdapter used to integrage an effects processor in the render pipeline Prefetch @@ -110,7 +114,9 @@ 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. +Project ProjectorSpecial video processing node used to scale and translate image data. +Prototype PullInput QueryCache QueryHandlerinterface @@ -120,10 +126,13 @@ RelTypeenumthe possible kinds of RelativePlacements RenderEngine RenderStateEncapsulates the logic used to get a "current render process" in accordance to the currentyl applicable controller settings. The provided StateProxy serves to hold any mutalbe state used in the render process, so the rest of the render engine can be stateless. +RenderTask ResolverBase Scheduler Segment SegmentationToolTool implementation for deriving a partitioning of the current timeline such, that each segement has a constant configuration. "Constant" means here, that any remaining changes over time can be represented by automation solely, without the need to change the node connections. +Seq +Sequence Serializeractor SessionPrimary 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. SessionImplImplementation class for the Session interface @@ -137,9 +146,14 @@ StateProxyimplementation std::exceptionauxiliary Strategy +StreamType +StreamTypeID Structkey abstraction: structural asset +STypeManager 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 +Timeline +TimelineView Tool ToolFactory Trackstructural asset holding the configuration of a track in the EDL diff --git a/doc/devel/uml/classes_list.html b/doc/devel/uml/classes_list.html index 8e8c2d9a6..96378253b 100644 --- a/doc/devel/uml/classes_list.html +++ b/doc/devel/uml/classes_list.html @@ -53,7 +53,6 @@ DefaultsRegistry
DoAttach
DoRecurse
-EDL
Effect
Effect
Error
@@ -76,6 +75,7 @@ FrameDescriptor
FrameReference
GLBuf
+ImplFacade
Interpolator
Invalid
Invocation
@@ -89,9 +89,11 @@ Media
MediaAccessFacade
MediaFactory
+MediaKind
Meta
Meta
MObject
+Monitor
Mutex
NodeCreatorTool
NodeWiring
@@ -101,6 +103,8 @@ PathManager
Pipe
Placement
+PlayControl
+PlayheadCursor
Plug
PluginAdapter
Prefetch
@@ -111,7 +115,9 @@ Processor
ProcNode
ProcPatt
+Project
Projector
+Prototype
PullInput
QueryCache
QueryHandler
@@ -121,10 +127,13 @@ RelType
RenderEngine
RenderState
+RenderTask
ResolverBase
Scheduler
Segment
SegmentationTool
+Seq
+Sequence
Serializer
Session
SessionImpl
@@ -138,9 +147,14 @@ StateProxy
std::exception
Strategy
+StreamType
+StreamTypeID
Struct
+STypeManager
Thread
Time
+Timeline
+TimelineView
Tool
ToolFactory
Track
diff --git a/doc/devel/uml/fig128133.png b/doc/devel/uml/fig128133.png index 089545c768e411dfdcb5932e8689a0fab1b558c7..ca5e20d4ee1ef62dbd8c8a511a5ad013669ea218 100644 GIT binary patch literal 64556 zcmeFZWmuGN-!3|Wf+8VErw%DdcY_QdASER&pmcYGBHbV$-CfGiE!{|WcX!vm@c%q( zz0bS$+8@?Fj{RxR;UO^0-1pqq{fqN=p67+XoQyac3Ly#v0zs2_3wsZNAPPeu4{;tN zfM>3#l@}n87Z3@Uu%cta_Kd>^Y?UdbeFMXY3b=JS>L2hCSB z9MNEAj%PtBx>DGfm;)bMeE4b0Js;uv8)Aozef9j%=;NN!wCnEiu4J!%`%O*_Z_U}> z;UOWqL0FPa~KFP0ep|BwIwYMdFq zsz!vQ7~}iM+u{k?`N5!~4iAJRUN%1vnyCpo)699w=c9v<#EdRPl_2#90$HKN@@Fb} z`r`S0@X)Zga6w|jKx7L|yli{$R>TJp0znrFLZm?^K!-poAAq-E-M`QhNtf6Y|L=EC zbcrEP?|;h$4(iF&&Ik?zmng^CBx|=8m5kh$StBJkd|a2qBPYib5z!{yv)9$F!p)c}2rwpj4#{~8J}!-CedyGl)4~UQ`xHO^g zho3*+sVFKct97|MQSmtI*4UdDs@JHikxo~J`=J~i-5_C*T9^y8PV#v5Q>T5ct#v{~ zu2xr**_t?VS0k)}hU(bAR$VmKEzxNUO0lT7VrQOMUQ&=)sS_4ndM91clPCpyu)7Om z8~QC=qL;4UN6c=Mb>3a!?R{%*zSPsx78`p}Q&mU*`upw=+qG7DDTgIp)9s2x-Wv4} zt~2F38=5tr%oX+HSAN)S|A>s0fK{FC#@ekn;!0W+t*=OVa8?Y^s|9g#&Q;mIQaAgN zq(!+Sj{LCaLq$-ikM{?WWBy8QHWc!$;T zdhFJiHm?6y*`)2oc}rD_OuLCaOTg**d06FR>@oJ z_{5$0ZHBen%7up7Q^cuL)mC(s4%F! zm3%meQ%koSjMmm|TEe(EyzZ`XJH{v8sLgK~G;sZC^N8;b(#u28_mYbaX?Ivdb!<;g zFjiLBSy-TH4#nEw20!+0vL<6!=vDXxozv6c)QDA8!SNiFX=yQx;v5$4suU4Ujjh2oaX+>@ zdxkBhKWIQ{=!hl?CUPq*CZv-YXpId&?%(#t|0+~VqXW8ZwOy}+U7iRlh&4>h0D?KscX2ZQdCo5llJuD z6w`$WM>yrAbxrc{jBHKZ=|4&pdNISi(Wf$qc87?(YB7~%VR)|owj-jrKF<&yRoXeo z$u>MV(AnEH_-FXj^N8)b=pH|;?x@na*53=4oskiguMGO_H%Ia{*u_LdL=@m@JCbCS zkQ}-WOGpareSdN?*0Ya$%im+7L}AeI9OO_37U)+$bFEtZ#SIA<$IVspV+`uFmdZ*y zEv+cd4<}u3Qh!G5O>%SZXx7CAo4a^@CDzc$_;;|K7fHqVAR);pWH}bA+VH+i-9&~} z%UIyW(A%s{@^UMcjGfBJgm*_rxnEMy&;_DD&XK&DEBt_2ZmH80PX0MF^UaqR8^;?b zL)k7xYLrF$E{fmZQt;Hf)kxpn;+Uyi(kQJMA_^&ed_f4={9x9XDTDFE|7rz~Tu-lN zp}9Dj=j5XC%hFo!)5Cqo%XRssENQ&G$&p-@;%i?FL~5DWu7?>_{+%U1@P|%!Bo>b~ zs=R5HPcN^JWXS}!J3GQA)JdC(>1ZA&GL!Sa^7pGg*;vBERX)6Rs|vX(w>PWm>z}O* zH{(7Z&b6N5g1b0;ZxF=XSl^UELtPFgW3(A!nfksx4pLjy{`4D%+38G!#bA-9sLM@O z%E!ctGf*(?h&YIO4P?gCM7OIHHxL;nZtI9Rq3+krtdycO&r0_O^o-@gxQY(&+uVMC zJ-Rw2C^N*g+)q*UMd$OGIGY!)+7a-$uAKgxZgyNTD8}dw5QtoRUc`dX$?%Ah`N$-6 zwn->)L4y_o86MrjW5k|$1S#{nZ%Jh%8KO^7>k&E#?pxUZDS{$ZM1a@@>EMF~JN)SW zRG`U%gIQvLIRE?g|INYw_1?eT90JLcT}dVn5_jk#yMNx3&kq)ZGvj^P#Kb4+AWZW2 z693Cp{5`*r*`tRKe?FyCDN;0*9Y${ZUwSS0i2rnAAp#{f9bez}&Afu$&FVA}UyIEW zk(5t=yYqK>iB9g=6=voGCDogb@NYdmb#{~Fatt70rW7)AS8z~?x%vkO>kRshjEv4E>EML8P zWqQ1x`TO_K&JOQf{msYC;j&k+7ED(L-wPXWqLYxAl~3YnJ0c@F%Or47FcznnO%<>8 zlkF|RJ0~V?o4nDoWhgH$Z(VOL%O~KRQ6{w1Ypp++yM57j*bVx|?RVb!y{&$T9r7Eo z55o0D2Y;l`@?8C4p7f#0d28U;F z4cIYTTNsQCw~ZV*xw-Pn_Te|9S7!#tCw8qP4-pp1OdMEPZ3YK-EvD=hDXOP)2KKXM zL-Fz1u>E18qOCqYmn`wLbkAE_DQ^#@G={Q}j#h)om>R{ZVY+*cx3{<3EUUheM1SF4 zSpN99l#WjOSFh}1jSCW@u?#7SjdepQPAE1?U|@d$EXKP@s;UaPb;Z>4IT63}M!nlw zZ%+^&gROzoLxfaNs`qZWx%=siC8eZnt{rDnMIKB}stsiq$EYF%c!S)Md^t}Ru=`l3 zE}qq3yUJ!uPmghOqIbONNKv9wd?TVu{TYh)&DGR5-{co*m6b5YVmq7>J`Vx*7as#6 zBi)phNiqFlP|{*?Sc?R-+VLPO+u$)~r|D)}uuCL0awuV$ZHwP*g~eXP{pq&uV|ux_ zElX2z7^6R_ZnAtQC$Jj>kJ0=)L$2WrDgUIy4$sAK?!5nVL=h1^>34DMEwA%)tc4oC zYt>~D5fP!0nH%U0_4Qk9o$fs4VJU3Trw4_;s`&|CR__ek4&bZa$aBjxMQ9B0y z$L3jUiu>3Dr>zuTDfVq{WlNc)y})6hdv0iCq^t!s7}>#c_r^i^3v;n0c!*wcGD1jEf2RT_7;ufImysbk9#_~Emyi2 z1Mz&HWAb*onD73cpWmpj7knOWtH908czJvf%efbWjBz-jpD6`_q;N1*JcgXTmDzA# zY>Bgutc6oXoFJobr>3WCDpQ5M4hog!x8J6%DagH;3$?LX4T?&TW22MEj#*}xx4(4}pr+^w5xQL6J#7d(P3?7XZc7XdT+yBg7(qRLuQ)2c3B&C`O9l4SJ z$1({70v4hY`Tpu5ph{U{{aq3pM;Sy2=f?;Kh)i?3a!TKQJzIOV5VR>dP6>hF{4Lp# zMt-nx;4%I8$CQs}dxARnN$1+W=yMuXhhvpibgy4e<4iFN2sU?{%+$G51?(Vod_zT+ z3mqq7vLd2_D2BM1&U}5ei-{Sy+C$)ScN^*bwBq0*_VhFnXX;n8?{g@*EW63*hhH;) zN1#nj2?_tS8Zf`mb8~z7U0=7kI8}Z7_KrGDrFeE_wf-l3>v~xtHGeCBN?Od&5S5MD zYNl+94U+;q;k{i%2B9vp(-T$dkS#G*Er zn$PHND&7a0p6;TEhylBC1|Er9wBM(Z{uj{jx1~ly#PsyNh3cVL@^3qArKQoRsjuo> zVrY-|JxzZs;iZ_LpPzH_@@iLFE)3@?)YsRK6>G;74b?gw)z;RAg+0^Op34U}pw6#zP9*pO_J37$I^=T7=4vvnh{aUP%O_pS5W2-+;(}T4% zu^OC9NNkw)Yz}3ce4HnR283wo>JHZGi62qRqD0dNQlu&6r%fPrcRh4TW8rZ5EEUu#y|M)9I?06;!&YUevEuDbBzOivVqT;62;O=m; znW)ojIx~a#`n6iz4>syFJVvef_=>kOeTFmDD-&=J!3`M-EW3@vnMx}}KN@cC=EfAA zu_CkGnQphUBF9EgQq$B=H*LX0laqaxwxy%P!;Xg;`x9`Lq9R1U^}`i5=;lmKJ~Ra7 znisT>93q4-LW>gn+)=~BfBt|%j*Lz`UTzkjnyT~mZHJ1s8)b|Df+vflj12XCNubLg zRaP!ULnTD3cQS9s6j-|;(@4iv$evWmTe+}z*jOKA8XMPMtN;PuOE zcsyLTm=0Omf+m;L&FmKDIX^`Zqu%%+<`D6bGC~20XV9wsFyKFslS32!7MqlGcYS?4 zQwk3e(d(5$R)H#<>g7w}`a~rXfaujL%-OXxFQXUo=3v_k3-U`l2yYjUSj$S;1n+9S zDwk*Lrqj~y;1zp(P9>4`^+gqD)#9N^QQuunhq9u+2sd|h?5UR-bLceX-CQw}a?Q^b zYoCFZ0`ANH{)e0GiF~-hn4r`9w=jEq<-NI>>yt5Zmn(*CWqcni+fpiM?8$`j_6$x) z$c%qSPtOmXA7No`0bI2Ed;7JDp4A8E2YMJ7q2i&W>}Hd;V?~;E&L?RN$ze2DcY=Ct zLFwY5<%R=`jb9K!-WZTE=H%xS;p20;U!QkPwKwBtwzjqH&emP^#ImyA^0wU?Qb?Ik zSN^`;HvY*VM7d9gYKOiAqPDrI3ChgO%*eQRx-+%-tg*g5aBc%UnIz!myalH4L>}oR zK5pK>4_4MAZA9XZPdYjaOH1TO>MRylIHA8J(916_FUyTb@?6e#Hvl2<$;2c+CWg~; zUPwx+JBi;VD>E~^AUCv;7@Hqf(#t6+DJ3K%04?*1fg#$U7-Eb{fG)%y zOjPkz$5FFJM!x|SL$I&!?sk1Z0U8h}RSJ(!O=oTS^QX00?<8ME6n1=h!t1l}i?cxD zaR0+h$;uDf5bjPJWd~$rUrchbj_XlSR6y0ZJwI5IieVrTaIK6Gn*<@8oGfUy*fIe( zfK$Q^`q9zR`}+Dq0s;YQEB_$>EmNdUQKPMvET3oaS zWj26Tqta4mAWak#6O-3|JItW{pHD7>_5ArtRn_ux5S28lq@(~=xX=q!H2#mDhC9Z` zI|dKo^y=uLBsH}<%}6Grj#HEN0sj8U>?Y4Ke~k%GO{zti7+*VTeOf+Ks+D^up>OA4 zZ=VDzMwWDZlAwpyg;~R5ym#x+@0RvN~+NZ=~ z+I5Z)12p30jI<}>n`>#umd3t5 zTJoh|$#bI%%{vSl{9~ z!+58xpy1_aYiAe7Zqk!P{W+VIiIw$s1#j-_*9y3Sg?>EN<8PqkWK!G5B)zUr(zh%A z{UF?Fs@TV;4U`r}&1wqO$U0TWtJ9qu0JWtq&-TbjNo8PGR#sYCT8anK?Vu85T|Ml| z`P?1d8_zj5I;w0d4#|6HbB#bla!^>nZvK*+8(drS=xAQX@({r2yVFj~TU(MKtrKHj zPYA>6ob7Z?aB=H8Q9E~2o`&J99BLhwp!tBWtU z4!RB-or_y~%4cyT0ecO1^$vTpundsG1O%P9GVvUR2K`BG3{`Nwi zi1_*Qr~h+mA0MB%A3s`JTAmGnq~+)18!guEpSA5#-Wo_32X%s#g~b@|kOHbq_Bw;7 zq_7X7oLE_q75D%%)n!K0AMQZ&EHm+l=NaMVzhTCln6w}K^U;syeiTxF4poCwiP2#9 zC2n1w9~^!C%IS7#OP&T=rj4~0D&a9VCMC6j?bc{pV@m3A%kIvUhk|*@Ilw*giG7<| zQC=_LP0O8;)Urt$MNF^nA3=V~g=&;lyO$?hl=)?5Q{~gWDBIHQD{6X-QHZ;jTg43p zg@u%OoAJi|^l9r1Ipm=G$h|iW%KsgJ@MRwi1KT~@Fx$iBlL>e`1$DN=`o~d#+r!DP zum-?X2CzQ04C?gHg~n1N?O>9r(8PrM*)@{7IFzX3je-I>O@|Z>HWhU?99|IYhoEBa55X+~l1juFNGNKwz z2U2|73ndAhB&6=HZ9!-bd%L@XttDEVislgxdAyiHTnT)`cBqnRuu( zcw#lRW98U%Sf9y2({L^s@k5uo*Njb)^6AZ z=%~(FDPx^fm;_wmeBR_cytRd2)u+J_Au}daMmDz5NoPqdt>2Abj$YHxxSS?LN82a+ z>FP1s?_L*rd%H}PYwu0k#rdH;ovW_8h>s0sWhGi$UDf_@9&NVV&4`!CWfctc6nQXl zWMmsiRfxglMOq6s7uIdMRj1nh#PGRl3yZr8p&5f8@gf6r}N z;xL8mB7XPl?DkMSM$Jjvb4vuw-h`^()3u`Z_S;MC$UVL4J#l5>X1{xb@$h2a!T@0s z97Jfhq5Eov@b7rx;X!0y1unQfR9mTW_RZgOW<*3pWMpK}tCwTr;f;N?izTZB9LxWt zV%8U$uao$*Rn@BR&h;MhZm#Z<3c=9PStl;t-PNVvX{_~3Xi&R6geY+u^nD;9**QN~ zMD_)E9{wxV`DoR{uVZ3DXSD|{o`b~s_Iji<(!_85Y%cP?3`u#?N8vg z1#LL2qBaz~vz%|t1QSApUxqq)ntBCksf9%s11RzUKp;NarXOYpVI*2@xzLm*8VH3# z?YGC}y+%H}&r?Cw)#(I0Tt195L*sZIx|chf;cz{`K}_tmwG~mMWn?g&b_39>py2Q` z>VZ%aAW8f|Pr=1Y#_?x(>K$WkgMl^h1@U&Oycdwc7*8&C@{6ON$yfOoJwkX{^9PiP ze!;!4AC6b+19Z=+P$MP?G3#7Z3bM!MlY=*La7LCz$Z3e~Kihxw%yGg3h9g8yOf=&0 z=HXH&)mTqI22II$mR5g1DrrJ0c(|~a0O((_=kyOC%LN`D@%#JFVc2*v>nmj;e$}=Y zeT^v#-(SgqCQnT51iddlO-vYz)!A?vbs%%#jZn%JSZws;EsH_3Hp&fdA%KdOABMsDe`ycF}tbZ|Xpb z$^DE5a+#y%DdJhJ)6(K17CE_WG7rvcxQy*F0a-G$%UM$7YdjQhLPC6hWI6osb(Wex z<%Ry|lSrfBu2RdAGN=yLRxPB87RFJ`&JZ0f^x>@F9d+W8*j)+}+~S zTmWTkhYCRV|DZMi(*fA*MuP1jnFpRWv~fB_f594;hb!Z za*X5CRJ3Qc&YnD9@2PFMv+)H^(K7@^f?XqU$Q(WPr$$`+3*;OzeE=Lh+KRQ%a}b7?2& zer-&$jYY#bJp^ea_~D5tWTbRmJrHHfnlzpkj(+KckXKHl$>yWlf>g%=S z<*mvt5jDQqEkC{zY(pf!+_pI_wDDEEKmNN=Y2Y}(qy zEavJBVgODVOY@eut9h94ml-q818smKUu6rS(i)_;<@r7tAfi_L?nDPMtaFy$ zo3K%P(?m}cZx8Muozb7a8O~gjkd$O*Fjj?BhhY92^;=2^)0sX_=Y^0G3(ePLJVmIW zpvPc_gsQ5ln3!02c(}d2J*U2!GxClzq}Q<0hxOX!b>j=Go)_SsG?v z&E!85LjS(MS6mX#2eanYSRD3CMpu+d7Yhbsukpu^FR=Ur0s>Ic(ER;$et;QrbAA11 zG0hht%bm%xo}Ql4(oz87eibtxNXeAwuT13~Y{Bc>7yQ)%q)($bO&Oc!ZY zD51A4U?ZGmA_zIH%w{epui$+bM{9@(2nh)Z zB_$;}Vk#eKojeiQ0U-*xQ|hcybX%j1_3}8W;FhBVqnDuT`Onzc32-avsZTkeF%3eS^5$@yjOV7({Xy~KguXqNYaEDzfm`y>Y^?7oxFBh?ZKyD8K` z#LrvhjX*tXByi;X>YS#_+Ne`5%Kil`iN^cRn((gL2VM!k{KY?O33ly+_hQ_?7azQr z=lk_^Wue=9*4$DSXYKY;PC`Ikz__2XlbpgYO=SR=A&nA#R&qqN+=vNS0^q`M z?k`MbVfxu{P=F=`+4$Zh!-dL>p7&HlA%z8u-=0(8#s?^xB49%9&s6IiVCCmSd{`{_ zIzjN!$bB;BLDH?{o}e~-kpzGmf`dmwGE<~kGg_#wuBHZfn{fJ1_*67B9mB)6yVF&$ z?|{T`-2Vu&!oTZ3Hj?T);8r`cG4xUHgk~4F(^5SVqKA~M){1UMX7kU90 zZ8h+b)YJe4Gc~@)f_ikYBu+v?Qttl0X5Ht}&hBn7#6r^mv!(vw12zs0GwRXpjSI+s z@9o!q5_i*8=bME#T#xh6Ks!x&pCP^^7D`%YF(&}h$onatWc1ehx?jwre+&m0HrCdk zM#DpVwn2_yy|I5_2g*7mFH0kc*W=bzNXRoXQbAc6SBZ&TFtk0;&+kQAAReQ$vvZf} zXlJL<$>s>4LSH<4_~=npW#zE!S!(&Sc_C?F#PdXn2(kj50nl=rfKGbz=4)_paB_08 z?aj_q1(|^Bcu$WhD2m%77A#wQ&c_{1_YWv1XGNNEiclp4eHcY+3#6DzeL$sqO69Ca z4o{Tpt=`7bWPE_D);AX;mXm7f5hU+^4pJo0)hNqZ=Ic}-Ywo9@=e~tJbBy8Z)-xPAsQ5lAPTu3=D>H`xxsIb^GPdzu~%lfk*N~zB2EGMv5^zXDgAX^rzgZ-2h{O^ohL$?fOdeer%5u) zP;IP9D;?8A=6OKu%Q4cDEm7$Bp$mBf4c&86J|Caj=OvF_^R3^=ex?@AiGx7}-$K12 zfJzh*jo0ZKBt8p3QpwAwcXldNFMnOqM$d{GdXt^X49MHgvEsSHBU0ZuEd)sb@VKUirF%&!omvvG*I2})Kqsnbwe=0$c3rM^c^)e@@r{r z?at0uV1q`%nRmzEky$=RV2!CiT&4Gqj5 zctC#{t94+EA&F*XF$QkF>8_~rru`k+Jc!a3G53$3#78(Jq<8f|p*uCfDn)b8$%);Ab)XgZFneKpH}FB3xLjnnp*X z``3KEy)g&2C*T0Qz~S)pw6xl~I)B5%QvkH8ck*F0c?4vZWqkob#-Hy1Lp^|0AFGO_IV1_yTx@bgRRl@+}tz295_x9JMq*)*k9v>h7orwF@%8W%}6&7=(Y=(b+ zFzW%PAwxZkrt0Vwj?u+UClN9T4yU{_Bom3^YOUej{pE0(HBxmy+n*9%|19 z6^VmmM_2C#XNDX?>3t9N^Qd0GHeGD-PfbmwqM`yy3k(|zYp_^bke9b+f8P@5JHx|@ z{QPyK{LZ#JlkDW=A_F%!WMH_Fm7Ymm*Me9=){wCt7<+DstWVeN)?-N?K417_k}go4 zhr0HD3$ZWrD;xSviONIJ2NN=MElMM74(OtJWbu$8(_imR6T^X$Axj83FN1(#DF^Q$ zp^e3tD9Yd+HiY(mrj&g7Vt$Xi8QZ-of+s-+M;7+xy@X7w%nN{7H7TvNg7c?{fyU z)7z~8S9hP7v1*qyYm=Yyop$ZP>c5$4!Q>8~Ljn2@6Q9olzw_~TKR_w$Z0oPDqcXGE z9suoZQ%N3;1KBPxyip4)dol)skV6W(M_+fZ8zv#46byrG6;Ao;RqVakbW*$p_|Inq zPI;>EHumwNHo; zYkLGc*l7-AbUsE4{z64nRAZk=mA2GgY`?dgo5|kMV>%s9{v={+bqx=AsE&7M04G8% zqd}eqIN9y(0u~n1s|zy{foV|5gF&7p^AVVS{1aA~vaGmdYb=^7J(|87z6_k%Hh~b! zsbHcr_ZxP1AZ4HJNdadWYEE&zMJ+d-`{!qZMq7ms65nS9{9Oc4n4;GU}e2yneR`%1yWt*Gvo`u)AG>#UE z^E#B{v+CcE*uLN1VW3X4noVA|v?RA~QBh_-mroYZEY`XS^cyXl0-9Txr{|197MIzK zv*L?q4BEGaSy@P!8=ISKCZp#UM`HnepJ)p;b_*m~=d64;2tTv14Re6yw`9AbnN5)nybx`26X(7aGSNWqM{ohBtJq} zNDpM0K+D!YiY@FY7beJO~S?o z&80X#Apzv9j){rV`@;?3g>l&BJ3O(Yg!0z(NkwnJNYkq0`9;F;+BH7%sA*t8jk#UQ z`=_8Zhr7gT`6ha{L};UqI~Sy=u}Tqw9vCR~?p|l1hxLlN+rQTU$cx&PdFf<< z8Nc<;$TwE{lMNm#z(v&#SkAUT=@-Z7;I$oZFCRy;T= zfy?c=9xEp3S!~?giGCoaxSS3zffWZt&DXEB%7p>uqucqw@{%gzBAvMT4i-$b1?Mhs zvS|(_lL989sVN7lG$3z({`?iZg5TqI^G~WE=*3R8q+(*hheuB_NNb6o{j9N=n{aY^ zv}gzJ90=m=9bUMBlx$M1fXnHR<>g~^lAbsYGeEOwLkU^+oeT}P0pSVEr9U`!@_*@F zz1sbm8#lSkp@D?lXmro4DFHUR&f`wvT@MSeD8Pn64m2}?00KQ6kja8q1sgy^s)W{}fX?Y5RL@ z?9xtMU%SCOiO%+NGig**LNPISP)^#OJXf~cHngAj^k{IOx#zR(fWh$Y*3F-*IT(MS zMmk>E)jbOi=f|X1J?yP7b+X6zpS~l6gfLLTJ@1;>h~<104~JcEa(6B6O{N`Gw&ec^xL>G6;64%oQv+Y3eib1kkaB*+W0#e==PX`x_1j!DqkyDN0+rKu&#;6(Nl z6B|2ze6Wdf-$p%k-wN*GK=RP<4?(6BYaZQ z{QQz?;I2X^sn6|3e}!RA<|cnzb}!c z^DUk5rNi`4P44<=^w{@1Ukad9E>ybez>t7?#+g?lyk)Yg9eg1810k+W@X zdiouK8c>$si0Bm-X8#OhnXhnHa)0)9E zV69VCt+JTAP5xAzA+?MME-FPbjLA5Z-}7DT+gD^B4-e14TmTG2W@g#qVo7;9_tw0eB?aI_=wdK2zICWH?o0Rul!Qe_ zh4)Rxnl;Zctyt)H+>MOxq2Sy&d`%n*cv=VB(&&ldu$TN6GXX(?V4+csCWk-H)*cK} zA|j0sxBq?xHu`u*G6{mX%lOB3nwB2pdXY)bOGBp#m0*eV2h`ExBK*I|7nhgS5hMSd zH~sGS54{@8NWE57W~Ux24NSx#Wc^DA&gbW*aRP2``m0(S5!JjDI8C6mdge84D0*IU z0AsGr+Gu;57I2CDvRTWGhzK2|jH-BnjdFEX@dQIq7>ND;VA7+_bGmgk7HY%>Rjr_a z4~pdv>)s{BrBP z-5u8AeGOorx25&ulQ1A}MdFGjkyDJhpG*Gj0tfrCEM*ZP)H*Eak91|T7ik$Fa<4(j z-wl8FZ>AeU^EZkAwbc+161$2JIWAC9=F2C0vZ!QUMrltfU6g4nnLY%TR$La1lbjK1 zi(1Njiq0{nEApairCy}UF1-X>UdICfLODNG8Y}#|IH3DFMXL0!SFF2bpfC-eT9xKP z)7~a8aoN&=7D9tt(GMO_03qIh685YP<6F8Yejv5_c&H(S z?`7QsNCz4VvEp04gC7xsUc`Bsv=T)TDO3bY6#2OZ&dnQ&Mk72X{mRPc%!-p&*5AwZ zQYgTnDn#Nh^5b|z{$R>jblt;3`{UCCQp6R-L#zl_dZjw+8~F(Hw+b!&g`_w8&FDT0 z61Rb&4f3t`pcQzY7^>tXNdAZC6lQyO`@ECheto|e=+#Pte$#L5OWHu3q=ew-zGM?y zJoT2OmBLj9#7ABqmj({q7#Zb;4;xOPm8-j0Ag(m%D_AiA=9P7A=>tRC%QXMzzV8w@ zq41D%bzcl>m{<}DdQzMDcR$?MmK7z&z!2{Rbf^-`h4Sm`7*i7ziiu9bzYFu+AI9#o zMO%^PEaQ@&xAn-&{v8s)+fk&}WpgVHVz5wYVf{vu*s^O!jh6e~PXS+#i zYF=Q=83}j9i`&uvf_8=eBIM;Y&e`s6N{UZBn1C3QnU4E!w%Jl!IIPrRkDD%EA}-FW z+CDKMBBIL9gt&PhmjRU(oPN$-S8;d`_|67LN%_nso$Y12M;ZV{;Ikl|OloYjF`M#R zPOza6rdSlo?t`jg!>Elb9g8(xvVt$&E8NzWP9=ld(@mFSWwOn*r=m@-(_lKJkI=kd zP(U>zZ}8w&YIR=KZjM@U$?XwjnVgk%?dB@N3z;!c)KKAVLo3h27u1b2VHq5DPv| zOYg@DFSsOtQDFIVn8l@MW>(p4$wO(!KyXwI#~mF^U=z7mjTQ`qgp9hnw`EEDlJa%P z%An^<#{&rRmcsd>Wc^@i&2B^%QuUkt7V<*D+L{NGgtxp}Pu!+FLzDM88d@*`tC;)U z&1ncpFQdkI4v^3L1@BnRry(A9ov>2CH-SKzu=|(sR_+g}v~+O4poO6MwB&z!Zr$(r zV{b-5bp>ni4=UgO-??}vMxjvLB<^NeNl61eWiUn{BA$IWv7ab;3sozljoYySf?a?A z{DE^%;uay!2`{GE`20|zI?)#)L$etlKljTGm5s|}w^24AgefSbTP^v}tFgTV{1fM* z%;;*4E^*N+Ff#kE`;t+)-<-?`6B$^{@)<052vAaz0SyjJc!Zqxr>9yf?+*`7caRa0 z&NnyEhDJyxYt9OQsyaw%>V=C-5A?X0$Rj8_d%m7HYdI4;d-rdhtfJjNNN7H%0B5{h zz{O-n1zTat@R%+P<@hQqFLZ)`Gw3imGq@_VtiBmnan zwMj7^{{a3H@V?dKjSQJYs+sDOkAG4ad2E@;(|{KvGhX_y8N3B}T@CbCk9Vem z{ea^Q0ATx_$yH#Qb=V6)MqU4nD>*9Y>Ie)}VBbk$ZtlUd!~$?G04JCXEF!T0EvR{9 z`glXTH}T2_7;TO>M{-@x>_MQi>IYqKWd8uJVJ^$YhSJjQtztyr6LsDg>@^wNCFa9V zNl#zdshb^Q%@7TwT9E_Qx7FcIDih^OQq7f6svKBuK%08qml%0>_l4hH zF+)ReM1(Y87^1kvB?^t><69@oDv;Qat3T>>rp3K?DFb}6(JjmXvSe`lvo79fd8*6x@U{A~~H)LYj7+>?aR z{vW`w-E8Cf0pf<)MvjD0o$1bS*&t+~p9 zwSGbJ45=2g$qBpFBi8rtS$4L0;FK{8W<2($Cx8-~u-O3zfUo>R?UvbXMc)JJ9^;0) zq<1iIn=Ut~E%fxr?dd^6tN_v5ps(QMFv1Ovk%O8+2MKFfT*UCWIr;f>zp&zr=QO!^ zuOGOw?yir*d*j!B8pr@I;N3N=lx*>rsHpoLTVUq^86F-RSSLU}1qR&q&(^c@PJcEq z5QT+@&s7+Ym^OV=x;oS513?B{HwP6xJwXIMPo7MO!$56}j$U0$c6fFMo1R?mlmTFM zc6JMpbjt4!e}VZ8*kildr~Xgf-raU39Q(+1&iFo8~ z7_IdwfK4LY))aqc-Sq)K?{=jIY;HU+K6W*J0Zfo!g#z^v*w$yd0{&B0js#l+fRRcz zvASG?9oQ6r`7AI%hSNC1KzH$Sdx9=}{Sasu-?x%L^jn$S)nxzG=~Yiw&y}WV6yPMq zztuMFzm1rA(6zUwrP-ZSM1i@wUO&*1+Z%#<>&l`OD*M&o=kYJxdmj+8+0PO|{N4yWvncH;#c z00Aq<`FW7}xEv?&)uzk`+Ztr#Uz`VZb~qAaT3L@XsoNakR#h?jbxgUys&+fqK76VE ztz-p}qqmr?^*CoDi#b+&dfTBaYbWl5L&N2$ZGXxtE1R7qO*A$Bj-7*}r!S=Na+512 zPuCdUZOx0=ZM0e55H-J;DmN)WXV#wgRb=mnB-oy|VDW!XPs=fG+B?h7oZ>;S(bwK9 zDFdQnNP|%}P>s$v6fQ@MO}h7AlJhMwgA6^TZP@IR z&7P*{_Eg2l_wswTUK#hfWC>otrjM(;?A7r`*Y1lNIc2IBY3Jv|Ko%>(VPm&y`uXPm zGDQoqA_i&C$aBUhvZ<13O|njtMMqBeyLR+yxl$#?lv3qBXt*kaQUFlf>2{Q>bCalF z1>}W_v7HjJ6b05VmqK%1^cT`J*taH$w>M@@&9cwrH8j!y_kOvDt#Z%MqoX#xVx{2r z{MT+t?R;Z4VPSI|7D) zp~Mm3(rwlH^mIEAn6k+-&L??q2lx>fe!oaS$@v_iho7_z6e+5?x_C`_X)sE#G_0(Y znNO5-coZrZa+svF&E%*IivKX4IPh?_MFwxS|~NtXQ5DA(B^EH)#C;S z2W;Pj!x3w$0|T3PXAG{dr?JcRAl9j?Dy^N0@$sZ;<)&EJ%ivG0{Ii)C@C!TCvPdc> zTjAl^Ja#M?C~=Z7us;zM?IgdFf&$4p7_PsSEMrun-`|UyqHnneU3y#$~+S(-V=DdIT!3-@lD= z-v1co@?0Gr0ZYo;6Te&eLLF}MbTKdr&d!o^m><7POGv=`UxBZ@2KWDpXrt4YOrg~d zj1Db+WPXNiL2|u!cU2Px&V$D+`1URZg>=-#|exRKuZv z_86Ft*lbpPvZNaZhln_=mqP(rU8KwTsay;O{KuuXWGpSRvKAoEu1xIyG@Blo1 z>&(4W-n@@aa!D?5i`2Xy%`o%I?R!9=U}e<>ry-MV$Fqh--3erA?|&_tS>)&D=*y%blFhKQh!!mC9yz&oeHp%OEB!m zx%itmLZ3g6e0yR72EgXhKhFl5ywzD)tlx+j5D;!w*C5kt)zULF12a(XaH+_r3`R^V zE)8_wrCovJ{RJtNqG_X{EG73_1&_O2yWv+fY{w}L9z8#p5%qgM5aUEG?~wt?SWEd- z|LQcu>8PHFXSi$1r8$B!9D@{lggS`OM7?@A(GLYBz|Bo_Xwdu-^4@33mbKj(1b4D^ z;OGKo-o9@YhT&4Ku3cSGyz1q{Y@D20b)558t3 z@k6w(q*}17l$0c!Vgb$=W21@Ki6ZypuwQyAgoK+Rr2HSpnexr1LJm#9KEaP1K$>7< zAGxC&eodDjHf`j|CxVdicr&(hWrhFO&mT>uV6TkPWNCO((pGmjT|&b3kEY?_`0GS4 zo!TzKc;elBJE_4T-o2ZA9$sCY7amUP!D(PH6;00`8F^ju ztmk(x(tu5%%p`jTs6l$|4AfM&zZWe140qIuM+?j9&;KvJ-U2Gic4-^FK|)1oP&yT* zk?t0d7AfhFZloKfB?KuE5R^ucmKJGAN$KvAZup1C{l?z!w|JR1)`n;<&s2VY?HIMo%p_At8UJqOvi>_xuOL00lx$--D-tWH zQC@x`JuS_7v3798$jP)d(9ucm>l^Mo$Wvc%cjt@dMMdN^q71s97;jk& z7d#f2lw>~qu`yPCd2#9&KO9KNG*Io#`Llhb@yzJtHo$bR!--0s%FDkv-jQ*t$2);bLsvGy?JMif9P499JwOFxwkv(}5eRMr1FYkR43H#;i z!1tDi`EIv)%7#a<(6Agke!!H1^t^rAulhmRmmFKYfjY zrm)s;ipFl7X4=!^id`nb+276qS?^vIO8D>0YR;u z^XB1JePn^&B^^J1AymD+PP_lObad9p0)UAI8XPL>i>2)R{Mn21R)2!3YOG3UrbEzM z+St4b$u8%UeWJTHp4fTD?{TpD&Hh!e*~wlwouUbAqrZ+eY2fV=>huiR3JSsZCZ^mh z)U#%SjoC%znc9zko%~627%jzibTrZ$W2vp-f|6Lli7K&B4HiH(#Z0WMYRf{Kp`I%r zANIzN(%!$np`uc8o#0W$O`Iylw&E9f5IBCfLPz(&*lf46x94$Tjv;y$AMHRUZ1hoy zmA)YDb!OpEaL0l|st`RL-Bc^xGZ`76x@p>V_UEdqnDk(#^6oA{)KPAhrmUf%t*t#f z!)ADS;ppuRN)*(cLsFp{#j)})z!2ef-$PL6e(8oM!S)at2TC;4e`YwhCcT0q6cnCR zn+EPHCA+-Bi{%W~V~kBoHcxETl630i6 zisKpW<86@9Dc$Z8p!cpfHz&tBU+=oNic&zUB&=HeVLxL3$L_wY28kvekwrU9$Wahl#UEMhOGpRl| znHV!!WtR|CKqMOR%jEGjVHBE7ML`Q=mmOEvL)4cy@9yrVMvzro3^UgYc~w2R=S}pQ z_cme&J=_jKxs`BlGmphrZ*2D1s3m{ejz>*RPnyYaaTbP$Ow`|tM=v(h~ zI@=yI92iIrBIo@A9dG|265>^6-E~kKt2OLn5D+==Al&@t(Gc^)`)mA(x4j*-=a7%e zm{Jra{MVjcYXO2P4}^r8e;9(8R%@vn&v}DSRATTDr{+*vu2Y7NPAl^{Ec`HjWj68= z#)yB;=IfS2{e7IZX^@kW);KUcytymsu%?DfyAl^d$eEMm>X2YYbot zojlgk3JW&rA}+B>jw}_AQP!X+2(d$IzRCOHIxF`rUJtI_-$fmAA;rbGIJ~?g-S78z zvz0-dy5)R!#7CW57x^(i-vbu9&ho@WQMDn#8_5XY{2$NlsSno*WuYd01N@hG;@{EA z@{?)??a#cIHek`8Pit`b$VtE4688;z97vuKGon z%vztdP714s--VnjTMQ9}n75-gvYle5Uv;78bD$j@^Ps`;I$k*Z^1Lj8%X+@bsUL*5 znsY+8nB!$7s;c-hG71x;)eC>_@4ck;Aw(2EMv`i_uN()OIQNO2$xC#02Vgx4-EXml zrP_(&k^7$S{QOI5!;-Cp_s*=WX07ikEVFbpT+L>i3@`|-%#{KVlt|061c_~Jl6Z6l zH!#A6hi&iNsR#{*HMqBM%8I(LS1Bw)S8Yy+)@}>O(sFlw-IJeRmilLRcS(79)Z~aS zytWVNA(4^5j6DR#E{Tq~^(X#SR!IB+2+7Hvy+Q%<*7UtAv$F8Qn&0y}?!D*q2+qDB zK=wtU46>y6HuYKRKIt4lsmoCz%TjQ{XUwU?x-st2)Z9EXUMY7!NLHqDb9R<8B?@W& zjaYanI~!XfyJ>fhN_c77FFzVL zY=t4)=juL>w4MZhtGq2EU)w%o$4hGSd{kat9o<|CW&a0mR@GX(oNIW2#B24Z$iteC ze~*qv5Oe0P><@4`eBuJ`-gV5$timY;y?U~G*87XJKye0XPIq^48r;XXG%|%iFb-hW zS?xAi`r}%2Pj-B8;8_M4&OrRLMcqLkw3s(RbkY%GvG$x1`dVjRk8S;*r#k z7`rTa5?zv^}Na`muiv zoXb1xj{OGIs{`$|5n=cJToDLkq?4yeP0L&L6t{?qr6ncZX2jwl2Bo2n0Ea9VZWldJ zc^{vy|1Nr_r6n7!TxNSYGFmp-$yHLd0sOeV{W0s2ViB`yq4ZBN5XU{Q9+DMkxDe(# z#f)tA*iL5@zRY24x`v?CF@uZ$^!4izsPf@p9JEcQgY=Q-r|J+TuN-U$G^5 zTV8@OPCQFt6ZUEgi$(z6m7nfBms4I@F5NqDHo0(f<7L179KJ&CF791fM)}TQ_M6s4OauS3s^ajT+981BD zygD}gp>+;^m06odcYen2rB3w$7EUEMQ!49nb;ltr({Ma1xpcp!C)-fh63rL4>uacG`dymYhk-C=;^J;2- zw6{k-l#{PLUhLAMhH;SRWch`q?)TZ|1Ug>KLFdKe$L@xqaXq7>{$1V2OQ}B$8c)_I zJObfb+g_$U+SdN|b)_lfCD$qFgocB&Yih*CagY(xxF=5~r;m4^st+T?8@B@k=X7+g zr3kZxhYRk*qYDq$f!yUsBNooDusbgb3Xt60jl$n(s}+p5litO1>}zk28*z3npQt^3 zH_(mL^huqCotn>ak$#tzmv^Gq&J)OI6H;sy`h`A=!%C~Gxr>V}ox=D1@|42}S9Pk1 z7v|RuE;dF={5ux58)F1WNHE~?2J>9LeCe_bQ?k1xV*kP*1QP=L8;p| zBcVT(pBnyVZ)azAcNg!?n>~n_FBjq)L24`HnGh9MKG?$&8Vp~w9V>S-m;vfL)}OI! z(b3FfV~57&V0rcS-Ahf2CB*E^+FEWw0iX4AX|SPjTAQt@<$k7WzpBBv-yRb$Dq18P zCxQDb7{{v_Usa}kEtx;&_)@p#L7qLg>5?}jSIZ~+KE)-wV6-(-vDNw2Kux0b<;uY) zss8o#MM(+L7YC5Ge)G93N=RRTt>$R0aI7aKc5mHWP3yJ)wz0|NJ!*FLS74-u{nq$S zS1c9ep}#XaXdA*$5(IcPK8PauUjGRDxI#+j14g-L%F6e_s7OFgZX6hg7fY!=Tfgnk zAn;*e$h)fX)Ze^`3k>3rwke<0IHr0WWr!Bo*{@~d!YLqz=;ObEjUn67z0?zQ`A7Vj zwDgD2(BfC(g}uEaPMu<$oEuRoDP9+6Wkp6CO~dYcdn{oFeg2P^$$EfblF6tOWe zTXT4zGn`*osCk*=p-QlHyxVtv+SA;U;^0s`@znqg$IbQ4Z-{48^#;pU{D+I*N7+!Z3!#bwE{DdZ0)*pYqtu3qlr zh*C_<$&RblY;&~CBRSc+C%FS)XD)}&@-{Y9INPo@koE(s^5Rcgac(Hy-Mby6uurQz zKe0a#{wIpUF9<*&B(hJwMI5>MP(M+OoVRs#vxX$@p|CKx7|I7>=~1UwI&ufR?riG_ ziwxN|A~rkbm)*BQOyl)p(jkvku%z&^cQ!S}1_RNZoM>eXiXTE=Cd;dN|IW9G4y?k}}_0fYRzKT52@S!QcQiB$R(nlKT3!@A$ZXNBku$=-*EdDIzGa zW*jOB2(mai2i*iFW9V4!;WHpOh%V-%?{imBL7tJQ@Vm4$sh|L}FXB1`CHwYdgNMgE z9aqLpY}TV~PHUNZRWDqWu>|%VsMqzMj3spl_HCp7TXO3Z92;QxjJgtf>O`3j~5w89$rvP^vpYhK4)tVR^8<~?c z7D~W>q-bstq3^6w?Of>BaCE%OEz9MMKpb7?)sAUu&C<}2V`H;l8+ZEwp%8c?9tt@pi@{&!#|!b9 zj!QN-ZzR5rze9mH2WC2tGhsFDI5-eY+<+%Wdrv2>kJnG^&)!SJA`RddE67%>jtSji z9)~1~_G)R(zF41bsJ(S-R8`f!=`NTg4q(pByl-l6cZSVSDjb$2pNhFw&<4daDEnL- zA4ZV1+KwMp6c>jE*PT00LuENPm*>WfJDGCF?}NKjx&)lpjY2c?&)CAde^!~An0&WN zN+dFVF%k3Q*wWs4x=dofKJEoEG=?( zU2A|V@JKZ_Ufs+hmwoK{^Y<@a5cKgqR6=26qg(1aWrlnb(lqb1=;)`)zrvEZx7e{Z zHauEdQr@#Kjn#TI^G71RN5*@Ez$b*7^3^=Mzms?O}#DPj~Vk$);WE(5} z>cPRSb441A>gquhKI8k%cOF9`dPUrVto0B|CltKV#AII7yu7ck+@+q#>Q$KczYo@} zr62C^f4iC}${rsRQ&=dhptx1?`ZdBkEwbkU0|SMvt?8nHM3b2Mu}kbEsl&F%YBjtGqAF<02sl<;+vyl)HGf+G+xJ8i3Ea2 z0ivQQ65z*lUSiq^(pnvD?P7D4^y!o{0uhNi{NQmN83e*y6myss7L}Wv%8XiE1|!8c zI-Tvla+joi>fbp(Ejjbza~T3RN&MWO|B<=YeHATzZ>c2>!JLW7=IWqIxz%yk&sB^Y zHHMD0(Fnw>FR6kWB&PNbJ9Bp5B;Lh2J2r>Pz&iW>%fP_%VLTlCyFAusM-<{>vsErz z!1{Y)FNG>UzqQ4(fsGJJk7{hc>Etw+Av-a$PD&nGVI0DL|J?8Bdbd&bD?icd`is%~ zoBH6EU=Kft4X&f+K?wQ5rgChkJN{11ZX%Rh$V`euG!^Q{qq@8TWhpb5`l8$3$89wUg#q93lV$QqM(f&bJL z5yjs&LoA2mP3Auk!j*@8e3NpYsy!7y?Q?i)i>l({(H*rv4__MmbCzLNjZ;KZS_CQb zN;BQy(5hN(d$=BTLM_hwDTIg+tg}&%8Vv0GqcjGj1Rb>-w8MRJ-hM~&)fR^PYz8E~67aA-v)^#trl|Ye_~J(JJ-E(iVMmm z@jl+zGCLDCc12LKu(A*!rhW7ya`WHHsWD}$H=y5WLg$6P45Y^94neKe4>qug zugS9eYovkE&EiLX#nnHA2;X&hLU0w7KE3fb5uwX56FJMasBfpINSpu3`bBo3l)5tK zPzi$OcxU|mM{YaDFe)f{mz7ZwnovjlIXgF(oSY2mN~R5w)qBj$3ZqnTJOqvdPtM=^ zON4Z;``OWUZ<;u`prC+?ib_RA zg+a)eZPWvP)}5Vl4I7n?OM$OnLnPhY)FhWGlw5BLS@npOv#~MlmF^Nx+1mBkn^fnSVqjlF4gXVKepKHxfwH*Utk#os#SF*i|-N}Y3CM2^)^{XWO}{YZ&{ z;ujt1>FMCL2B9M;TCJ_E8$O|MgLCMYjEsBV;4f8W<%WSz`T5$as?7qYpr+^KEL)9j z*k z;g9RnA>0R@acEd1;AZDzw($ViNkx>JKbyxyLZWE={s9e}7xH@wQcNkCl{u1=KQrPD zS>Sq1c@!lxjZ#smZ6hg(8rcf35}wqV>EOUX(_J>-(!rAO+w%6sCe5K_OwY|c50lRu zgL>#8)yd9YmK1GZx3t8#Km&fNbEOoPB0(&bi3y%!N~eB={F4(6Gc%rxiYaE06MBw+ zqYyr|dKcZN?{#huLc6k)VBCqNt+naEm zl=#D@4$Ese=ljDOkOWQCor4OfuKV}5+DOIacMpYis@@S0lpResP=tl*N=T6E)O!a) zp3(M}%j2-XxWti%)Mlz~5kNYVC2X9?*0ECa6wozGG%1_w-cb^Oiu3VrAgO>GA6OT{ zH%lysnKOG^TU&qr%-t+~6HHA*L#OcJE+JuNVWD2@d_O?APHRId z2$1&-bN?79ZCoEQ!oy|8{&jvD32jk?X=t>-S~st-4r+@XRy@4NIoS`Sq*(fYnOC~+ z1N?bMqST}d9CyQY3JRw-!&u&s3(|7|AnX*HoRZQ-YkYp{!obW7fUtO==OEPjxcH?s zHFI2S!2-oH8=#n#-ZXjR&xOUsPvL_0_Jm?q%a8&faK0Zre;5=JA_F0bk^#&bb{eV& z53)}zw<|!Nr|ngYe5rZS0!+gsays7+V&!xg5Q@pm*UCr`6E`MCL$-j2lay>^J|ZJ4 z`>GynZLEzyXMO4~{ygs_+E9XYtqSkTg9l*awY3VGbkiPP@W2AwnEw9$l_cAfdUsXt ztP668Es zAx?YKE(ykzMhNVk8SxC5I`9&OF9m{v!5)>S#-LY$SX+(wAQT^(5L|{Ue*M~)NsAEF_HwCp+YPViU@hJn$T7-OW4d+QNs|#E zh|{e}CSYTIE$1pM;>z3_Yzb_iaRBeJf*_7U%m?IWu`JxZv@~Kn4r~ke6h?k6GYoya zwp}N!v0o-Rk2*w%R3yd^h!Dc}OcXYY-meNz_p*_F8LxKt>L`Xb#u`opr4tm3;p1;s zlpe_aCG8<5KXKp={fW6t*dYo#LmTN;L6~xF-o+XR_K_|ksMsQeEF=yexIaS@ zc@EoI8^`DCV6{cFmw_x&(yZunEIuTpNu9tk?1k?`@@Wu{ghc4tdG9lqCs#-TaQrP=axnbTfipfvpn2Xp;NT^^XIzvpO4wrS{uvD zFKXQr*?J0|FBDl0x0hRM(b1wLB$4bM);lpg9xb{SeCz6VL@u7GIXq(bN#=J^k#2ia zQ*)GXxBjZilWIMzQ2q5!Z&OGkA>(iAZ}so|QL!=dnUE1(anD8@d-3Urb{D;}GBe!| ztQL!m;uCRSEL_^g{&%XPTVfJ9eev`C;qxQHk(rz|t+Ia)9P zeii%;milIMd3h)D$iw+|*)*?r?=-ZT)$M$I7g4-&5Do}Da!G2iwiz2sx?}}aJSbgM zRaL<{V^WYXY+-4s)kh7irfyP+T^kuYd=q-|kN9-|;Nr4wAR!?JtdRa@3@ei8S2aS! z#}V8oo^L8)C2($5sPgoFgBY2>D-i(NUsUPHUZV>gYcAIS`fa+ZB;JfHpwy@!OT zGGEVUI$m#ayTj38XMewSW6Z^QZ7AUBEi93Ic)`BuM`yb|OpJ_x+;>4OPVNJ%0rFLm z<{LDKSsQ|u6B!v9gIT#J^QO{sO+odzVvxG8th_}<4FVgRuFhLW{1T5(2no*PVhJY7 z@^IRZf8Icpz17B4SKhX{IO~GqYHVy!LXrn5Z}jMLZcF6lucjvX*F{JJc(U%FLDt;9 zD2eA@x!NF?B5*w2@JixcQj(UM8u-2nQ&+j~TR>|FU!-ew&>iF3H=bXfY6wJ=oP#5= zNzWw6KP)C|ww_lEJ+EN487++hCy(FXav=j=Tv%Wn{R7-hpI(*5_-F4XB}r)aeh&^h zfq@HfP-W!gUb?uL?!YbbaC39tyO*(5cWMJPB4FYxtEk|$cNjUmdiFWf=B@K}L^Nfk z^S7g;cM)V`fk8bGE-?srcBe}+UnzZv938PSI9lF&SM27JXhk zIOB{Da!v!ih?>uN-2tiv^z`DLo%d4&5=A9|B5YJd3Kr_@oK7n06q{=#R7H3wh>>9! z?BLun<#U-l_4c`{s?+p$KX4r*40~Z~dkIZ{RI(Jjic?OqUMwre3UnGFP^l_OH(|ee zK<{o~wZ6Ja{C#elkja79DOB*qPemIWaY(>olarU$NZ5=XFM~08W8)Ga2LdcxG9n^! z`?yf~X`DIOu=HN+jD@XwFe3~Ovr|(;2Ut*Wa91}K)FB{u6d)j22oC;)%P)$E!XPIn zC*iVkJ>1lZBo_=`2E#3g1A+WBy$z|NEkua`_r^QF0XXV@W!(VAogXSs3rvlTQ+eLn z!x9fViMUu*Y-J@S#u9N=f}mqdP9E2(kD`LG(Q(;)IEVP)Ml1?yGd%;t{-!mQ4O3z7 zhXNE?a$KJJ7CpVYsDzcXLJ+1kB#W`JvCk`P(y|T{n-s7`(%PD%LpcwO`1tuf+}wal zmT>%I1Z*?FC|p%lxZr}%sO1(3NfMZ*^z}V$Sdat@Y+^FBtM!nS_FZGZ>vf-lbyc%v zMky)ih^AdymYgcgQtN%LXEb+^rRbymE6Zt(5a3im@|>Zt%x+q+{@dPjs*b(AeGL?G z47~qrn7wUnZCsD~AY#ybx>NOWdc+rLA|$x0&dAg>CqI7=_ADq9M3B%45ThaRKY-z} zzF4`-mTrS76B82yJ^ivuZAM!=?Jbuwv}^@2UhOA8%iw_#-ii0zAG}k4c|nH*a2BXp zD)x$$K}yn3owCZ=Trb6X7zNXprM(lboAl%I(afyK6O2=)GEhqv2*YSULfu- z)6_C|u<>np^)LwQQdzZGv$AgvqDH{RD$2m+6zC`+X44{XLJ^1+aTRU6_7!dF&nc8@ zxIbrLSaKLW{+%X%2aA+vsw@x0Lv@prz!zIPJ$kK>LTY7gZGZAI`|aCJ&`iC0by(|l zs;gJOk*{e)$ar^asY2(g@y`4Vlx~3`MVAf>yyK$Pdk%B3tlgez6m1MTG#FwiDl%~R zMoL{=vPP8%bAgCfg%_`n2Z7CWW5EuJ?n^zFjL&#pE~_7Ip7;Eo`6Tr!;2=l$$E9Uw zd;0;z@&1ZlryC*{C7`#^sP}#x**o;xs|3V+9Y20ZjEW9^ zA0MBCsktcisXRfGF{nT%d~kFONX8!*`1&Xx z_A#H!)y)b1iMr(08M{~hhJZq;ss;gP2Mx8^fk&I#u!t0RMK|#LIXD6fpA$>~&JS?y znas%lg*K}q+&jAjgWG^QD?AX`?7+$iU8p+MRUDhZu`(n(eKtAI(zoj5k3pj+1O4PM zS;@3p7c}66a(+t`t-YqCd?-fA;I0DhEaev!G{g;Yeo_%5?f(QM@qR%xbAAqP{6yft zJe!?O>vMTmUVa}+8X?k}n&#gT9iKl7!;3D^S%ZDzJSyrO4Cw_`#C0cQw(4C5fU-cA zOiEf)p~Js1x|*X5*i&Jl<@3=m)6=!G@l}_=%!08bD3}bPQ%`EWnoFlY4=Hm{V-DMA z(5!_l&vK&gn=8cpWc9q2j;=%snYh`ld-n)0eMCb-{;^={0H9%{$mn7H>tJw%=W*Gr zfKr`ADS&F%u1&zC-^E(*O$)ETJS5@nroG}GIt{3N`pa*GM8wN{g@l^ViT+jaj~^!J zC~^yh(HdHvWjHr;Ql#4RSG%6cKYT0K307SYd-dLhUW#CQ_&08Ao1=d%_S!rX`evKlo6VL@HT3wQ7^3J(7@e`P}ur;TR6$w;GinEtx)IO_WC+wYdFcv{nZHwe_$sEo5qk} zZEez3l^MVdV7Ou23=J`B3a$eVOLkETVD+$ES2?Y{MaK$V&9;VMd$?eMS+lt7yT~B` zg>b<=QL8QnA}8~+gv7YmcU+vO>SC!25B|cxolNz^`6KKveqPs1X-DZwYIES>)$x7n zhk{T1v#)sfcy~tl44VKKH!D3IbXE);FQKe3)R(dO{~+<5JTtQxr4kf8Jv+8EY8_?L z6OvI;scmtOV@ZXu%VW7$62Jyj)EdefLO)E zd@C#2d@i*r3=Itx_;^Pi?ep-DZBBaq93EDU&cga01kAW_4t&-?TZjok30R!gvANOhF=Ckiv#BM0wPzu^)v9 zd)4L-5P@RyDv#}?3pCk!@dR9T@NpkCwzSMHc6q=yT%a8i8hNNF{Y}XTxivd~-q_>< z_W7$Tw)$K2A1W07s^37k7#P)gA@S}nk*m|@FOdtzZ=e4aa5CQ>fWeJPzDGxm6^R3j zFLio}DLa@YbP9C5xqW^`mj(yyFB>9?igbiwoQ{jjoR$aIHx(r`H4i&GZzYKRMP1W* z8GHk;Dp|dVaGTJ)B|%n+YORu{)TzeQy~h73g$rCDdaJlYmW(nn0DZ{LPtk_*@x&lh{2`{{Wn zw&EYGz5u(QfvUXRZ4v69?d`+E6tK>W0A=VVnW43HN^)|KmFYj&VetHC1Thk%0EpW( zxrw(i?%1@qwcWU#{K71IZIiszb(_mX&I@Wj@T`rDYJtQD$H+=ci~A3Pe2Mdy_y^tM zx)W7Sm+K>6VG9N;bykK_r_Fpluah4@QMAnS6L!gJxfb%^Q6KlCzKW9ziTT-CyG`x; z{X)RbtxX9-M+&|+1dHcg&jHbA&;;XOH1bM{=WfTXZ&f?V9swu-wXlIoM|G`=A>hv0 zIqVpvKyBe+S?~+-|EQ0LRk;*wqnAGnGpPKhHf}^X0pus(<<E<4%jzpU*13R za6alx6b3JwazKs&n*)sVvIM(khC42T zlHn@jVg$)gjd;+OkY{#h*TgVH++-f^9=7YfqL_il!@qO5z0W93j3)R}`JBNWT2m6@+Am=PiP=^qYNv>j$pl8wyWKz-zAK`;x9m9@t! z0jUCHom?QH*dn&o=h~U@*;I|DreP4`fqBkexo{aoy@pZkLo~0Ycl_#zu`p zhLqq|4N9>bt2*YbTki~M5sy%(Y?!LJIR%O+NY@JHP}2Q460K++PjarmSE#O~{%kEI(n4jV)M5boIJO#VgDNWIh&@*AYaV~3o92xSNU%xsM#@dTCFgsa<8^U{gHK74R6;wFv zsyBg6DgMTNlAZy9|0ArHK7_joanHMh&NBO#*L{RAeTT z-UUOFS8Gd4`U}}E;H!a~)_lV&>IU(jKj}B8d<1O9KSCCzkXmPdvZt)9EF(cXaY~ui zuJ-u4i7j<%$d5v`Y!ne>xX`Y|lJ@rY#k1p7h<5HU{(jnO_$D?My8Y?}l*`IaUH3Y? zQRbucH*TG}~n24w4_H+3VVQy0p6Rm8=q!BROFVtYuG`ke^P-E5Ok-*1hg*J}4wCN}#YFgCy zHYE+BzWdRJywIf&YJ72@6dNqo6j4(R2|Z`~`}(r&t8I9Bk2^&ci2?TgvqhJkk)f%k zrrcuz{Q`-iej*GB!oa`@P%RW}98@sl$!m&*Nm9B_C7mc`-M^^nY0u3z!#0;2~60?9ySeFnN9Yv@2X4`;L}9K!E%q1HpIu(&*}dGxSQE;{ z0b*fB#>5l(+Dda3!%qxwu56OW&3-7->_K5+{2f+imX`2Fb}!iiY^PFkPO}5u|F1Y8 z-+mu1TU#XPK8G#5XDId+g~@&oyOV)OhpAP;9MM{>p`o!pgL5`5sytRc3d;yUGLDWI zwA5N-noykMR7=m{H3S_;3>`c08o&?)Ca}Zt&X7#Z&`uF|%7;Qjkm0rD-#d-e-+OZUnE>3~UYIX2T6^rRsO2!Ca@+HP(EpepmJHiy#H zfbgxW0g^}^SNF{0G^MC0E7)vnlKm|Ds>vciXU}Z6!p{VcM|9yX^MHVv!c%ksv_=qw zQoRJw?TY*X5#cl8uPyQYgM$y5yt=Fafhow!>VK_*g4i}R`G}6%eAC;=*mMb))7Gj4 zStl2_pW~sZ42T-CiV`$QG4g6d7s%yhy!-cU&bYpUP5>P%h5M0%CJ@J1>N|~Ydi*73 zk?lk67nI@TLqmkh%3;tF4#YUM)5=0Z0G4_(>(!~Ae<#-K9vv0n=T9AhT^u-_*zN7e zzC5h#y>#-#7XW@v)?fY}Pf0im%FBBNbvPA^7JMgED*ogI={XTOiCrAiA`O2_S90EH z3)`s@>#?Ec=6fb4F;8SI@2=fZoKE7fH&!bEO`)HK=7-SuytY)1coZSgDw-^HTMmkrf6!T&1Mx#Ydl|jN`rS=hqMAZ8lok z0*^xl05b7gWjXx+eHjDhvFa!e(u4HCZY>ulGH7Me&22k*@BYQirqH`)L!C<8{eR=Z zuDUYGDWm(E$T9MM_!n;^;(byZxN-u-^Pmcj0)*hQTCYf`7qhc%Maj<#KCoM4$_)0X3Up!nrYYiIxfL#w|$;9C9|IO1p-^09BR@q@_;5dbTAi8W>P!T2R^_e+&q#yg z+7>goYH?S7)I1BIPMX^4ip}rRDuja?=vp{Zm25?HqM_|bbIi@42*367^P|qeL%h!b zH_Xn?@xi<-Y0Jr~q%mwdI$_KpS?D0et)8Didwf^K;Ofv(8jBo28GF3CJH#fbV-iv> zniY7d2XSiMyV`UBN4TxhG$XA;yoBW=29O>*sn!hOz&&6QPRq>X^E{dbN+`xnOi(|c9KGHI0`yEHijfhty1ObzYMpBk zcBGYONh}xE+g$!>ECiSnN|CS7_HRNmX<*RT#8+F(?Y!J;0)k$}P0d5zp?dNtsYj!j zt$7sYLEuO+yRdAwJ0rdTS^x-Ifrbu22N3*&uXNdjg!h48&+p8rQ}Wn?_a_J??>;jA zRb~mS$f~nHjh`)t9Ux>o+mR{{}oHyQs(# zpaVw_Zo-a+fdT8^ta?`m;3lU{Uwu0^(seJr+6Cir_=%rTd8u3H`+Y|chJaiW%Bp#J zSQW)Pl`kKL`J8YLF+RiM5O#=ZG(eCde34IPp`k@Trj>IyK-HaH;X$`co+$RzK~@8D z^k{V{LkE&$2*NeEqiI@)pJJpt??UwD-ws9`nTooABj_@9Qc`N&pif$RqEN*2IIX zf&5Oz`(QcwD@^TC(0KJB$kJQg+!W!J`M;_KQn&ZU^Uc}jv7;NK}H~g_(r6&!jaX;|%xyRp)Rbk_w0?RgC6A85|-F z2W^v%)uiF({ovW9uiwsP zu1AjWMZ5cGo&g{%$Om9AgqlLFM-nuhjVHR*3VLH;ZgY?R*2vdj1G~O2Qjwwe@RAA( z^I+*NHK&3oX823k?!lyzYI9LZ2`RS?HjX^t|MTr{;MZ{9hJ}fTa}E%?X=*kDhXfUh zW&fk(PItdh%h$!?AbC_(F3tXZPUoHTbabq?_M7*8) zJav%CE%r^(4A_I$e=C*xZOjli-M@D0VbdGpniqkEk%1{JZH$#GvXWSo zumT_`PM#9rT-MDUVL((QqR=k?4}$^mr(GU1$e!-%Cp=-6U4`5Tik8NZVc?;lVd*}2 z=DNFB@csJ)csg|TMB17Kz`$%HZJWYY{)|BM(XoV4w99_zt%0M^W%VENzcec`YVCtn zgjxF=4Ct(&*6Y+KJF@*?EeUuSce)smRDi-IF|bSw^0c_pAwu(Is-3#>;8JnKFA=?5 z*Tf_e4-bCmavKn=twUB*n_OF)3}lv-RbsnC8&QcS9KsHR_GoD`GE?@F5FqSUJMSy0 zlC93+{Un73rvHZYDnJ0|?{5kN3E)pt3m%^fVo=B$Jx<8UNvb-r)0+w=#(Fn;4Bg>< zU4d}^`pp}_w2F?S-P%l+?0ClOyt+o#`56g2erxn}bR5G3x3@QK{9#gImD4`nb2RYq z01!|puZ`6Er~*5-&=v)3AA%t=La}K3cQlrh{6QJ}6{&DLDyi<7+q(2ZM_Zeky84Sv zTyeliBYS-|I?NzT^N|p+6EvrQ#IE^~6mYNs{e#`1 z?qoHr%<_{ zve2-D(j*87d%)gZ0e;QSPN?WBcea3*mJP+!$u`o#DyOiAD&EDV>z^|+8U}jP1JIyk z(cS%2QxlBtmcSI-c(YjhT;$;g_N#N@ojh&c1S?0V=L1crQ=B>8W8o*6rDYftGH~C1 zvE~MiNWHa@5g;*5d*PVG12MsTFU?e*?NKwVO~G?)-H zLOVNF(SJH(fZ-itKn_;Z<66DkUVWa-jIPm>IVCQT*MbEmbWQUe@gt%#H8quysCGUk zB3hA8Aw8RK@957G2eU*iwS$(H7O`x!MUh3-^>z1W!oA-=Cco^yBJ(sowjo@PDlC(P z+11%CU|K|qjEtOM9RTO?^!gyeHKRi7@bpZpR&*+KXDsu3&=hjlmC_t!(ce$(aD71o zeH&(5^Hen)>wnFqe~BVsq0?r+D}EEcM@gU1PszN)Z-!s80sl3oaNx0jJEAG;L>qtB zq5$L_5RNLq9e&224V<(2tNF#&yT8sPo376{5$#4Z$y?O4bS=Z{50=QGJL zKO+;7Bib5{>~%IoXtXkG}DDm9Rvck!Pd{HuI$eX)KC$)rb?Q~ zwZKG$w~6HupK1MK%*DOLD2R6kNo3$xI?jq1X3&w>bXc$&E_FK?TZK0vN)pZU}O zfNj5~TdX=Q1QS797@>DtdhX-M-@94Sb2dxAhPYu=XCYMi7`M*sG7MO!mA(a_6;fm3hrOV#h$E4Cn>Cw6rA4{{XZo$fb>b5)T#dCP3-_B|jgGE!Fcis9c?UQiWZd zt_(!s1Ijv}N8?qg({J#PAma!28Vx@`KNr^lbeseJ85bw#Z7i(9B5%wfmFLebjEyCb z6WK~|C@5?V3=9kn`+#DrQ|&yc@l->D2O4AnSOYpa5^kG;Z&*;xC|&L9?tR(ktu9P8 zE!P4txiu))Zjx^75bZ3ef!3`ki=y@ z>re@8(MbeAkUCiljWAsWbVWt|a&vR_JH^yjfHUHs)o2Cew}r*U9oL$g8UZ@GEMi%} zhhtJwy63i`K^rs>QJE7`;=bV-`Z4WKrmxuBq=u9oer8S(4~$X`Jc--Fr5Oq-z&+vt zXh_iOq!hYRFDxuT*IpA{a7ckK5)cwXM>_0Z(EJ3bNWd!5U{r%veR*nMV4nvP%@L$w z!XR1$9GBZ>9F+egmm1`eS)V>N?qxXee9-ebcY-CJh=}N{-+)V7M@O&DlhN(%`7W$ZxVgipR zANWZlBZ&{eRDNdL6RumIo&RjG*6;{=9Xb;_f zp!Im3sj3)f+xqAa7+(bi1wai-;B(5=KZXw8(7xT=&`?YQoGho*62AqxA^ifBq&g_h?GII;8d^MC&Qf##96BgM@C1n)qoBeHuR;!nm% zPm9U_X6@^=3c}*`vI1+(CG_65 zsJZA#5rlgjgZ4%+j`)GX0e`EpQ2A}!F*7p{-uXIRUkN-!cp4+%Vg@sx5M=3Qy&qTa zQS&}bB$GsUK+${h_lZ;7so+D7);l#PLk;yIA%P zOb}kjML;61=4DxI@Sm4aJ)(2dvNC8h@<;*xk^BR)WK(Zo9>cj#PPgh!foo^pM+;MH z_1+n2H(+Q$Ap_=nXIIw-w6%w3O)9)Wjml4-0s(Lptf67x!a!Qt+$_k1cg}Usg zX;G+0q{tk>f~I4nvdGE*B+89G%25x2 z=*kK>bWBJ}ijRxK6*GIUps0v-`!>uo<|GZ4Z&Q+5ISWaH^Hl1g=>wdB%>r3+*I|M_ zQ%bz_tbC-1>aeL*c+D@}Oobms38{OpQ6}5bTtQ6Q$;k=Eg{o?-E48GuY#d_|v>Jl3 z1bZ-SqtI0FcYGX+9%POawH_|c%p)x8S?{}_AguqfNLUwA|sK}s5NP>>LjP6068!kd#>Y;A2pL_m=%pZ@c%@wyCMXcKtpFH6SpTk(1w??a$kTw3ag z=DBN5=!3;x5%QK@v%Qsars240ig>>7$s%{naqTrxQ6*J5v+3((w+Q@D&yGNs^oIQ< z!MIeom68~CCqsPDgk@|ZxV|iOr{iGVfinjz;s8-ZCUpJ$1ZPwye-*?MkZBYI!4n4B zDkB8O&`_x1-?maBSbn1`=5O2>9jZPlG;2va-ni%Gu&#spxx11Ceu|$92ygjcWCF8b zYs|sFRBox(p{bWtZRi-s>zYn-vo9zd@h67voHDi zVIpVu)A<{L8UE$Vmt9C+%vz{e&EQmoR3aAmVjsX%>R_7U{Q2_>5slTHh%)x9kX!?O z$JyDoSHAaPXaK-8@1nG%@nb~zBsdmzQTQ_M#rBf5LodF*tW8$^RLut65Y-LATesSK zoZ(4~g6Tm{hMR6j$s^2{uQ@$z0W-Y5zHb>Bfn~h{*RFlO7kXJMSI?-h3{n6Qkza~AcRGe8`3$Jby}iA> zYNqYTAFKtw>|ONeu=;xGjc!pVK0P_PKsQzBpOUj9tUpec`Go{0!dRi^+Ly}sWP~!y zQl?&~Q_7Nz=4QPxT8Yvqz?AOl zwvUa8sr1rcU8#z8-|1o*wnYT1z7UIW0L>`sXSvJAwmACh*Uz?>wX5dva5_Ek@12gN zDn#|@;~*NsoJ6!l>V(BAzFk-HXqZx68PuksYp!Ts-^EQw=}^(Avlp7 zm6DP+Ql^&gd9(qSc5p2CfY~Q<;sLl22RESYmMcpI%)&+HvfPZj(+=VOu$(T!?O&?Y zmrqO^#;V?DmO4&d847h>w%nSD>V`{Qog|0xb03dIu`=jZ$q}6*%bVBe z=&vDtd}SBA(}#AJ$`TWefcNg=xNwD3I_M2^z#UBT5+TULuI9C*hy8K>)$F7$O zQFOt=7^+c2;QvE?zzZOruP+Rtof(i>A-dmOV~6%1*L))KGKH+0uC-O8q6pw%n#N((8yu_^D!J{nBPTE!4JY~6&`26fCQ$2_6YL{@bd91 zlR@~9KFCAFp2NHc{PnsXhtFoXv(G3 zS6ClK?o55Wbk67bM<$G+g3k;1TJWdCMYuG$H}J}b6^i*Q1Q8FWgMrv{VD+zi4syF+DEF!J(nG;j(bj$+b0Q{EhYXpDisfb{0SE zuXeG+#|6KlA@Nby)J*&QxwN9<`t|Gm5kK$=2}NO?`JFqpP>PcNhLo0qoct|=$mG%zWaAeg=r2$TO3J80 z>E{hqUubA(dU|?Ah1iQE1~nZQmmL6}OKboi#D?)2b6D@b_#Nf?{4O}p5oZ}@+*66NMzYyQ9qJTw4%SD@ApQlIkJU544@ zk3hU@XJ@C#o{Z!05DT$0*(!pcuAp*dV;1^!ImGmW$EQbYeCDkH(iVV((3z0F4$}{T z;29Yi>F(|hzYB%#11r?Wu%;>aFEH@}ZkzpVYYYYJgIl+5g(;~n9pTFSkS9R&5Y1ib zl!%4Rz1e}KY9T+n%_66Zs2?K+uj>~ehyKd{8EdT zOG0L{EBB!1&vB=?dS>m%Z{lJp!1d`D@VH|aE0I@fZAlos`Ox)})JcsbrY{ya|ASKoSe3x%mE>00n2cOt38Og zD_qx}IXQ*9;}@6QMkA)$w-r|aslwi*Ht@!jPOZI*D}d~*hqjJr|vU9;$OdAP5mGP4gp zx@XV~2|^zHH&+c(VXK6c4%X4LXU|Y5EX8g}a9?cCzst;ISL}ur1!L47cmWj(lH>Sz zhV$orV~Hg5noG9U9DfHRq9ib( zdsIKkionpfp`mX6C#I&`#|KUn6cn*(pyP0bVu1AwQd=PO9>Tnf8#+Z9vp+hr*GKZ3 zWH_-94c{Meuqik?Zh+ow8G5*IT?q+_`0g8%eo0B-X!m5_$OR(`V|Q^J>rQt844Q>W){ZuLz~ zFzKVep`n2zmk;4%4S~W8Gyf7YcBo?R-*1MN2muo2b8^8*@S8Wi*2im?`tt_j@7%cq z86+1Q8z>z>IT6sKW!8BEx-GD$C)t1h{tY)3T0cs`>|W@>wSG%XG;nb#1_?4e<`60_d?fU& zEPJyq@kPRHtoTm&T zWn^rdT^=l6f~nc*igA7E%1MnK*dPCXbZ7GAp%QOd{1^$(9KVJaJUq2%Qi+;3dTk_Rf5UX9mo;~OU!^7$phjh=?a!dev0;x zO^BDS;Ms~-Q0y&lA?5heu1<&b0<&LLF9PW3NI(EhePn&KOHo-xO;2-yPGB*lt4rvO z$COHXeSJN&+O`gkp%wyz2XYiSIXQGrzvSeIInRHe+Zu?6N4q#uQIe1_lA-$PeRw#% zyPn9yk|Kn8(gSXlfD$3N-f7#iQKxsKY)DI#xRYR|`z42P2%uH1cjb7m87UWwx zt`4_lYk5mLTp9eH{A+t*3G4jSV3E5r^UP>f73!lL8)dF;i6k$t+4j5ypZSeHwzl`1o(ncUFsSECe>I?yfAatPBw7&_W(6@pKyhsKbwl`n`8QBh-;u zDQ`I~;wTCIB##|<*eua+6qlx&yj6RC-#G#!?-RVj>E>8>8Y(~yW#R+)baA}?Y?FpN4 zXDM$Fc)P&G`XuGBy0f&|pVv}VMa}1aQ@?qkvvzT@cZ`~QRMcS{Z>c}v4Z{L0)wes$ zeq38{Kha@~VpPS}W{~l&PlalcT(0~sZM(Z02?T%<7<^pyf_Ik4a%}YJ?lMoD&{9uOHgea~0YVh6(`T0{BIKS7fr>CZm*-q2ryNf zIq_KECNsH0r$kWFeUtND;ORp8YvAz|T6nXdp}6zH6mxP99;j^1vL=YxXMOQ#n&!UY zQEsXFzQmQAn_J7Jj~-E^Z(>rKSAAIhdAdQ%uq~S3DojPVZt(eX5JkWL1xKfUin(7V zraciI_KZ}5Fv)8vUC9hqV1#Q;S6S#Jy|A!>j}%W_o}-GG z6m$&h+MmQlS)rx$>C7Hb$umDTB9iIpUPunZ*g`Pm8c$EkJvcooR8?h%o3OIF3KLe= zB+opcEl@R7vNbY{f|+Tzt$V1UN3hbH-9l}M4a2xL*C+TED8IGBa9;{knzG@G$@*eA zIml6sp?lV*w+WD;Of^8}=>Opt^tbM$H@srW3S0FaQD7rc5+3XVJI6291mc7p#|MiGp*K_Elny@9jG;|LgmfDN78IxZSG~bB z`qMpb&%NBiU%%`|%C&QJ;}kyUn|bXHpqrarfBmw$7i#dez`FRU+4w7*(>GtPBkS99 zpU5_@z%tm`S*d_^g&Wc7qwz8M9o>3N%K&Rj%h+g{+WJb#b-atu3JY!GlFlB<+n?)E zLe>nMwMY;U>q|P#_8S>hH#Yh=G<5v<(J1bH3X=}_K&iF8ySu-bO?!6vEe$=r>^)^7 z0__r~Ipyy3BmP510L79yosJ*EiFIC5$kjDrz&h3|oRQ}aO}cRx^g6&hh#Aq$AMml3}MMs@8A+Hu`^|yY+Q=C z`?r3Iv|2uK(EB}pCp=c^uvAE?A(|-vy~LI%-oPC(wqnTSGH4DbtksSTSN7u!8ahL< z-UPt=>)h2koS>6Rq_}+(H!B^PROYXKo(|WL31RutzsW(TruwtEcbmuj@4Q8tT_fANGGC&5~qeqrzMz@$f~hfLJU6 zYzGd1-QOQEAzCW#ihp+8wmehRxl47a)N~hf@S(Ui7A^}+I&`E};n92k&yO8l@eikV zI``d7s=;BwukkKqL^)`h+{+HMDz`mmJKZd05Xm3@r<$7$IIo1-^8Nc$N_EE$XD^*Z zwH}*uTZ;cpEWZ@vAO?dHlIizA?xKlF(g%ZxN9wh7?}+0ebk0L*XeqK$N}N4%-ly;T zKLy^fFAa(My=&yqGt5cT0wFXnFR$Q}L3IOz+-9AZtB+Za8XPzfmUypIUj^f1zp}46 z*$tIE&0w#C7!F|NeFX&>W>q)0QjR6uav%MimjmCEIS>wvaG{sJ78er}5s87Jk|HgX zN+5gGBq9od-!5(M>O7Y6dQi$ba^eqd`(ff7TmA-`6`g2zv$^X!9^r9!VU7F%E~;-NpnUZ+JA3$)3*1=${y1n ztdxw!CnPio^*ki*WCh%<#BK!Q@ZQEV~>R%^;Z3E3X#6Z(YQE~v?iZaT_?$8D7U!#CfdDR+tAR^z3IIVeEY2Q zyVSSza$Fefp7v{I9pl=>(9*zKQNLjGnVL&lx$BE* z0A1=Xqj`Jf_4)A|tk2a5KXBv{AbfT^E?%dY#XUdHKzz`4|BNhypcrdhdJNm^ zMsVsU9)>$Kc;6Xgzdf&Vqe&Mj#!6n;TFgZ~VQW?x(dZN`7mjTHk<8&Ut9G=X`C!?a zX)zZcF@H1R?F9Z0VMLpM`%{EZ?ELB@SVz2y^pZF}jUjK}nhSzmP_Hhbk+F9;}|;Ud0s1x}p4yhS3l5;1Z@MM|3d`8~{my2vwpc9#Y( zS(anoYpB9C?_mpGCpNc1gkl_(jS-Km^4ceud#W5;lvTPP6TC#qPzi%RO)oL2<3X$O zBH9s=rPaL;r4Mu`y4ddqklcQ@OtaOYlpqSqj*8M!x9>jZpi+Xo{%3nTD>@<~0_?TJ zI_7{j0QQFDD9{%XAi<0Qu#dg1t-`OE*T&Y?3k=I3;4k_y2ROY}ojm;GM-V+~;dzVnf5jl{Wpkg%%xe-@Iw-=unoIhkRKSdF{rH)}f&az>Nh3pTUqq zH0etzDSXgAMhnj27|RwT5Z?S@NX8p!;@0`29?U_b21s*kzM|K}8& zi#reKcrx8-z9%Q2#Gb|1D}7f`HK3dkaGbmknQ2QT%ib!ZwWTl&?9Ugmxebef}(M-W)>B4Yq38 zSy>W5K~Rhn{LK$|Xlr6Ov?<*><^yekz<*fmNWtP@yDU)o3kL34EOzW^8;050>fhSpG>B=SAg|cfS70W9_ zNms9?$HvlO6!W2yxqx=*l{+_Y&Lokd0IBdeJ^1YH{dz9u!{zO5w>Y5=K0(22==yr> zm}nY0T7lGstuDV?2SELWIwe-HSBQ`AGV3#j@n*G1E-27$ik4aI%#UP!-yX`*Um&usVsbQmw;sdI&NdwIYKz;8HcyV%jB z0M}jO)O21QhUBmh9R~IPlacZdq)(wzA0K~=3XF>C2eJYI5>RwNQEU&G-&w*x0SSeQ z&=2OBva*`j2a=Jy{A_NjG=$|B$X2~ZL~BbOPx^D>T()LOh(h+1 z;!DkKhkI&Y!WaeDR_`&-JsFqcFw!4Ws%X;NRcF}eTP0&Eg2621#fx{&$jO746e$R; zy@8Ey91+2+9ozPR(*rXAz5wTq8>Uz{79s%4hb`~5`RjV?&7hzlXf)1k9RPb12te1+ z*H~B>MV)^(HnIY!$;0#R*X-ir;`B6}7ux{V4?weXaFFWKrLTFsfFymh?#;?nONSzI zCR|y9=WpAt@%s5>Hn3QAm}>M*@+zM_TI-ONNrebeQc*DlqvBz?PXL45ZmiwaiD;m3 z&Uvi59UayXQUV&1t&ORu&4?TNa$GS0Pcn(KskZ9AqI-O^P4scOY7RP2gNttctCp6Q z5P+$>lnw9C0%66gvIQGAavIj$G%R9U0Bul5V%77tD)YPkrFr^dEk7o!4z_CK3*j!nB5u z^a|9YR~<+yX4&WQ>m7FdbD{CrDYX-;E4@Q%%)u~AWrg1=i0Pp(`qAXRgs_znRe$l; zwQKdmm{)uXo4Lua_bhL?sSr{oMmLHlZeKmY(POnLTsM6&aIfDPq# z<2kl?sVnncsUZMQS5=(=uOmi!H-PmNY-{ZkQ&Y`=ngZ@;`f65`GT`qB0cmZpI2$6^ z3X~3og}OCfw~+vYf>p{(4~emX0TDhvH4hk8y9y0u7EVqDb29{j|D17YBMO4&qyO%0 zS^u)Kw>N|~CM+39@A}{8WMwTjzM+T3t_Q$846FzG6g9WO1AGD^qOINCn;aa$Z{8#b z*pdq%Yg^Q4CxJ8*kL!&-Jv_=y$Pc zu-*Y4iav(j3PwaCA|f!-gO~Gs^2^1F*{VgOwikYPCF6~gg-E1S!J8d00QhO(%E-QD zU_b4GR_y1kEjRJox2tpr`FVJd=>5aP)uECO=+goB=Rvs&+w{h%2p$y`Rlxyt^MK$a zX!}Ryg&9Kl`jyAUScNYKkpL96brsuasi}3tV7wgd!r94&kO$1bAp=1VpcM5^0AO_T zCqzW_I;3%W+ z_NS*dkfYd|L()3D*K4=^h)zKBrmlC~I_fo9;c5{b)%S$}Y_uz1zLW@8BoJsiaUk^f z62`$mfv{6wcxGCk{Yxq#_)YoU?1AXl<>ILZP8=sW-fL_1>vP8@b_F>d|h(*RNJp4j*gW z%7cPF{#d$j-_J`pRqF2thqc<==jxBm)t9{eVt2`^+kbDNyRGdBZrn}sATZ%nRk>o> zJzJ%go*PbQeCM59y+koF9T87_0p!|e~&MPAB zWa0CRgTH@SSvzm@3za~#EAAqFUw1=l-SNTL7sIn8?SdFv*Hw>nbO}~4`pVrh(nc#* z4{ikSgam1u`rJYA!Q`!`yxcpI@lQVrkswO(Ex6u1JaR#MKGgW2fu-p4+b*?EnFvw( z%5zqAe>HYEk`coi+S)N-hq}6&7$2{v zMtGHtZ62aL__xAA0-aM*r1TY1QWTV=fQsC{eY>u%Zf&fl!!%MUlkuOo5x~4n{1!Ct zA^E*{G4$1|S0+twSy)-`rw7jM?d~SR;`Jw{PZW25dc5zr5rs=khXLJSpgA@!?ps>E zS-^3+*t0yHzH7{fYFyk#XH!df`^1j-BfA0B0sae&pBHeRSD9UNSfFGU)Sy@F28;oa z9}#HI1JN_)meORQ=YPU{o1fSSosJjjw(BzSp2NKpHU(=o=yg-!W5d#cNksSHUOET6 zodSdiDXJ1c9Dv8bxoX-i!%T*}#>r{3*pvC`Ug$1Rq<;N+7lWm8{Y!VUU@6#d_}qo_ z2(Y}%l3wv)VYiIy17R{Ipqg6%T0Y-fRmA6kl+gZz6To#(p9cRsvbWWQ;j>(Oh?ss! zgGwN+%OsL;|NBKlA!%V%jO|HGdF^R~yd8O8)qwc2J~95IDvORTSt{mpCYgi*U)5cH z1acq{)bas(n|MZV2DHpDC)9|BPdUB%ePU>%f~hQ#$qz=WKc+b!W2@4(Z^eJ-X>-O&)VbPEV^G*;j4F8 z3;?7b5n;5uO#JmL-{uw$J9`K?g0!RoUJG4AP)o_-$B4Oh_hi<=KMD%w#AxBXl0(VK zHcA$zUZ9=ynrake<+G%GvsBZo=vEDwAm!>@lKt`i)FpFW<+ZaHPjD|d2;Az-%cUYm zfdX^1M)Ex=;CEs9`NUm*9^1c{raWMP4>ZD(n&z-5UC^%LNaSHAsy5f=Tq;pi~1oC!%U z{K{wvAbczi2J&RPZ){wDdSY>Kyy56LWVdbax-r`T;-RhTm z$>|79GU@Pqv!H$WPamV1QANl9f4BhP6+}V;MT(~F#C=g4u($&F_})arBEGqS(C%;S zAm?XOC1aP5kDWYPBHNN~bB^RsT-oYsixV?7$9?k(awbHA1MsyvB#vwWzJ~ln%~gLI z1a}55T6c~h@xZuQt_)?h#d*U9ErgV1$A?CV!btiOg3|8aIUSBB&FnXCUcU9%Cm{i2 zQ&<4KMdfrhYsi9t_ztwSctE*fU=qOMTrse}03w0Cu7JO>w|5=w=H>=Hrhg|26!Lt) zv-#>T+`o8yE58~A13Zh%%n2=v0nW~n8LduVVFV8UuBh|^F?iQ?cWBm{1u zSy>$4cws|UxNpJ4`vgKlLe$;6U^+p0TxN;0Q2dRbxNq>Gu--3zIutQWEgq3dxTrVd zf1r5+g;CHEXmx%kC#@Q>kE_@%aA|XQMHfhK-$+{hlaj{Zv!RlK6l7#%gy#X0!dRFQ zZ9&IRmk4?f#jE5&%`GipC2omXV~z<6wm(@ezvzt^0CmV=AZYCWIe>yfLSFnsG`Mt@ zix9@=iBE%$2!by4zd$%%u>x(i=T(I7SjmGRBX|Z68FH4Lh3=-dHpSYtdm*>76JD)K zU1&N7=e(5DHC9%oSbla1iBaHGAD8`(?OM_Z#D+QoR0jeRY2GSyUc#_YF4Q|P z_`(jSluO(qXcs}m67VqWVM3)$=9b5+dkhGED){wlnA|$}Vaoyb9IajLG-Ej~4}%tl zIw14TU80uOU$?&I%ly2hKp(a`u1O|?{~Zm43T4n1#4SWy0L|MW*t9+=`EwN54v2Uk zrYynl1SQq$LFam~Ye*2e-%o&0!;yO6IY;;CF8Twai?q(_y!aS&oam}^Q`2gvA|c3n z33I)qhcg`E3~i|u=tDu&bbWk7BO60KDk2w~&^9&w{M-gBS)}t~`jbw2_-@HW@J2|? ziHOj-$P@nz6C@GIBk-48@Ry<)X;#8mSeh+`M}NL@in_#p`AK-rrwhYd>bwj?XUx*p zMve-_D?oMJ02LNt4jF=t$XNIZrt-*b~}?S1?U#tBEHBpR#Ow=eBW1sCl8VhbNa2ibNTSpDd4GpcfqPHtFLD=F|m-A z^=d}jbg@rfxUii{L>44HGm~z4SSjb6n=y}wYsYrD@$Z?YWH>Wruv?{fF14SZvNcDR zJVn*UR29kP*M0r=ye5sJG3w~dRffI2R0JZgrDo_Cu{4F`k0IrLNlEaJd)~&as%!M%Q zxI!(x@$KcRo~CqHrFNyiA4a3v#YJ=1bleFcVEyM2#}c#|2ng=Md={?To>k6-Vv!sY z===EYXD8zTJXu+N1@SO2FUme>WLLe2a#^k|UCdr9u@xCEFFwdOy4~I71&yYY z_4SQ&=XijGks%W@3qofg#JH^|OQ&RjbuR=MY3bK%V`F{?A*!OOACqW+rfB;8!-Kgi z9>{%CsT?}mI-aa-KgHPj-ozB+=4^6fVMNTW$SfyJL5=g-;jNlwALEkH&A-JBSivA~50}(!bjUljK77%)@{=gn$=V z?;wR~ULz2>K;t`;!tCMiNZ>?aehQC=;aJkS0dfil9An{qOhXxxP#+qSYw*@8sU4DI zvZ@A?XD7!_k?}`w=}Ue9EFakrPGoAbXz zQc}`^FyjsnJIRo;+tp=z{=@3X`8fWApN;0j7bW#f4Kb7m=*uON@*1J|k<)|4V(2gs zz~bSB28P7l!FNB{6wn=nV{i0DM?e$(V@UYs+LJzqu%MSmJqLd~1}Bc*Q&LjPGwe8- zjjMyJaxh9MI|zKscs=!Vyn{n@N}l8`07kczST=#R%PHgD7ENYvF*jDU08VV07Gm5ef2A080NMM;lh( z_?x9(5h1<7BVShba zGq``ca$Hzs%T5{m?TMHy{=(=;BKu0XGKR&~*Ox;CR?r)8|Lm(pnDv)`g~ud$Y^K(n z-8Wh(l7DP)I1^A8a)BCWvjtM369kaT6bHjrl~yb$@X<2F#V8 zU;UH@ylDI3(oU(bYjyU1&NTW<@UUQkff z!7p1_yf87T+nOtU@`UTl7acNGqQpsDhyB%4@`F94iuiau`!P)}eNmPxk8dIC2g^TX zW^N?k*-A(l0yv-%cve{Ft3X9}e6-fDm3u5<8dy=|T_pXrKX(My$7D}t@dH1r*ww+E zZpW!Z3KTpZ6Km_`=^k(lNCEZ;>^(E`hAp5?EU!uw+8bKHSAn4^MBrou<7dP4OcH(PmI^vfgW7kZ5Znm( zqAm#~eIFAu^f?H#z>RHwL<+hrI=~_T&d2Fa|5R{r$;yx};5-VHM?jnh(Pryh2?742 zll_erwe&uinGsLgRhT{nOf7)E0n^iu`J_VGTaw3zls5NbrQdRv8LJ*);UGY`{Gg%z zsSqctUc69+m{XyY>7JYEko5AH_QeYYc4t}w4ksY8t*hPo?^8d?NB zll_KkE-TjAz=Zc{gn+Z-11DGm7`uqOsdN=*CzJy#fDW&NU+M(Y3)J9+hne?M3(?6q zAK?3!BaiTbuB5O3-#C?Q00#pu0J2iPsu5A;*$|uHP^2Rj11sk zp^TrSBr}yK8#D=5nIii zhDVPRa1k+`7x4&vMupk_t576>EcO%~2F;m#`Yw0i&*73V{G5YbmjK1xK$W<-I6hJq za^HUdTO>Md;UCCWw>&HsIOb$1wqTtC(;yhK1kUpqSt1OA1GAmNA6;UN_4SW*bvqKo zN_LMC2d_}>AYBK; zPIC(jEwxksJCb^y5R|1@^?pgcDwqv`PooMhkZlvB~XX~kEu8w@1eRMeRz!l#Jre+j11wNKkv^;g&0W_ zM4;;MI0Y)7>%q(#U-@uW*omFZ&DPKY2gT~OhbEa_?ogV8rNb$7&Ebldhs&TJ`-XHA z$n;v8nxkb-0R!1ZMLj=$7{g2~XbR>mzzu4A*s!FcU>4Z($U5PGUe@?V@0g^hz>Xg5 zYhGS*c1%xNEutSLLjp?`c-x)^H8(-X4FjN=ytWkG95)Kt)ilp``aeZ-wY?9gE-M$T zBpJr&Jz^YK&Zl;+Uy-lN#v4>T^b%%uHW6ZLUfP`Df`?H2?K0$9RJyt$yDQh#H4=7q z^vg}cFHgfO6(I%W*z+?`n3e~{1S+++=H@ac#HaPeaPjaMpPd$ZobH#F zt_j)2cV`@)L+r8h_?z@6ndb-b@)c(53C%hbTV$-E1~;>{W;B>O<(O0(T;SXh4NS92 zn`!CZw;vsL1o#zAI{OQEHwZ6?_{EFt*RShSQqK41vOHV1%z15n9udIC;}4sf^HSY4 zzEj;*~__U?=QLG_eOmYAZ>hUm!)+L4`$S5T~-j_<-IR24@8KoP-L1yX$l@e zIvyWv7R21ygM&juU7tP6^=z|(WA&v}XQ~1}vN7Q#)H%#fB_Czezu6Zj!`cPH^at2n@<_{%Kw!2{;lcA)U$&xy} z_t!s)8ycFx{ZH_dBSA#m2?`|+PRap7OU!_0Gz(DxF+CMId4YLbEbyhi0VP`6`cN?l zqlN}3W~`$lFH#_#J(!n=2L!8r2z_>??zmcb44)!jiL($9+qW25mM^r`1^w>X_5_e*xq>kSw1l|B>Ke5lu2m@| z5>){3Jw(bjc(u1H$;l;KmH+F4ub;iS{F!h6;NU;582o2qGBe?b&4fA-hPZ`Kj*qK6 zdQ=KMJZQi3=)dPkM%IP{U(Xr6Up7A`;@X~_CyF7iNwMyTM;!vR0R6uh1wFp#o1Bp# z&3$Lmw$Rhl1Gpg{Um-BE-(9`e_wXEC*Y3^^j3`I~?hLg3Vlt+dhB?7I-7 zKtE6ya1q>yuA)2n^^eF$fT};LKiSzu`+4k@^ZoOEqe}AfAFV{$*)yT5XFCbham_q~ zC!p9cGhqgVh5 z0|5a6c>M&lc3y*NxLu#+;n}suc6ZUj3EBf%6;$BIk47+tyFPmvIn6ByijKCn93XGh z`4c-iIsz)^1>l2})OYA4MzfT&+>gw_+&^VOIg2na08(7MNV)*30q`2e!#RzAKPTu2 zHW?7X1`EtW#97#=A{`K1SD$^N*AYNu;OBlSSGY#5t)l}GQCCMNYdH`Y>1Uuyit!d? zeNBXq|EJI*G~Q2zvSGOFCmR=+S#Bw>tEmERMnb*5os0RYeZa8$jK+hbacE!1%oslz8R^xTAB87ZW)j}v6qr4SGc1BYH2d%oWkj@wXrIq@*oj?Hex8M5 zm62Dw^h!{*@r@mD6u3ds^AinJ%B(bpoN6PzDtL>;tgtF3C0eyhSpB_AvL*f>xXJ2p zu)mA~2h2Bkv&+wcl!w9R0dQ#A!=1iK#zgRIARXS(**gza>{;|O09%v*#8UXgr98RS zg(vcAqw0R&k=98;{bQ1`fU5C?U{nhm8(0=|R=~+!?lgK>@yrW|R!jX%SAer7&Lr$0 zkt8`f;I3mn>pd%1?wVJs5T#sDu$omm3u3Ln2`RN6&etZh)8R_WV7*`CEt%928WJ*8 z>S(g!7pSa3Lr2#vp4lAP+Pdosnq=9_IQ-#1?v_9T3(`AaVSSxi7GTt3mibrfkN50L z7WruD*C$hrce6EdUYlyxHvIkVGmd@ zyqs6&92Fm2AV5}EE9|X^nV57xpFnxD>a$S>arGUe+ma%RzBi;!!T85ZTY?B5F^I*D zwXd?0Nja*2D;gSl1Ajc==?P$|y96Gq z_lnE@PQM{w9D??v;?_NE!6}fb3xEa_;&Zw(6Z4WF*aO^vAz&ieIW{E@@|9*dURa|0 zM%F@Rt@T5X)!VW+3TT~;9tz?7fG#~Rdp6VR|Lr?rp~+*6qHTn^tD%h0b@^yj4h0N^ z>rr541duQef{et%qQvXuIV*j|cQRx>;M3)%%*8j}{};n1HM<`;8^gnTsGo5D4CLNf zz=<%Zbeou)>rYdpmq@B{UXbK-prfVz_2v3i(3t_(2GYsi{(k$e&%Xl6u7aIKLsU`h zzY}y6@qxV=C1EEo{|guy2Oiahg-(E4lIiMawU?wRLdUpR?WpJq@6sm%U`psGf1$Da zzYH!2v9SQol*Nr}0`?40N6=x*%eEjbgl+=xHywMkH2nPhfaM66$`e=k4^v0r!wt{v zxWv1X(KB&-{Wu{cUi-5(GaD78Wze63}6tot9#%&c0bFj0=?m+PvL=nlWNR2s{7MSfdV~_!u|Vz74yH?U5rI0uZ|7fB2pbt@$nC54P{hJ<<;aeaZ5i4M$si$XaXQzaJ@W0(OuHohzKy?Jl z9`G80%!1D*lF07|5dWaugkS*DRk<4u^|o=*(LE1&3*kxZZO$lwBM}5hnWf;28eo*b#L$jErf;0-0R?&%ONCG0>&b? z_aU&iL~>y~Nf^q%d};0J0bj8m$oEoGUZt=Bk1}XV(57!0!gyL*8oy!`FqL9rejW4` zk+T%fe!yzM&Q)0~y7ESSY!>~s=kUiP4xb0jivi)npTMzWK^z!1ZV<(|!OsbT9{~j` zDGEfJV1#91Vp8ZZf!c_FfY7q|wOk+vU>?L{P+!7HM_y%o0X8#;FF`>H`3x(HxqwQA zyv8=rzF%D#6&MiE1W&I)4K@;sXA^yBlgS!UghVdbbi_%IOSVYCoiDm5tL_qGorYs| z>zmzQ4mPt{g9Bt3@I{L;eja{M!(Nqr9To%J;r~;F2_UEcBNq`kF6JsU4KjOI{@UJJtpZHod)?b0BnJ)X2#9kb9nI0Nh&-mxg|lD@Own40nPG`AdF@YtIIaF-)#F+$ z5D$Qq79Jw2%wg%l!2#3_V1NjGa&R&eEzHZ#&i?etWW`?bh%K{>BX8!eZ{~RAXVN!$ zAIX*H2RRoFgAXsCD?-Sg>v>RtXWZ$YhNWjONhiQ1x3U<|FMaydK~k^kZ^9FsQGq48 z0xmF%xv#n=Ox0ys5D5AtdFeaqI;rZEGpVZ_{G^y(8K zdM7mJWl5{f`QQSLR|(n}s;-w15lZ3dIPZd-F5x0ZAeHeM`g1)^U_}BcQZXE@i?S)_ z;Rgm8+?4y7NerN}_F+|9h}}aZ@6ZWy$^8#Ih@zpzGJK)xEKrR5orrJTJRdyM^Q0S{vXvkWo;4PC0api5Dsd!zO+t zasuqyzzz)pI1KKNP$KJCTUohn(|5z1>v0gy(!a<IM6HWC#J04+Se^RyNv?DybdaP{=Nw!L-wQe>oLaf{4GjQdYBImJfd~VM5a^lVoCJq}cX4r?2`OQFfk<`4 zIN|U`Je`)|N^OUA{Mj1Nvyq|9+h2zUAHpg+eBXS}TWV^gO1ED2afK^4F+R-=%3w6gNV?wb5YWaY z%|@wTUR0)>WH+5;_s!exgGmV^WBM?BFb+7h0wxa5@oS#N_K+TQ=Qk#7P~7<<9KL>2767sDYV~($~m04vxX} zu7IVGj|9Yh!ypp@GgWv&z5&@5xeMg#|A%wTrB56*2)y&*!9jo{R>8as+Cgi9nNmp- zo~D{UZH>0v+6DE{p@WqYeqH%nK>-wkSJ84&+$RK5S3z6>u0C%MlqUsCv$CwsALVCd z>C9HQrs_dbeI0Jxx|_JkR2tCA#aydRPLEbAxFdE+=ujzY!L+zJPEr1EBKty|f3kR! z_CN&Z0`&@TT7Yl^XDzT?;jq4rw*Bt}33-j5A7gt7_v|77nkR<> zNK@$VLC*ml23r$|)Zpp-?a_b8X3lD0BHGO?(X*-jJ)bBCm4nQD$(LlB16{2Ro>Klo zUXL`d$d+fTNVC!#TmiGfUXL#i?u=gckA3=;h+{PDfk~ZiGOOHuokuybsm$-o(`bF) zG4svsHDv}d;!67(wYM%EtcT_`tsNw;i7c)scDT03fR`uiF6-h!Xk8Q%fR`j2zEjpL`bmeY;HL#G;ZkQv$)wac3a$I9BeB0 z4(7%f#5AdBgdIo9M>G>o7&DWmy*ltl5QuNdW?J+x1~u)sB|n`a6axjn2L{Su%;4i& zl+@Ho!j36LMc~}15oz{D)(LbUz~#b6f=_)HaI2~eygP31MMOnG45@&C3fZ~LD8`N+;c?Yc~vzW7%Cr`6_D{WVz6*7=HE`X4Sy%1RIH*Hc_vaL#seGF%(h-ts=%gIUX=+MwSl zb6DIk5yEC3)WGOGNd!Y{-XXM3ftDn={&6vK2AI{m>5W|F75KvD{PxE_u%uhCi z4;9-Cam=yZ$VnC4s55%Do|jFliawt#%k@Ip_r1w$SrfPqz}vpj0vRVI>NTA}^U#nO zGqW*hSs=rktnprFTLD)iaF?tBaTy#k81JKojW&a4#JIivslG8}gZi1u+9CDHz1_>fL36ex|&S01p89;&r$w?$j&duFDzBli!x9%Gj ziyu_?u2WT~zO&EX-~KjGnV}nT<@%h>nWl@5XNvbd#3{7)ws3hNO2=C@VW<1ZKmei|7j5dwCK|6$BDBK}hZ4p|{(AhOSVzyvd;k~rcTXcd`-6(M{B zT}hnPdz`h=4RnbTU92M&9NZ16CW=t)u!1p4qA`ZQjSb5ZjnOjD_@}eAk(8;9C7um^ z(2)4l%aR0HQo2MV%6avwkhz^Ve{oT!&&N20)IyUTQ2)kSOkY$@Y;m)qaK;eN%)5julUN?|t8y6Um4{|0 zBC>=e&Y&2qM^8o%r>5`ha%rW5TUDmt#JD>}zg9}gngFLpJS}q)iiyd!k={0&*I>KR z^%+Q)>Qiofwzb7adA(3g)Zl-_2VyFBLj!l9@J!~id3LGeK$?UjH%CE4#Cj-oDm3=K zfD$aP+BRWT)Q#7m1W(e;4gc9V(DbywE4BKABXm+7DKdBz%@W(vqQ%WEAs=Ryk=$yb z(1LnxE&Q_4g^k(8MCFRgz3s(cy78PZt$H{oecT%P)+2vs)<5OCnt09N)~&0a zUeO!7Ec6V??g!4fDET<~1ip^7p=&h`nmN6OMh803uA4t2vcf=HJ0Wo>$)-Pn3IMTJ z8NTTLd*4HR%jSpCs1>ZFzU7xEbZi0ftJBjrA(P+K-?<*f^_ryY0Y==gr^==iA5F{8 z+qt{zYEYw=T=A$qKn05(Nlw0|nN(&-8JjMxN$K>>JO!0qvB{}&Hugn~>uN|(Qu!5r z`@9O^M3|U*t*+0{r$$ETHyt~Npa7k4rV}?=6;(RUm`$GUY%b~V)xq+>CAPOyX;leh zZoqaDLY`bvVGR#23Px>gI9gY;z!|N290ngs|M;VJypzL(FtbF(%Qb=SZd&N3e9cg> zccz|et+mxnMa9$jGlhIuP*8lyJt;lixip#P@|Q0gVw=_QAG)Mb%qyjK%#zzZ_4O1f z8;)cUjcig;qKacLT=OAiRR8Kns07W$T=;@cK3zqVX3m-7l9rO=!pce=`&Aa!AogG` zFW~MCna#()i23|k`rSLTba5?H<3sz0OQJ>-26}ovJ<^(qiH;Bj*NbNHOOo6v&2wVs z#;gp-pnX3^GfRN#Zp+@}q)FV1KcZ)r7>%_yGE!5EP%}%Pc+i<#&AyH7!M`@v=;YKF ztqI)9ahm-jz`*R@(aw+&b$VwM6S~@VNM9oD7QN@%m?if5_J<2TwGMQbB*(B$*ZRvP z-DpnN8uwsn4MKUIXv)ZF8I<}O?mYx%Ezc@o(@91v-;n~KqtEOXu8bw8w?H`le6C$# z$;A9jpJ~E;a3EOgi1_rLi=yA^q$K}l_|uN(Y&{HexX3GLVP=d05% zUEz@CmcmUHL66yqI<2kgP%1|BB!Bk=&z5;Ei7o$ZWyr!-F?VUM;G|?>5zw~>(=&)<>2XrSLWhyxq_YD@bLlt z?)vFWg7O(ErkJ!etl-bod7=-G_CVM+7d2CkCtsa7vB6+&pAfD!Z_l+o zJ_9d49i7XB$3m_N3y1VcF!(_G`-+GAiWyRF9orI3A)rAg@<_l^TgNI*)^DWKR;|>u z*SJ_&XO~ehYp?u))wA952Ut?_Z5wYP1fgg*(W|;#+4IJJ-1ukamC0(`{Pot;-k$Zs z4`6F;8^%0Dit=xzH)8jUEhB+bVGk*JG#6T?R`}3mm+@O&y6k@Ch)oKT8loOrtqo!lML}UxdM{}x^SaWg1tjx54+Q9b{d#O{ zIKVuQk7bYP{Nh1v$J0sor9yVio>u9-F>ThjDI!u{I}sqn)Hfu?!@+@HsS^;078W-C z8|-;q-v2pv{k~#M9}O+7akFRs1p&4t;#FF}RZ92g@uOvBs$TIyUiaPzl%MqdKm{~w ztd(WU4U5{QdCFRQevcSDmoyiJVmi3xP`-`2Q&FbUl`fC3MFC!)62OY!a0^czxbo!U>C4;6BfgWto(^kU-f9g`fV-sK|xbTN?L zj;_`<)WnsY!gCHr85uRIn+ORJIKZK<78GzOFU;??=HuG`b7Z72@2XkCUdLw3LIzW_ zg~DUhYv_9SI+)jMFJbV~h_!G?F!gPXZlRxlCl9>N&CPq`MnP=y+yc6H@&23FEaDy& z@{|@Y=aaN8>6KmF+=^Z`DPrlT`bmgS-sffKf+wi7czEkNI+}Z^Z?HyCDh>_U`ZAY#d1fd zR8m}=%j_RrVw2vom#5YSGc*6PmGdT z)%jC~0A&6|g!}Gi7mx#R30m-9;P2et$piFah@Jizu#}+oNb(+UH<_zH0Q0~*W2l4s z%PlWJh#!B`c_r)qlc#pf3u+`;;qFFc1L|??8h^}P zMf$fQr%CTEb=WV_pk>B*w#164ew+eUl6yVb%46=s+i}9cCQ1Iqiu{Kkh&t<%k_~Vg zi0+Gsh(OwkMF{hr>RMAwVqzl5D0FaUhM5g%uQ%^aKwQEL%G#r79nud#?>-3Cq(&kK zD^wfHK$jc@zWS|&$pfF))$P9xr-!UDY`iP@8XFo+>u}E@j!?n3ymJVQJ>C=efwD9n z#wU05J8{4D$d7bWoril~t=l#MAr02Iz_EaO@2T%`UuK$p(SE-}$BU=&R$R!4z6#SO%VebPT&nxOJX(0w_U3`MmUv8xV-Sz{vPem=V$@ z8^E82wW&EPYYKh3kI&Ea#Nj_eNac9UC84P*8v}a$xz0`W$Y4Xk9)PY)u@pU0MhEXIbw%(tIZ_5o{FIpG^J2ny z;b1xlGv9QcAKEs;x6$cYmMvCPEOPCD^DpVW{^8xZ429* z`h|@A+1bhcS#%~W8BZ(YHMf5*S} zS!8DNRKT`c2UK`3gQm1^zJ`z6(!fDQMIre0^i1dd6``yZP6T(!qp!F` zjf+PkR>V!P*Rlo^qI+{DHUmky9mj4oF~o?cR#8*a{p@YVgK!lPWvmMz#_(SOi|>9T zl;5MjJBi<vzsBLA9XAEQa?+kmt3&= z7h=v2-9-NivVa}7PxqMNLi~APF8-rI2($d-V84%H;gp0%{fD_#y#gB;1)`#)p;#hs G9`J9u_w2U- literal 67880 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 WGx+L3582lt2VfL2~ft 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�jHolL-@ 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

`|uF*P18GfZY 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

H53HiBtXp64XIXjR@M#h z9|#9NJ!#)0{^d(X((%-;3duzIZtqlEYR0De zR0lL&&8{srA$jLQ_>3qGC|I0DV8FNNzSh#(y8Zk2`3o2D8$~50K3-l+U~qBYe9?YC_BH$)*TfdXdb`V%tEk zN9>p$Cs+`d-_*uGeaglA+sveQdvh!pl1I>(wuO=oR-vnNb4r1ubwv*!9@5i$^Cvkj zMe%z%N%!#K&&MRi2M4Y=I|~ApKq6V0|7mTll{DuDr}Q&+S?|Tm#UCz92>lo^>{R{d z&t4VLn~9NM)#t}Fyq1Hb5 zON)PqiJ)bEO2NH${b0~9hT;+$UnMH)qso-WRl-S%SLW<9cFK4g7g7Dq3DT%6FGXOU zZ^zZ2boQV;WXtPZKJvRvK-$-JY3z>pkt1d6`Rfx?=B>$6JGZ|Sb-sQbTaJw!7#y^D z8x*jyxCzthw?4}&_wMC-Y?VUG=l@2@0gHW>#?K+}?2YHlL`upE-L0DXy84}@r%td) zNJ+U}dU-L4Om@e;Bmpqq-#6Bri}l<39v>eqA`)ad!zk#vI$fWV!m_AgYb#9{ad2og zH|=X_#lby#UK2u@3~so(_8l4k>&TChfPcDk+;%pryr_--#Ea?wj-1B&?^NDnKb)YH zm}H|Iu<?UrGc^ zOIJZAH6b{dupaHE++xNS!Y7+5-TF&oU77aB9CVuEw4a&M7$_6jah9NSF!ZMPoqa(({M4?P5Z~{5i*L3BV$g5LW~je4+d4>=t1vFi!?yj!%g`qnKDvUKal4)SoI`j`(TZjxtiwI zg5S|fvdXYcROk%^(LluwHTJ%J=`g=uHL>!ogvB;0{Qdq0^myC|(^5T+(Cz4)-DGK! zr&osjwaZf^wSIgh{zPxD{O{lI{C)MUYvhvy=M&9aWd+SjMwjN#xQ^Bx54y1*VMWE+ zWM}1?&|5$Cn;RXO*k0dz{@ihzG?s%W)%jUWOoS4NnzE@0)8!hG8~FUT_AaupV-f?R z1tZaWW}!}##!h+ZIr*<&kN3O`?(KV7R3v+NQU%i%!{>M^i-q2|r;iw*r-$c&AFSG$;{6morpDpA4UZeCReBvqg}kE)%@g!Yc@%Yc_u6sy!oqm~(#bnx?^XAz ze5Ixk_|gE%cLd0Xy2Zo_E`Q?+nC>hO^Zm1Jj@`@Py71I=K;R>$oNRfI zK=-n!x|M->e)(7;Bv(iWQ&kB6C}u&f=lLZH?p=Lvqk8MB;)M$rq@_#PRDXvIH^Ft! z(-~I*W~rev$4IF0!@|NoK^30DbTyO?lpfSaN~X9Sc!dA6Rz%@X|62~CuumZp|F^XC ee;)pat?EYZ6{_z`j_@rHh>qsP^Timud;bOBF=lfB literal 0 HcmV?d00001 diff --git a/doc/devel/uml/index.html b/doc/devel/uml/index.html index 1081df7d3..c05d6f597 100644 --- a/doc/devel/uml/index.html +++ b/doc/devel/uml/index.html @@ -36,7 +36,7 @@ Documentation

required classes : Fixture, SessionImpl

Component Session
-

provided classes : EDL, Fixture, MObject, ParamProvider, SessionImpl

+

provided classes : Seq, Fixture, MObject, ParamProvider, SessionImpl

Component EDL
@@ -83,8 +83,21 @@ Documentation
Component client code

required classes : ProcDispatcher

+ +

1.2 Class View Project Entities

+
+ +

+

TimelineSequences



+
Class Project
+
+
Class Monitor
+
+
Class Sequence
+
+
-

1.2 Component View interfaces

+

1.3 Component View interfaces

@@ -104,10 +117,10 @@ Documentation

provided classes : MediaAccessFacade

-

1.3 Package codegen

+

1.4 Package codegen

This package is used to organize code generation by BOUML. It is considered useless after having generated the initial code skeleton.

-

1.3.1 Deployment View EXE Deployment

+

1.4.1 Deployment View EXE Deployment

defines and lists how the Lumiera executable has to be created

@@ -122,14 +135,14 @@ Documentation

Artifact source

-

1.3.2 Package common

+

1.4.2 Package common

  • C++ namespace : lumiera

sourcecode package

Common library and helper classes

Diagram : Source Overview

-

1.3.2.1 Deployment View gen

+

1.4.2.1 Deployment View gen

defines source files to be generated by BOUML

@@ -148,26 +161,29 @@ Documentation
Artifact time

unified representation of a time point, including conversion functions

Artifact source associated with : Time

+ +
Artifact streamtype
+

Artifact source associated with : StreamType, Prototype, ImplFacade

-

1.3.2.2 Package error

+

1.4.2.2 Package error

  • C++ namespace : lumiera::error

Namespace for Exception Kinds

-

1.3.2.3 Package visitor

+

1.4.2.3 Package visitor

  • C++ namespace : lumiera::visitor

sub-namespace for visitor library implementation

-

1.3.3 Package backend

+

1.4.3 Package backend

  • C++ namespace : backend_interface

sourcecode package

Data backend classes here...

-

1.3.3.1 Deployment View gen

+

1.4.3.1 Deployment View gen

Artifact mediaaccessfacade
@@ -176,13 +192,13 @@ Documentation
-

1.3.4 Package proc

+

1.4.4 Package proc

  • C++ namespace : proc_interface

sourcecode package

All classes belonging to the (middle) processing layer

-

1.3.4.1 Deployment View gen

+

1.4.4.1 Deployment View gen

defines source files to be generated by BOUML

@@ -207,13 +223,13 @@ Documentation

Artifact source associated with : Frame

-

1.3.4.2 Package asset

+

1.4.4.2 Package asset

  • C++ namespace : asset

sourcecode package

Asset Management

-

1.3.4.2.1 Deployment View gen

+

1.4.4.2.1 Deployment View gen

defines source files to be generated by BOUML

@@ -286,14 +302,37 @@ Documentation

Artifact source associated with : DB

+ +

1.4.4.3 Package control

+

    +
  • C++ namespace : control
  • +
+

sourcecode package

The Processing and Render Controller,
and the Proc-Layer dispatcher

+ +

1.4.4.3.1 Deployment View gen

+

defines source files to be generated by BOUML

+
+ +
Artifact pathmanager
+

Manager for deciding the actual render strategy

+

Artifact source associated with : PathManager

+ +
Artifact renderstate
+

renderengine state manager

+

Artifact source associated with : RenderState

+ +
Artifact stypemanager
+

Artifact source associated with : STypeManager

+
+
-

1.3.4.3 Package mobject

+

1.4.4.4 Package mobject

  • C++ namespace : mobject

sourcecode package

MObject Subsystem
including the Session (EDL), Builder and Processing Controller

-

1.3.4.3.1 Deployment View gen

+

1.4.4.4.1 Deployment View gen

defines source files to be generated by BOUML

@@ -334,13 +373,13 @@ Documentation

Artifact source associated with : Interpolator

-

1.3.4.3.2 Package session

+

1.4.4.4.2 Package session

  • C++ namespace : mobject::session

sourcecode package

Everything concerning the EDL and Session, within the MObject Subsystem

-

1.3.4.3.2.1 Deployment View gen

+

1.4.4.4.2.1 Deployment View gen

defines source files to be generated by BOUML

@@ -354,7 +393,7 @@ Documentation
Artifact edl

the (high level) Edit Decision List within the current Session

-

Artifact source associated with : EDL

+

Artifact source associated with : Seq

Artifact fixture

the (low level) representation of the EDL with concrete placement data

@@ -428,13 +467,13 @@ Documentation
-

1.3.4.3.3 Package builder

+

1.4.4.4.3 Package builder

  • C++ namespace : mobject::builder

sourcecode package

The Builder creating the Render Engine,
located within the MObject Subsystem

-

1.3.4.3.3.1 Deployment View gen

+

1.4.4.4.3.1 Deployment View gen

defines source files to be generated by BOUML

@@ -463,35 +502,15 @@ Documentation

Artifact source associated with : NodeCreatorTool

- -

1.3.4.3.4 Package controller

-

    -
  • C++ namespace : mobject::controller
  • -
-

sourcecode package

The Processing and Render Controller,
located within the MObject Subsystem

- -

1.3.4.3.4.1 Deployment View gen

-

defines source files to be generated by BOUML

-
- -
Artifact pathmanager
-

Manager for deciding the actual render strategy

-

Artifact source associated with : PathManager

- -
Artifact renderstate
-

renderengine state manager

-

Artifact source associated with : RenderState

-
-
-

1.3.4.4 Package engine

+

1.4.4.5 Package engine

  • C++ namespace : engine

sourcecode package

The Core Render Engine

-

1.3.4.4.1 Deployment View gen

+

1.4.4.5.1 Deployment View gen

defines source files to be generated by BOUML

@@ -574,20 +593,20 @@ Documentation
-

1.3.5 Package gui

+

1.4.5 Package gui

  • C++ namespace : gui

sourcecode package

User Interface classes go here

-

1.3.5.1 Deployment View gen

+

1.4.5.1 Deployment View gen

defines source files to be generated by BOUML

-

1.3.6 Package tool

+

1.4.6 Package tool

sourcecode package

Tools and Utilities
(separate from the main cinelrra binary)

-

1.3.6.1 Deployment View gen

+

1.4.6.1 Deployment View gen

defines source files to be generated by BOUML

@@ -637,11 +656,69 @@ Documentation
Class DoRecurse
+ +

2.2 Package Control

+
+ +

2.2.1 Class View Controller Workings

+
+ +

+

Controller Entities



+ +

2.2.1.1 Activity configure Render

+

Pre Condition :

    Post Condition :

      + +

      +

      the render configuration flow



      + +
      Activity action pin Render Request
      +

      Direction : input

      Type :

      Selection :

        +
        Flow <flow>

        From Render Request To determine Render Params

        Weight :

          Guard :

            Selection :

              Transformation :

                + +
                Opaque activity action setup StateProxy
                +

                Defined in configure Render

                Pre Condition :

                  Post Condition :

                    Behavior :

                      +
                      Flow <flow>

                      From setup StateProxy To build necessary?

                      Weight :

                        Guard :

                          Selection :

                            Transformation :

                              + + +
                              Decision activity node build necessary?
                              +

                              Defined in configure Render

                              +
                              Flow <flow>

                              From build necessary? To build Render Engine

                              Weight :

                                Guard :

                                • OCL :
                                  +build necessary

                                Selection :

                                  Transformation :

                                    Flow <flow>

                                    From build necessary? To merge activity node

                                    Weight :

                                      Guard :

                                      • OCL :
                                        +reuse exiting Engine

                                      Selection :

                                        Transformation :

                                          + +
                                          Opaque activity action setup Build Params
                                          +

                                          Defined in configure Render

                                          Pre Condition :

                                            Post Condition :

                                              Behavior :

                                                + +
                                                Merge activity node
                                                +

                                                Defined in configure Render

                                                +
                                                Flow <flow>

                                                From merge activity node To activity final

                                                Weight :

                                                  Guard :

                                                    Selection :

                                                      Transformation :

                                                        + +

                                                        2.2.1.1.1 Expansion region determine Render Params

                                                        + +
                                                        Opaque activity action determine Render Params
                                                        +

                                                        Diagram : the render configuration flow

                                                        +

                                                        Defined in configure Render

                                                        Pre Condition :

                                                          Post Condition :

                                                            Behavior :

                                                              +
                                                              Flow <flow>

                                                              From determine Render Params To setup StateProxy

                                                              Weight :

                                                                Guard :

                                                                  Selection :

                                                                    Transformation :

                                                                      + +
                                                                      Opaque activity action build Render Engine
                                                                      +

                                                                      Defined in configure Render

                                                                      Pre Condition :

                                                                        Post Condition :

                                                                          Behavior :

                                                                            +
                                                                            Flow <flow>

                                                                            From build Render Engine To merge activity node

                                                                            Weight :

                                                                              Guard :

                                                                                Selection :

                                                                                  Transformation :

                                                                                    + + +
                                                                                    Activity final
                                                                                    +

                                                                                    Defined in configure Render

                                                                                    +
                                                                                    +
                                                                                    +
                                                                                    +
                                                                                    +
                                                                                    +
                                                                                    -

                                                                                    2.2 Package MObject

                                                                                    +

                                                                                    2.3 Package MObject

                                                                                    -

                                                                                    2.2.1 Class View Session

                                                                                    +

                                                                                    2.3.1 Class View Session

                                                                                    @@ -649,7 +726,9 @@ Documentation
                                                                                    Class Session
                                                                                    -
                                                                                    Class EDL
                                                                                    +
                                                                                    Class Timeline
                                                                                    +
                                                                                    +
                                                                                    Class Seq
                                                                                    Class Fixture
                                                                                    Class Segment
                                                                                    Class Track
                                                                                    @@ -677,16 +756,16 @@ Documentation
                                                                                    -

                                                                                    2.2.2 Package Builder

                                                                                    +

                                                                                    2.3.2 Package Builder

                                                                                    -

                                                                                    2.2.2.1 Class View Builder Workings

                                                                                    +

                                                                                    2.3.2.1 Class View Builder Workings

                                                                                    build process



                                                                                    This figure shows the process of building and starting a RenderEngine

                                                                                    -

                                                                                    2.2.2.1.1 Activity building the Engine

                                                                                    +

                                                                                    2.3.2.1.1 Activity building the Engine

                                                                                    Pre Condition :

                                                                                      Post Condition :

                                                                                        @@ -700,7 +779,7 @@ Documentation

                                                                                        Defined in building the Engine

                                                                                        Pre Condition :

                                                                                          Post Condition :

                                                                                            Behavior :

                                                                                              Flow <flow>

                                                                                              From configure Tools To fork activity node

                                                                                              Weight :

                                                                                                Guard :

                                                                                                  Selection :

                                                                                                    Transformation :

                                                                                                      -

                                                                                                      2.2.2.1.1.1 Expansion region establish partitioning

                                                                                                      +

                                                                                                      2.3.2.1.1.1 Expansion region establish partitioning

                                                                                                      Opaque activity action define segment
                                                                                                      @@ -727,7 +806,7 @@ Documentation

                                                                                                      Defined in building the Engine

                                                                                                      Flow <flow>

                                                                                                      From fork activity node To segment Tool

                                                                                                      Weight :

                                                                                                        Guard :

                                                                                                          Selection :

                                                                                                            Transformation :

                                                                                                              Flow <flow>

                                                                                                              From fork activity node To build Tool

                                                                                                              Weight :

                                                                                                                Guard :

                                                                                                                  Selection :

                                                                                                                    Transformation :

                                                                                                                      -

                                                                                                                      2.2.2.1.1.2 Expansion region build Processors

                                                                                                                      +

                                                                                                                      2.3.2.1.1.2 Expansion region build Processors

                                                                                                                      Activity object build Tool
                                                                                                                      @@ -771,65 +850,8 @@ Documentation
                                                                                                                      - -

                                                                                                                      2.2.3 Package Controller

                                                                                                                      -
                                                                                                                      - -

                                                                                                                      2.2.3.1 Class View Controller Workings

                                                                                                                      -
                                                                                                                      - -

                                                                                                                      -

                                                                                                                      Controller Entities



                                                                                                                      - -

                                                                                                                      2.2.3.1.1 Activity configure Render

                                                                                                                      -

                                                                                                                      Pre Condition :

                                                                                                                        Post Condition :

                                                                                                                          - -

                                                                                                                          -

                                                                                                                          the render configuration flow



                                                                                                                          - -
                                                                                                                          Activity action pin Render Request
                                                                                                                          -

                                                                                                                          Direction : input

                                                                                                                          Type :

                                                                                                                          Selection :

                                                                                                                            -
                                                                                                                            Flow <flow>

                                                                                                                            From Render Request To determine Render Params

                                                                                                                            Weight :

                                                                                                                              Guard :

                                                                                                                                Selection :

                                                                                                                                  Transformation :

                                                                                                                                    - -
                                                                                                                                    Opaque activity action setup StateProxy
                                                                                                                                    -

                                                                                                                                    Defined in configure Render

                                                                                                                                    Pre Condition :

                                                                                                                                      Post Condition :

                                                                                                                                        Behavior :

                                                                                                                                          -
                                                                                                                                          Flow <flow>

                                                                                                                                          From setup StateProxy To build necessary?

                                                                                                                                          Weight :

                                                                                                                                            Guard :

                                                                                                                                              Selection :

                                                                                                                                                Transformation :

                                                                                                                                                  - - -
                                                                                                                                                  Decision activity node build necessary?
                                                                                                                                                  -

                                                                                                                                                  Defined in configure Render

                                                                                                                                                  -
                                                                                                                                                  Flow <flow>

                                                                                                                                                  From build necessary? To build Render Engine

                                                                                                                                                  Weight :

                                                                                                                                                    Guard :

                                                                                                                                                    • OCL :
                                                                                                                                                      -build necessary

                                                                                                                                                    Selection :

                                                                                                                                                      Transformation :

                                                                                                                                                        Flow <flow>

                                                                                                                                                        From build necessary? To merge activity node

                                                                                                                                                        Weight :

                                                                                                                                                          Guard :

                                                                                                                                                          • OCL :
                                                                                                                                                            -reuse exiting Engine

                                                                                                                                                          Selection :

                                                                                                                                                            Transformation :

                                                                                                                                                              - -
                                                                                                                                                              Opaque activity action setup Build Params
                                                                                                                                                              -

                                                                                                                                                              Defined in configure Render

                                                                                                                                                              Pre Condition :

                                                                                                                                                                Post Condition :

                                                                                                                                                                  Behavior :

                                                                                                                                                                    - -
                                                                                                                                                                    Merge activity node
                                                                                                                                                                    -

                                                                                                                                                                    Defined in configure Render

                                                                                                                                                                    -
                                                                                                                                                                    Flow <flow>

                                                                                                                                                                    From merge activity node To activity final

                                                                                                                                                                    Weight :

                                                                                                                                                                      Guard :

                                                                                                                                                                        Selection :

                                                                                                                                                                          Transformation :

                                                                                                                                                                            - -

                                                                                                                                                                            2.2.3.1.1.1 Expansion region determine Render Params

                                                                                                                                                                            - -
                                                                                                                                                                            Opaque activity action determine Render Params
                                                                                                                                                                            -

                                                                                                                                                                            Diagram : the render configuration flow

                                                                                                                                                                            -

                                                                                                                                                                            Defined in configure Render

                                                                                                                                                                            Pre Condition :

                                                                                                                                                                              Post Condition :

                                                                                                                                                                                Behavior :

                                                                                                                                                                                  -
                                                                                                                                                                                  Flow <flow>

                                                                                                                                                                                  From determine Render Params To setup StateProxy

                                                                                                                                                                                  Weight :

                                                                                                                                                                                    Guard :

                                                                                                                                                                                      Selection :

                                                                                                                                                                                        Transformation :

                                                                                                                                                                                          - -
                                                                                                                                                                                          Opaque activity action build Render Engine
                                                                                                                                                                                          -

                                                                                                                                                                                          Defined in configure Render

                                                                                                                                                                                          Pre Condition :

                                                                                                                                                                                            Post Condition :

                                                                                                                                                                                              Behavior :

                                                                                                                                                                                                -
                                                                                                                                                                                                Flow <flow>

                                                                                                                                                                                                From build Render Engine To merge activity node

                                                                                                                                                                                                Weight :

                                                                                                                                                                                                  Guard :

                                                                                                                                                                                                    Selection :

                                                                                                                                                                                                      Transformation :

                                                                                                                                                                                                        - - -
                                                                                                                                                                                                        Activity final
                                                                                                                                                                                                        -

                                                                                                                                                                                                        Defined in configure Render

                                                                                                                                                                                                        -
                                                                                                                                                                                                        -
                                                                                                                                                                                                        -
                                                                                                                                                                                                        -
                                                                                                                                                                                                        -
                                                                                                                                                                                                        -

                                                                                                                                                                                                        2.2.4 Use Case View config examples

                                                                                                                                                                                                        +

                                                                                                                                                                                                        2.3.3 Use Case View config examples

                                                                                                                                                                                                        @@ -847,10 +869,10 @@ reuse exiting Engine

                                                                                                                                                                                                        Selection :

                                                                                                                                                                                                          Transformation
                                                                                                                                                                                                          Class instance

                                                                                                                                                                                                          type :Placement

                                                                                                                                                                                                          -

                                                                                                                                                                                                          2.3 Package RenderEngine

                                                                                                                                                                                                          +

                                                                                                                                                                                                          2.4 Package RenderEngine

                                                                                                                                                                                                          -

                                                                                                                                                                                                          2.3.1 Deployment View Engine Parts

                                                                                                                                                                                                          +

                                                                                                                                                                                                          2.4.1 Deployment View Engine Parts

                                                                                                                                                                                                          @@ -869,7 +891,7 @@ reuse exiting Engine

                                                                                                                                                                                                          Selection :

                                                                                                                                                                                                            Transformation
                                                                                                                                                                                                            Node State

                                                                                                                                                                                                            -

                                                                                                                                                                                                            2.3.2 Class View Engine Workings

                                                                                                                                                                                                            +

                                                                                                                                                                                                            2.4.2 Class View Engine Workings

                                                                                                                                                                                                            @@ -915,7 +937,7 @@ reuse exiting Engine

                                                                                                                                                                                                            Selection :

                                                                                                                                                                                                              Transformation

                                                                                                                                                                                                              -

                                                                                                                                                                                                              2.4 Use Case View Renderengine Use

                                                                                                                                                                                                              +

                                                                                                                                                                                                              2.5 Use Case View Renderengine Use

                                                                                                                                                                                                              @@ -943,11 +965,9 @@ reuse exiting Engine

                                                                                                                                                                                                              Selection :

                                                                                                                                                                                                                Transformation
                                                                                                                                                                                                                Class instance video1

                                                                                                                                                                                                                type :Track

                                                                                                                                                                                                                Class instance vid_A

                                                                                                                                                                                                                type :Clip

                                                                                                                                                                                                                attributes :

                                                                                                                                                                                                                Class instance aud_A

                                                                                                                                                                                                                type :Clip

                                                                                                                                                                                                                attributes :

                                                                                                                                                                                                                Class instance audio1

                                                                                                                                                                                                                type :Track

                                                                                                                                                                                                                Class instance

                                                                                                                                                                                                                type :ExplicitPlacement

                                                                                                                                                                                                                attributes :

                                                                                                                                                                                                                  @@ -958,9 +978,8 @@ reuse exiting Engine

                                                                                                                                                                                                                Selection :

                                                                                                                                                                                                                  Transformation
                                                                                                                                                                                                                  Class instance

                                                                                                                                                                                                                  type :Fixture

                                                                                                                                                                                                                  Class instance vid_A

                                                                                                                                                                                                                  type :Clip

                                                                                                                                                                                                                  attributes :

                                                                                                                                                                                                                  -
                                                                                                                                                                                                                  Class instance

                                                                                                                                                                                                                  type :EDL

                                                                                                                                                                                                                  +
                                                                                                                                                                                                                  Class instance

                                                                                                                                                                                                                  type :Seq

                                                                                                                                                                                                                  Class instance refPoint

                                                                                                                                                                                                                  type :Label

                                                                                                                                                                                                                  attributes :

                                                                                                                                                                                                                  @@ -969,7 +988,6 @@ reuse exiting Engine

                                                                                                                                                                                                                  Selection :

                                                                                                                                                                                                                    Transformation

                                                                                                                                                                                                                    Class instance vid_A

                                                                                                                                                                                                                    type :Clip

                                                                                                                                                                                                                    attributes :

                                                                                                                                                                                                                    Class instance

                                                                                                                                                                                                                    type :RelativeLocation

                                                                                                                                                                                                                    attributes :

                                                                                                                                                                                                                    • relType = SAMETIME
                                                                                                                                                                                                                    • @@ -978,7 +996,7 @@ reuse exiting Engine

                                                                                                                                                                                                                    Selection :

                                                                                                                                                                                                                      Transformation

                                                                                                                                                                                                                      Class instance

                                                                                                                                                                                                                      type :Effect

                                                                                                                                                                                                                      attributes :

                                                                                                                                                                                                                      Class instance

                                                                                                                                                                                                                      type :RelativeLocation

                                                                                                                                                                                                                      attributes :

                                                                                                                                                                                                                      • offset = +3
                                                                                                                                                                                                                      • @@ -988,7 +1006,7 @@ reuse exiting Engine

                                                                                                                                                                                                                      Selection :

                                                                                                                                                                                                                        Transformation

                                                                                                                                                                                                                        Class instance

                                                                                                                                                                                                                        type :Effect

                                                                                                                                                                                                                        attributes :

                                                                                                                                                                                                                        Class instance

                                                                                                                                                                                                                        type :ExplicitPlacement

                                                                                                                                                                                                                        attributes :

                                                                                                                                                                                                                        • time = 5
                                                                                                                                                                                                                        • @@ -1162,11 +1180,23 @@ reuse exiting Engine

                                                                                                                                                                                                                        Selection :

                                                                                                                                                                                                                          Transformation

                                                                                                                                                                                                                          GUI is here just a container to hold any entities considered to be User Interface related, which is not in focus for this Design draft

                                                                                                                                                                                                                          5 Package CommonLib

                                                                                                                                                                                                                          + +

                                                                                                                                                                                                                          5.1 Class View StreamType

                                                                                                                                                                                                                          +
                                                                                                                                                                                                                          + +

                                                                                                                                                                                                                          +

                                                                                                                                                                                                                          Stream Type Framework



                                                                                                                                                                                                                          +
                                                                                                                                                                                                                          +
                                                                                                                                                                                                                          Class Prototype
                                                                                                                                                                                                                          +
                                                                                                                                                                                                                          +
                                                                                                                                                                                                                          +
                                                                                                                                                                                                                          Class MediaKind
                                                                                                                                                                                                                          +
                                                                                                                                                                                                                          -

                                                                                                                                                                                                                          5.1 Package ConfigQuery

                                                                                                                                                                                                                          +

                                                                                                                                                                                                                          5.2 Package ConfigQuery

                                                                                                                                                                                                                          -

                                                                                                                                                                                                                          5.1.1 Component View Query System overview

                                                                                                                                                                                                                          +

                                                                                                                                                                                                                          5.2.1 Component View Query System overview

                                                                                                                                                                                                                          @@ -1182,7 +1212,7 @@ reuse exiting Engine

                                                                                                                                                                                                                          Selection :

                                                                                                                                                                                                                            Transformation
                                                                                                                                                                                                                            Component DefaultsManager

                                                                                                                                                                                                                            -

                                                                                                                                                                                                                            5.1.2 Class View query

                                                                                                                                                                                                                            +

                                                                                                                                                                                                                            5.2.2 Class View query

                                                                                                                                                                                                                            @@ -1198,27 +1228,27 @@ reuse exiting Engine

                                                                                                                                                                                                                            Selection :

                                                                                                                                                                                                                              Transformation

                                                                                                                                                                                                                              -

                                                                                                                                                                                                                              5.1.3 Use Case View query use

                                                                                                                                                                                                                              +

                                                                                                                                                                                                                              5.2.3 Use Case View query use

                                                                                                                                                                                                                              when to query



                                                                                                                                                                                                                              -

                                                                                                                                                                                                                              5.1.3.1 Use Case create specific object

                                                                                                                                                                                                                              +

                                                                                                                                                                                                                              5.2.3.1 Use Case create specific object

                                                                                                                                                                                                                              -

                                                                                                                                                                                                                              5.1.3.2 Use Case use "default" object

                                                                                                                                                                                                                              +

                                                                                                                                                                                                                              5.2.3.2 Use Case use "default" object

                                                                                                                                                                                                                              -

                                                                                                                                                                                                                              5.1.3.3 Use Case load object from session

                                                                                                                                                                                                                              +

                                                                                                                                                                                                                              5.2.3.3 Use Case load object from session

                                                                                                                                                                                                                              -

                                                                                                                                                                                                                              5.1.3.4 Use Case add new object to session

                                                                                                                                                                                                                              +

                                                                                                                                                                                                                              5.2.3.4 Use Case add new object to session

                                                                                                                                                                                                                              Class User
                                                                                                                                                                                                                              -

                                                                                                                                                                                                                              5.1.3.5 Use Case ConfigQuery

                                                                                                                                                                                                                              +

                                                                                                                                                                                                                              5.2.3.5 Use Case ConfigQuery

                                                                                                                                                                                                                              -

                                                                                                                                                                                                                              5.1.3.6 Use Case need sub object

                                                                                                                                                                                                                              +

                                                                                                                                                                                                                              5.2.3.6 Use Case need sub object

                                                                                                                                                                                                                              "default" object



                                                                                                                                                                                                                              @@ -1226,7 +1256,7 @@ reuse exiting Engine

                                                                                                                                                                                                                              Selection :

                                                                                                                                                                                                                                Transformation
                                                                                                                                                                                                                                Class instance predicate impl

                                                                                                                                                                                                                                type :TypeHandler

                                                                                                                                                                                                                                -

                                                                                                                                                                                                                                5.2 Class View error

                                                                                                                                                                                                                                +

                                                                                                                                                                                                                                5.3 Class View error

                                                                                                                                                                                                                                @@ -1240,7 +1270,7 @@ reuse exiting Engine

                                                                                                                                                                                                                                Selection :

                                                                                                                                                                                                                                  Transformation

                                                                                                                                                                                                                                  -

                                                                                                                                                                                                                                  5.3 Class View Service Components

                                                                                                                                                                                                                                  +

                                                                                                                                                                                                                                  5.4 Class View Service Components

                                                                                                                                                                                                                                  Class Tool
                                                                                                                                                                                                                                  @@ -1250,7 +1280,7 @@ reuse exiting Engine

                                                                                                                                                                                                                                  Selection :

                                                                                                                                                                                                                                    Transformation
                                                                                                                                                                                                                                    Class Appconfig

                                                                                                                                                                                                                                    -

                                                                                                                                                                                                                                    5.4 Class View Posix Threads Abstraction

                                                                                                                                                                                                                                    +

                                                                                                                                                                                                                                    5.5 Class View Posix Threads Abstraction

                                                                                                                                                                                                                                    C++ wrapers for pthreads

                                                                                                                                                                                                                                    Class Thread
                                                                                                                                                                                                                                    @@ -1258,7 +1288,7 @@ reuse exiting Engine

                                                                                                                                                                                                                                    Selection :

                                                                                                                                                                                                                                      Transformation
                                                                                                                                                                                                                                      Class Mutex

                                                                                                                                                                                                                                      -

                                                                                                                                                                                                                                      5.5 Class View SmartPointers

                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      5.6 Class View SmartPointers

                                                                                                                                                                                                                                      diff --git a/doc/devel/uml/index_60.html b/doc/devel/uml/index_60.html index a873c25b0..75ccc147d 100644 --- a/doc/devel/uml/index_60.html +++ b/doc/devel/uml/index_60.html @@ -17,8 +17,8 @@ - + @@ -28,8 +28,8 @@ - + diff --git a/doc/devel/uml/index_65.html b/doc/devel/uml/index_65.html index 33d5ebd2f..ab57596c5 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_67.html b/doc/devel/uml/index_67.html index 8432e5cc6..81d96139c 100644 --- a/doc/devel/uml/index_67.html +++ b/doc/devel/uml/index_67.html @@ -26,38 +26,38 @@ - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + @@ -96,9 +96,9 @@ + + - - diff --git a/doc/devel/uml/index_69.html b/doc/devel/uml/index_69.html index a7245b34b..4fe57adfd 100644 --- a/doc/devel/uml/index_69.html +++ b/doc/devel/uml/index_69.html @@ -19,7 +19,6 @@ - @@ -27,6 +26,7 @@ + diff --git a/doc/devel/uml/index_70.html b/doc/devel/uml/index_70.html index 56bc1daaf..77ab812da 100644 --- a/doc/devel/uml/index_70.html +++ b/doc/devel/uml/index_70.html @@ -36,8 +36,8 @@ - + diff --git a/doc/devel/uml/index_71.html b/doc/devel/uml/index_71.html index f4ad7d96d..75f10c74f 100644 --- a/doc/devel/uml/index_71.html +++ b/doc/devel/uml/index_71.html @@ -46,6 +46,7 @@ + diff --git a/doc/devel/uml/index_73.html b/doc/devel/uml/index_73.html index e127cf07e..963294360 100644 --- a/doc/devel/uml/index_73.html +++ b/doc/devel/uml/index_73.html @@ -18,11 +18,12 @@
                                                                                                                                                                                                                                      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
                                                                                                                                                                                                                                      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
                                                                                                                                                                                                                                      Categoryclasstree like classification of Assets
                                                                                                                                                                                                                                      categoryartifacttree like classification of Assets
                                                                                                                                                                                                                                      causeattributea copy of the first exception encountered in this exception chain
                                                                                                                                                                                                                                      chainoperationcreate and add another Placement for this media object, thus increasingly constraining the (possible) position of this object.
                                                                                                                                                                                                                                      chainrelationChain of additional Placements further constraining the position of this MObject
                                                                                                                                                                                                                                      chainoperationcreate and add another Placement for this media object, thus increasingly constraining the (possible) position of this object.
                                                                                                                                                                                                                                      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
                                                                                                                                                                                                                                      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.
                                                                                                                                                                                                                                      connectopaque activity action
                                                                                                                                                                                                                                      constraintartifactLocatingPin representing an directive by the user that
                                                                                                                                                                                                                                      must not be violated
                                                                                                                                                                                                                                      Constraintclass
                                                                                                                                                                                                                                      controlpackagesourcecode package

                                                                                                                                                                                                                                      The Processing and Render Controller,
                                                                                                                                                                                                                                      and the Proc-Layer dispatcher
                                                                                                                                                                                                                                      Controlpackage
                                                                                                                                                                                                                                      Controllercomponent
                                                                                                                                                                                                                                      Controllerpackage
                                                                                                                                                                                                                                      controllerpackagesourcecode package

                                                                                                                                                                                                                                      The Processing and Render Controller,
                                                                                                                                                                                                                                      located within the MObject Subsystem
                                                                                                                                                                                                                                      Controller Entitiesclass diagram
                                                                                                                                                                                                                                      Controller Workingsclass view
                                                                                                                                                                                                                                      ControllerFacadeclassProvides unified access to the Proc-Subsystem Controller. Especially, this Facade class provides the functions to get a render engine to carry out actual renderings.
                                                                                                                                                                                                                                      NameKindDescription
                                                                                                                                                                                                                                      edlartifactthe (high level) Edit Decision List within the current Session
                                                                                                                                                                                                                                      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
                                                                                                                                                                                                                                      effectartifactEDL representation of a pluggable and automatable effect.
                                                                                                                                                                                                                                      effectartifactEffect or media processing component
                                                                                                                                                                                                                                      Effectclass
                                                                                                                                                                                                                                      effectiveTimelinerelation
                                                                                                                                                                                                                                      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
                                                                                                                                                                                                                                      endattributeend of the timerange (excl)
                                                                                                                                                                                                                                      FixedLocationclass
                                                                                                                                                                                                                                      Fixtureactivity object
                                                                                                                                                                                                                                      fixtureartifactthe (low level) representation of the EDL with concrete placement data
                                                                                                                                                                                                                                      Fixturecomponent
                                                                                                                                                                                                                                      Fixtureclass
                                                                                                                                                                                                                                      Fixturecomponent
                                                                                                                                                                                                                                      fork activity nodefork activity node
                                                                                                                                                                                                                                      FrameclassFrames are just a low level lump of continous memory, most parts are opaque. Frames are memory sensitive, they will be small constant sized structures which can be efficently managed in a pool.
                                                                                                                                                                                                                                      Framenode
                                                                                                                                                                                                                                      getValueoperation
                                                                                                                                                                                                                                      GLBufclass
                                                                                                                                                                                                                                      glbufartifacta buffer and render process holding a Video frame for OpenGL rendering
                                                                                                                                                                                                                                      globalBussesrelation
                                                                                                                                                                                                                                      glpipeartifactspecialized connection element for handling OpenGL implementation details
                                                                                                                                                                                                                                      glrenderartifactRepresentation of a OpenGL accellerated Video render process
                                                                                                                                                                                                                                      groupsattributeadditional classification, selections or departments this asset belongs to. Groups are optional, non-exclusive and may be overlapping.
                                                                                                                                                                                                                                      + - - + + diff --git a/doc/devel/uml/index_77.html b/doc/devel/uml/index_77.html index e6d8e8031..c88824279 100644 --- a/doc/devel/uml/index_77.html +++ b/doc/devel/uml/index_77.html @@ -31,6 +31,7 @@ + @@ -40,6 +41,7 @@ +
                                                                                                                                                                                                                                      NameKindDescription
                                                                                                                                                                                                                                      idattributeAsset primary key.
                                                                                                                                                                                                                                      ImplFacadeclass
                                                                                                                                                                                                                                      In Memory Databaseclass diagram
                                                                                                                                                                                                                                      inFixtureactivity action pin
                                                                                                                                                                                                                                      inputclass instance
                                                                                                                                                                                                                                      inputclass instance
                                                                                                                                                                                                                                      inputclass instance
                                                                                                                                                                                                                                      inputclass instance
                                                                                                                                                                                                                                      inputclass instance
                                                                                                                                                                                                                                      instanceoperation
                                                                                                                                                                                                                                      instructionsrelation
                                                                                                                                                                                                                                      Interfaceclass view
                                                                                                                                                                                                                                      MediaAccessFacadeclassprovides functions for querying (opening) a media file, detecting the channels or streams found within this file, etc. Delegating to the actual backend functions
                                                                                                                                                                                                                                      MediaFactorycomponent
                                                                                                                                                                                                                                      MediaFactoryclassspecialized Asset Factory for configuring (new) media asset instances based on existing media files on disk; can create placeholder assets as well
                                                                                                                                                                                                                                      MediaKindclass
                                                                                                                                                                                                                                      merge activity nodemerge activity node
                                                                                                                                                                                                                                      Metaclasskey abstraction: metadata and organisational asset
                                                                                                                                                                                                                                      metaartifactkey abstraction: metadata and organisational asset
                                                                                                                                                                                                                                      mobjectpackagesourcecode package

                                                                                                                                                                                                                                      MObject Subsystem
                                                                                                                                                                                                                                      including the Session (EDL), Builder and Processing Controller
                                                                                                                                                                                                                                      MObjectpackage
                                                                                                                                                                                                                                      MObjectclass
                                                                                                                                                                                                                                      Monitorclass
                                                                                                                                                                                                                                      multichannel clipobject diagram
                                                                                                                                                                                                                                      MutexclassI provided a reworked Mutex class in my Cinelerra2 repository
                                                                                                                                                                                                                                      diff --git a/doc/devel/uml/index_80.html b/doc/devel/uml/index_80.html index 368babe6a..85ccb15d9 100644 --- a/doc/devel/uml/index_80.html +++ b/doc/devel/uml/index_80.html @@ -31,10 +31,12 @@ placementartifactKey Abstraction: a way to place and locate a Media Object Placementclassused to specify the position of a MObject in the EDL. This can be done in various ways (absolute, relative).
                                                                                                                                                                                                                                      Placement at the same time acts as (refcounting) smart pointer for accessing the MObject. playoperationTODO: will probably be handled differently (see Cehteh) +PlayControlclass +PlayheadCursorclass playlistnode plugartifactLocatingPin for requesting connection to some Port Plugclass -plugIDattributeIdentifier of the Plugin to be used +pluginattributeIdentifier of the Plugin to be used PluginAdapterclassAdapter used to integrage an effects processor in the render pipeline pluginadapterartifactAdapter for integrating various Effect processors in the render pipeline pnodenode @@ -63,8 +65,11 @@ procnodeartifactKey abstraction of the Render Engine: a Processing Node ProcPattclassspecial type of structural Asset representing information how to build some part of the render engine's processing nodes network. procpattartifacttemplate for building some render processing network +Projectclass +Project Entitiesclass view ProjectorclassSpecial video processing node used to scale and translate image data. projectorartifactvideo ProcNode for scaling and translating image data +Prototypeclass providerrelation pulloperation PullInputclass diff --git a/doc/devel/uml/index_82.html b/doc/devel/uml/index_82.html index 9b107d854..fd3368437 100644 --- a/doc/devel/uml/index_82.html +++ b/doc/devel/uml/index_82.html @@ -39,6 +39,7 @@ renderSegmentsrelation RenderStateclassEncapsulates the logic used to get a "current render process" in accordance to the currentyl applicable controller settings. The provided StateProxy serves to hold any mutalbe state used in the render process, so the rest of the render engine can be stateless. renderstateartifactrenderengine state manager +RenderTaskclass reprattributehuman readable representation of the condition characterizing this allocaton, e.g. "t >= 10" resetoperationreset all session config and
                                                                                                                                                                                                                                      start with a pristine default session. resolveoperationcreate an actual (explicit) placement while trying to satisfy the network of adjacent objects and placements. diff --git a/doc/devel/uml/index_83.html b/doc/devel/uml/index_83.html index 4ea8bf79b..e92c87510 100644 --- a/doc/devel/uml/index_83.html +++ b/doc/devel/uml/index_83.html @@ -28,12 +28,14 @@ segmentsactivity object segmentsactivity object segmentsrelationthe partitioning of the Timeline to be created by this tool. +Seqclass +Sequenceclass Serializerclass Service Componentsclass view Sessioncomponent sessionartifactInterface: the session edited by the user -Sessionclass view sessionpackagesourcecode package

                                                                                                                                                                                                                                      Everything concerning the EDL and Session, within the MObject Subsystem +Sessionclass view 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 @@ -52,7 +54,6 @@ SourceclassSource Node: represents a media source to pull data from. sourceartifactRepresentation of a Media source Source Overviewdeployment diagram -startattributestartpos in source startattributebegin of the timerange covered by this processor startattribute Stateclass @@ -65,11 +66,19 @@ stateproxyartifactKey Interface representing a render process and encapsulating state std::exceptionclass Strategyclass +Stream Type Frameworkclass diagram +StreamTypeclass view +streamtypeartifact +StreamTypeclass +StreamTypeIDclass Structclasskey abstraction: structural asset structartifactkey abstraction: structural asset Struct-Asset Relationsclass diagram +STypeManagerclass +stypemanagerartifact subjectrelationPlacement acts as smart pointer subPatternrelation +subSequencesrelation subTracksrelationChild tracks in a tree structure diff --git a/doc/devel/uml/index_84.html b/doc/devel/uml/index_84.html index 96532f18f..8f80d7c8d 100644 --- a/doc/devel/uml/index_84.html +++ b/doc/devel/uml/index_84.html @@ -20,35 +20,38 @@ the render configuration flowactivity diagram theApp_attributeholds the single instance and triggers initialization theFixturerelation -theTimelinerelation ThreadclassWe can basically reuse the Thread class design from Cinelerra2, Thread becomes a baseclass for all Threads timeattribute timeartifactunified representation of a time point, including conversion functions Timeclassdenotes a temporal position (time point), based on timeline start.

                                                                                                                                                                                                                                      investigate posix.4 realtime timers, wrap these here timelinenode +Timelineclass +TimelineSequencesclass diagram +TimelineViewclass toolpackagesourcecode package

                                                                                                                                                                                                                                      Tools and Utilities
                                                                                                                                                                                                                                      (separate from the main cinelrra binary) Toolclass ToolFactoryclass toolfactoryartifactsupply of Tool implementations for the Builder Trackclassstructural asset holding the configuration of a track in the EDL -trackrelation trackattribute trackrelation -trackartifactA grouping device within the EDL. The corresponding Placement
                                                                                                                                                                                                                                      by which this Track object is refered defines fallback placing
                                                                                                                                                                                                                                      properties to be used by all objects placed on this track in
                                                                                                                                                                                                                                      case they don't specify more concrete placements.
                                                                                                                                                                                                                                      Typically, tracks are used do make default Port connections,
                                                                                                                                                                                                                                      define a layer or pan for sound and for for disabling groups
                                                                                                                                                                                                                                      of clips. Note tracks are grouped in a tree like fashion.
                                                                                                                                                                                                                                      trackartifactstructural asset holding the configuration of a track in the EDL +trackartifactA grouping device within the EDL. The corresponding Placement
                                                                                                                                                                                                                                      by which this Track object is refered defines fallback placing
                                                                                                                                                                                                                                      properties to be used by all objects placed on this track in
                                                                                                                                                                                                                                      case they don't specify more concrete placements.
                                                                                                                                                                                                                                      Typically, tracks are used do make default Port connections,
                                                                                                                                                                                                                                      define a layer or pan for sound and for for disabling groups
                                                                                                                                                                                                                                      of clips. Note tracks are grouped in a tree like fashion.
                                                                                                                                                                                                                                      +trackrelation Trackclass tracksrelationelementary media assets comprising this compound +trackTreerelation Trafoclass 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 treatoperation +treatoperation TypeHandlerclass TypeHandler<Pipe>class diff --git a/doc/devel/uml/index_86.html b/doc/devel/uml/index_86.html index 3538c8202..203265efb 100644 --- a/doc/devel/uml/index_86.html +++ b/doc/devel/uml/index_86.html @@ -21,21 +21,21 @@ VFrameclass 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 -vid_aclass instance -videoclass instance videoclass instance videoclass instance videoclass instance -video1class instance -video1class instance -video1class instance +videoclass instance video1class instance +video1class instance +video1class instance video1class instance video1class instance +video1class instance Visitableclass visitorpackagesub-namespace for visitor library implementation visitorartifactAcyclic Visitor library diff --git a/doc/devel/uml/packages.html b/doc/devel/uml/packages.html index 49c0f4f80..25b52f427 100644 --- a/doc/devel/uml/packages.html +++ b/doc/devel/uml/packages.html @@ -20,14 +20,14 @@ Asset backendsrcsourcecode package

                                                                                                                                                                                                                                      Data backend classes here... BackendLayer -buildersrcsourcecode package

                                                                                                                                                                                                                                      The Builder creating the Render Engine,
                                                                                                                                                                                                                                      located within the MObject Subsystem Builder +buildersrcsourcecode package

                                                                                                                                                                                                                                      The Builder creating the Render Engine,
                                                                                                                                                                                                                                      located within the MObject Subsystem codegenThis package is used to organize code generation by BOUML. It is considered useless after having generated the initial code skeleton. commonsrcsourcecode package

                                                                                                                                                                                                                                      Common library and helper classes CommonLib ConfigQuery -Controller -controllersrcsourcecode package

                                                                                                                                                                                                                                      The Processing and Render Controller,
                                                                                                                                                                                                                                      located within the MObject Subsystem +controlsrcsourcecode package

                                                                                                                                                                                                                                      The Processing and Render Controller,
                                                                                                                                                                                                                                      and the Proc-Layer dispatcher +Control design designAll things concering the big picture.
                                                                                                                                                                                                                                      Not a real code package, rather a container for design drafts, specifications, decisions. enginesrcsourcecode package

                                                                                                                                                                                                                                      The Core Render Engine diff --git a/doc/devel/uml/public_operations.html b/doc/devel/uml/public_operations.html index 07fb079d7..fe9b01e39 100644 --- a/doc/devel/uml/public_operations.html +++ b/doc/devel/uml/public_operations.html @@ -69,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/uml/lumiera/128005 b/uml/lumiera/128005 index dc0adfe5f..d3970e39a 100644 --- a/uml/lumiera/128005 +++ b/uml/lumiera/128005 @@ -1,6 +1,6 @@ format 40 "design" // design - revision 11 + revision 13 modified_by 5 "hiv" // class settings //class diagram settings @@ -50,7 +50,7 @@ Not a real code package, rather a container for design drafts, specifications, d component 128005 "Builder" stereotype "subsystem" provided_classes - class_ref 132741 // StateProxy + class_ref 132741 // State end required_classes class_ref 128261 // Fixture @@ -61,7 +61,7 @@ Not a real code package, rather a container for design drafts, specifications, d component 128133 "Session" stereotype "subsystem" provided_classes - class_ref 128133 // EDL + class_ref 128133 // Seq class_ref 128261 // Fixture class_ref 128517 // MObject class_ref 134661 // ParamProvider @@ -99,7 +99,7 @@ Not a real code package, rather a container for design drafts, specifications, d component 128901 "Engine" required_classes - class_ref 132741 // StateProxy + class_ref 132741 // State end simplerelation 128133 -_-> @@ -151,6 +151,206 @@ Not a real code package, rather a container for design drafts, specifications, d end end + classview 129413 "Project Entities" + //class diagram settings + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + //collaboration diagram settings + show_full_operations_definition default show_hierarchical_rank default write_horizontally default drawing_language default package_name_in_tab default show_context default draw_all_relations default shadow default + //object diagram settings + write_horizontally default package_name_in_tab default show_context default auto_label_position default draw_all_relations default shadow default + //sequence diagram settings + show_full_operations_definition default write_horizontally default class_drawing_mode default drawing_language default draw_all_relations default shadow default + //state diagram settings + package_name_in_tab default show_context default auto_label_position default write_trans_label_horizontally default show_trans_definition default draw_all_relations default shadow default + show_activities default region_horizontally default drawing_language default + //class settings + //activity diagram settings + package_name_in_tab default show_context default show_opaque_action_definition default auto_label_position default write_flow_label_horizontally default draw_all_relations default shadow default + show_infonote default drawing_language default + + classdiagram 132741 "TimelineSequences" + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + size A4 + end + + class 145669 "Project" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 158981 // + relation 154885 *--- + a role_name "" multiplicity "1..*" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; +" + classrelation_ref 158981 // + b role_name "" multiplicity "1" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; +" + classrelation_ref 159109 // + end + + classrelation 159365 // + relation 155141 *--- + a role_name "" multiplicity "1..*" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; +" + classrelation_ref 159365 // + b role_name "" multiplicity "1" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; +" + classrelation_ref 159493 // + end + end + + class 145925 "PlayControl" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 160389 // + relation 156037 ---> + stereotype "direct" + a role_name "" multiplicity "*" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 160389 // + b multiplicity "" parent class_ref 146437 // PlayheadCursor + end + end + + class 146053 "Monitor" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 160133 // + relation 155781 ---> + stereotype "attach" + a role_name "" multiplicity "0..1" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 160133 // + b multiplicity "" parent class_ref 145541 // Timeline + end + + classrelation 160517 // + relation 156165 ---- + a role_name "" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 160517 // + b role_name "" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 160645 // + end + end + + class 146181 "RenderTask" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 160261 // + relation 155909 ---> + a role_name "" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 160261 // + b multiplicity "" parent class_ref 145541 // Timeline + end + end + + class 146309 "Sequence" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 159493 // + relation_ref 155141 // + end + + classrelation 159877 // subSequences () + relation 155525 ---> + stereotype "contains" + a role_name "subSequences" multiplicity "*" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 159877 // subSequences () + b multiplicity "1..*" parent class_ref 146309 // Sequence + end + + classrelation 161541 // + relation 156933 ---> + a role_name "" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 161541 // + b multiplicity "" parent class_ref 128517 // MObject + end + + classrelation 161669 // trackTree () + relation 157061 ---> + a role_name "trackTree" multiplicity "1" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 161669 // trackTree () + b multiplicity "" parent class_ref 128389 // Track + end + end + + class 146437 "PlayheadCursor" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 160645 // + relation_ref 156165 // + end + + classrelation 160901 // + relation_ref 156293 // + end + end + end + componentview 128133 "interfaces" //component diagram settings package_name_in_tab default show_context default auto_label_position default draw_all_relations default shadow default diff --git a/uml/lumiera/128133.diagram b/uml/lumiera/128133.diagram index 466c2ad1d..1fbd686ec 100644 --- a/uml/lumiera/128133.diagram +++ b/uml/lumiera/128133.diagram @@ -4,7 +4,7 @@ classcanvas 128005 class_ref 128005 // SessionImpl draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 18 679 2000 end -classcanvas 128133 class_ref 128133 // EDL +classcanvas 128133 class_ref 128133 // Seq draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 231 679 2000 end @@ -34,11 +34,11 @@ classcanvas 130949 class_ref 128773 // AbstractMO end classcanvas 131461 class_ref 128901 // Clip draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 279 361 2000 + xyz 279 368 2000 end classcanvas 131717 class_ref 129029 // Effect draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default - xyz 332 361 2000 + xyz 332 368 2000 end classcanvas 131973 class_ref 129157 // Meta draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default @@ -74,10 +74,8 @@ classcanvas 136581 class_ref 129925 // Auto end note 136837 "Placement \"locates\" a Media Object" xyzwh 370 73 3005 207 36 -textcanvas 136965 "the Timeline is a list of placements reduced to absolute coordinates (time, track)" - xyzwh 468 919 2000 121 90 textcanvas 137093 "Fixture is the actual assembly of various Media Objects ready to be performed" - xyzwh -27 863 2000 147 108 + xyzwh 28 862 2000 151 86 classcanvas 137221 class_ref 130053 // Wish draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 560 532 2000 @@ -114,8 +112,10 @@ classcanvas 146437 class_ref 140421 // Plug draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default xyz 560 597 2000 end -textcanvas 146821 "global processing Pipe Asset" - xyzwh 271 568 2000 149 24 +classcanvas 146949 class_ref 145541 // Timeline + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 114 546 2000 + end relationcanvas 128389 relation_ref 128005 // from ref 128005 z 1999 to ref 128133 role_a_pos 200 676 3000 no_role_b @@ -173,7 +173,7 @@ relationcanvas 135685 relation_ref 130949 // no_multiplicity_a no_multiplicity_b relationcanvas 135941 relation_ref 131077 // from ref 128261 z 1999 stereotype "<>" xyz 371 893 3000 to ref 135813 - role_a_pos 389 857 3000 no_role_b + role_a_pos 365 849 3000 no_role_b multiplicity_a_pos 451 877 3000 no_multiplicity_b relationcanvas 136069 relation_ref 131205 // from ref 135813 z 1999 to point 433 897 @@ -258,21 +258,16 @@ relationcanvas 145285 relation_ref 145029 // from ref 129029 z 1999 stereotype "<>" xyz 389 732 3000 to point 445 749 line 145413 z 1999 to point 369 749 line 145541 z 1999 to ref 129029 - role_a_pos 382 748 3000 no_role_b - multiplicity_a_pos 403 704 3000 no_multiplicity_b + role_a_pos 390 750 3000 no_role_b + multiplicity_a_pos 410 715 3000 no_multiplicity_b relationcanvas 145669 relation_ref 145157 // from ref 128133 z 1999 to ref 129029 - role_a_pos 376 681 3000 no_role_b + role_a_pos 392 672 3000 no_role_b no_multiplicity_a no_multiplicity_b relationcanvas 145925 relation_ref 145413 // from ref 128261 z 1999 to ref 129925 role_a_pos 321 978 3000 no_role_b no_multiplicity_a no_multiplicity_b -relationcanvas 146181 relation_ref 145541 // - from ref 128005 z 1999 to point 311 616 - line 146309 z 1999 stereotype "<>" xyz 103 649 3000 to ref 146053 - role_a_pos 307 594 3000 no_role_b - multiplicity_a_pos 329 627 3000 no_multiplicity_b relationcanvas 146565 relation_ref 145669 // from ref 146437 z 1999 to ref 137221 no_role_a no_role_b @@ -281,4 +276,8 @@ relationcanvas 146693 relation_ref 145797 // from ref 146437 z 1999 to ref 146053 role_a_pos 398 594 3000 no_role_b no_multiplicity_a no_multiplicity_b +relationcanvas 147077 relation_ref 155653 // + from ref 146949 z 1999 stereotype "<>" xyz 191 582 3000 to ref 146053 + role_a_pos 285 575 3000 no_role_b + multiplicity_a_pos 327 613 3000 multiplicity_b_pos 180 584 3000 end diff --git a/uml/lumiera/128261 b/uml/lumiera/128261 index c4b03ca90..0d01de253 100644 --- a/uml/lumiera/128261 +++ b/uml/lumiera/128261 @@ -1,6 +1,6 @@ format 40 "MObject" // ProcessingLayer::MObject - revision 32 + revision 33 modified_by 5 "hiv" // class settings //class diagram settings @@ -62,7 +62,7 @@ ${inlines} comment "Primary 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." operation 133509 "currEDL" - public return_type class_ref 128133 // EDL + public return_type class_ref 128133 // Seq nparams 0 cpp_decl " ${comment}${friend}${static}${inline}${virtual}${type} ${name} ${(}${)}${const}${volatile} ${throw}${abstract};" cpp_def "${comment}${inline}${type} @@ -133,7 +133,7 @@ ${inlines} cpp default " ${comment}${static}${mutable}${volatile}${const}${stereotype}<${type}> ${name}${value}; " classrelation_ref 128005 // edls () - b multiplicity "" parent class_ref 128133 // EDL + b multiplicity "" parent class_ref 128133 // Seq end classrelation 128261 // theFixture () @@ -250,7 +250,93 @@ of the current session config and contents. end end - class 128133 "EDL" + class 145541 "Timeline" + abstract visibility public + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 159109 // + relation_ref 154885 // + end + + classrelation 159237 // + relation 155013 ---> + stereotype "own" + a role_name "" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 159237 // + b multiplicity "" parent class_ref 145925 // PlayControl + end + + classrelation 159621 // + relation 155269 ---> + a role_name "" multiplicity "1" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 159621 // + b multiplicity "" parent class_ref 146309 // Sequence + end + + classrelation 160005 // globalBusses () + relation 155653 *--> + stereotype "list" + a role_name "globalBusses" multiplicity "*" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; +" + classrelation_ref 160005 // globalBusses () + b multiplicity "1" parent class_ref 138117 // Pipe + end + end + + class 145797 "TimelineView" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 158853 // + relation 154757 -_-|> + a public + cpp default "${type}" + classrelation_ref 158853 // + b multiplicity "" parent class_ref 145541 // Timeline + end + + classrelation 159749 // + relation 155397 ---> + a role_name "" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 159749 // + b multiplicity "" parent class_ref 146309 // Sequence + end + + classrelation 160773 // + relation 156293 ---- + a role_name "" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 160773 // + b role_name "" multiplicity "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 160901 // + end + end + + class 128133 "Seq" visibility package cpp_decl "${comment}${template}class ${name}${inherit} { @@ -298,16 +384,16 @@ ${inlines} a public cpp default "${type}" classrelation_ref 128517 // - b multiplicity "" parent class_ref 128133 // EDL + b multiplicity "" parent class_ref 128133 // Seq end - classrelation 131717 // theTimeline () + classrelation 131717 // effectiveTimeline () relation 131077 *--> stereotype "list" - a role_name "theTimeline" multiplicity "*" protected + a role_name "effectiveTimeline" multiplicity "*" protected cpp default " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; " - classrelation_ref 131717 // theTimeline () + classrelation_ref 131717 // effectiveTimeline () b multiplicity "" parent class_ref 129797 // ExplicitPlacement end @@ -423,6 +509,14 @@ ${inlines} b multiplicity "" parent class_ref 128389 // Track association_type class_ref 128645 // Placement end + + classrelation 161413 // + relation 156805 -_-|> + a public + cpp default "${type}" + classrelation_ref 161413 // + b multiplicity "" parent class_ref 128517 // MObject + end end class 128517 "MObject" @@ -618,16 +712,6 @@ ${inlines} b multiplicity "" parent class_ref 128773 // AbstractMO end - attribute 128645 "start" - protected type class_ref 134917 // Time - init_value "Time(0)" - cpp_decl " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; -" - java_decl "" - idl_decl "" - comment "startpos in source" - end - classrelation 142469 // source () relation 140677 ---> a role_name "source" multiplicity "1" protected @@ -637,6 +721,14 @@ ${inlines} classrelation_ref 142469 // source () b multiplicity "*" parent class_ref 136709 // Media end + + classrelation 161029 // + relation 156421 -_-|> + a public + cpp default "${type}" + classrelation_ref 161029 // + b multiplicity "" parent class_ref 128517 // MObject + end end class 138885 "SimpleClip" @@ -711,7 +803,7 @@ ${inlines} b multiplicity "" parent class_ref 128773 // AbstractMO end - attribute 128901 "plugID" + attribute 128901 "plugin" protected explicit_type "string" cpp_decl " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; " @@ -719,6 +811,14 @@ ${inlines} idl_decl "" comment "Identifier of the Plugin to be used" end + + classrelation 161157 // + relation 156549 -_-|> + a public + cpp default "${type}" + classrelation_ref 161157 // + b multiplicity "" parent class_ref 128517 // MObject + end end class 129157 "Meta" @@ -911,6 +1011,14 @@ ${inlines} classrelation_ref 130949 // b multiplicity "" parent class_ref 129157 // Meta end + + classrelation 161285 // + relation 156677 -_-|> + a public + cpp default "${type}" + classrelation_ref 161285 // + b multiplicity "" parent class_ref 128517 // MObject + end end class 129925 "Auto" diff --git a/uml/lumiera/129029 b/uml/lumiera/129029 index 5c7a2a6f4..e091ca09b 100644 --- a/uml/lumiera/129029 +++ b/uml/lumiera/129029 @@ -1,6 +1,6 @@ format 40 "Control" // ProcessingLayer::Control - revision 6 + revision 7 modified_by 5 "hiv" // class settings //class diagram settings diff --git a/uml/lumiera/129285 b/uml/lumiera/129285 index 4ff722e2d..4089706c0 100644 --- a/uml/lumiera/129285 +++ b/uml/lumiera/129285 @@ -1,6 +1,6 @@ format 40 "ProcessingLayer" // ProcessingLayer - revision 23 + revision 24 modified_by 5 "hiv" // class settings //class diagram settings @@ -120,8 +120,6 @@ format 40 attributes attribute_ref 128517 // length "5" - attribute_ref 128645 // start - "100" end relations end @@ -132,8 +130,6 @@ format 40 attributes attribute_ref 128517 // length "8820" - attribute_ref 128645 // start - "176400" end relations end @@ -180,15 +176,13 @@ format 40 attributes attribute_ref 128517 // length "5" - attribute_ref 128645 // start - "100" end relations end end classinstance 129541 "" - type class_ref 128133 // EDL + type class_ref 128133 // Seq attributes end relations @@ -220,8 +214,6 @@ format 40 attributes attribute_ref 128517 // length "5" - attribute_ref 128645 // start - "100" end relations end @@ -244,7 +236,7 @@ format 40 attributes attribute_ref 128517 // length "3" - attribute_ref 128901 // plugID + attribute_ref 128901 // plugin "\"Hue\"" end relations @@ -270,7 +262,7 @@ format 40 attributes attribute_ref 128517 // length "3" - attribute_ref 128901 // plugID + attribute_ref 128901 // plugin "\"Hue\"" end relations diff --git a/uml/lumiera/5.session b/uml/lumiera/5.session index af68f0264..d04da5e91 100644 --- a/uml/lumiera/5.session +++ b/uml/lumiera/5.session @@ -1,24 +1,30 @@ window_sizes 1302 1004 270 1022 854 71 diagrams - classdiagram_ref 131973 // Render Mechanics - 407 690 100 4 2 0 - collaborationdiagram_ref 132229 // Render Process - 825 684 100 4 0 0 - classdiagram_ref 132357 // StateAdapter composition - 414 658 100 4 0 0 - active classdiagram_ref 132485 // Stream Type Framework - 463 594 100 4 0 0 + classdiagram_ref 128133 // Session structure + 853 742 100 4 120 0 + active classdiagram_ref 132741 // TimelineSequences + 585 732 100 4 0 0 end show_stereotypes selected package_ref 129 // lumiera open + class_ref 145925 // PlayControl deploymentview_ref 128261 // gen deploymentview_ref 129157 // gen package_ref 130181 // mobject classview_ref 128389 // Controller Workings - class_ref 132741 // State + class_ref 139653 // Session + class_ref 128005 // SessionImpl + class_ref 145541 // Timeline + class_ref 145797 // TimelineView + class_ref 128133 // Seq + class_ref 128389 // Track + class_ref 128901 // Clip + class_ref 129029 // Effect + + package_ref 128901 // Builder class_ref 131717 // ProcNode class_ref 142469 // StateProxy class_ref 142597 // StateAdapter @@ -32,7 +38,6 @@ open class_ref 144517 // Strategy class_ref 144005 // BuffTable class_ref 144261 // Invocation - usecaseview_ref 128005 // Renderengine Use classview_ref 129285 // StreamType classview_ref 128773 // error class_ref 140165 // Visitable diff --git a/uml/lumiera/lumiera.prj b/uml/lumiera/lumiera.prj index a533da6cc..1017e01e2 100644 --- a/uml/lumiera/lumiera.prj +++ b/uml/lumiera/lumiera.prj @@ -1,6 +1,6 @@ format 40 "lumiera" - revision 48 + revision 49 modified_by 5 "hiv" cpp_root_dir "../../src/" diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 26659922d..01c9a849d 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -4753,11 +4753,11 @@ function addKeyDownHandlers(e)
                                                                                                                                                                                                                                      http://tiddlywiki.com/
                                                                                                                                                                                                                                      -
                                                                                                                                                                                                                                      -
                                                                                                                                                                                                                                      Timeline is the top level element within the [[Session (Project)|Session]]. It is visible within a //timeline view// in the GUI and represents the definitive arrangement of media objects, to be rendered for output or viewed in a Monitor (viewer window). A timeline is comprised of:
                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Timeline is the top level element within the [[Session (Project)|Session]]. It is visible within a //timeline view// in the GUI and represents the effective (resulting) arrangement of media objects, to be rendered for output or viewed in a Monitor (viewer window). A timeline is comprised of:
                                                                                                                                                                                                                                       * a time axis in abolute time (WIP: not clear if this is an entity or just a conceptual definition) 
                                                                                                                                                                                                                                       * a PlayControler
                                                                                                                                                                                                                                      -* a list of global Pipes representing the possible outputs
                                                                                                                                                                                                                                      +* a list of global Pipes representing the possible outputs (master busses)
                                                                                                                                                                                                                                       * //exactly one// top-level [[EDL (Sequence)|EDL]], which in turn may contain further nested ~EDLs (Sequences).
                                                                                                                                                                                                                                       Please note especially that following this design //a timeline doesn't define tracks.// [[Tracks form a Tree|Track]] and are part of the individual ~EDLs (Sequences), together with the media objects placed to these tracks.
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      @@ -4766,11 +4766,20 @@ Within the Project, there may be ''multiple timelines'', to be viewed and render
                                                                                                                                                                                                                                       ''Note'': in early drafts of the design (2007) there was an entity called "Timeline" within the [[Fixture]]. This entity seems superfluous and has been dropped. It never got any relevance in existing code and at most was used in some code comments.
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      -
                                                                                                                                                                                                                                      -
                                                                                                                                                                                                                                      Each Project can contain ''multiple timelines'', to be viewed and rendered independently. But, being the top-level entities, multiple timelines may not be combined further. You can always just render (or view) one specific timeline. Of course it is possible to use ~Sub-EDLs (~Sub-Sequences) within the top-level Sequence within a timeline to organize a movie into several scenes or chapters. 
                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      There is a three-level hierarchy: [[Project|Session]], [[Timeline]], [[Sequence|EDL]]. Each project can contain ''multiple timelines'', to be viewed and rendered independently. But, being the top-level entities, these timelines may not be combined further. You can always just render (or view) one specific timeline. Each of those timelines refers to a Sequence, which is a bunch of [[media objects|MObject]] placed to a tree of [[tracks|Track]]. Of course it is possible to use ~Sub-EDLs (Sub-sequences) within the top-level sequence within a timeline to organize a movie into several scenes or chapters. 
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      -As stated in the [[definition|Timeline]], a timeline refers to exactly one EDL (Sequence), and the latter defines a tree of [[tracks|Track]] and a bunch of media objects placed to these tracks. A Sequence may optionally also contain nested sequences as [[meta-clips|MetaClip]]. Moreover, obviously several timelines (top-level entities) may refer to the same Sequence without problems.
                                                                                                                                                                                                                                      -This is because the top-level entities (Timelines) are not permitted to be combined further. You may play or render a given timeline, you may even play several timelines simultanously in different monitor windows, and these different timelines may incorporate the same sequence in a different way
                                                                                                                                                                                                                                      +[>img[Relation of Timelines, Sequences and MObjects within the Project|uml/fig132741.png]]
                                                                                                                                                                                                                                      +As stated in the [[definition|Timeline]], a timeline refers to exactly one EDL (Sequence), and the latter defines a tree of [[tracks|Track]] and a bunch of media objects placed to these tracks. A Sequence may optionally also contain nested sequences as [[meta-clips|VirtualClip]]. Moreover, obviously several timelines (top-level entities) may refer to the same Sequence without problems.
                                                                                                                                                                                                                                      +This is because the top-level entities (Timelines) are not permitted to be combined further. You may play or render a given timeline, you may even play several timelines simultaneously in different monitor windows, and these different timelines may incorporate the same sequence in a different way. The Sequence just defines the relations between some objects and may be placed relatively to another object (clip, label,...) or similar reference point, or even anchored at an absolute time if desired. In a similar open fashion, within the track-tree of a sequence, we may define a specific signal routing, or we may just fall back to automatic output wiring.
                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      +!Attaching output
                                                                                                                                                                                                                                      +The Timeline owns a list of global [[pipes (busses)|Pipe]] which are used to collect output. If the track tree of a sequence doesn't contain specific routing advice, then connections will be done directly to these global pipes in order and by matching StreamType (i.e. typically video to video master, audio to stereo audio master). When a monitor (viewer window) is attached to this timeline, similar output connections are made from those global pipes, i.e. the video display will take the contents of the first video (master) bus, and the first stereo audio pipe will be pulled and sent to system audio out. The timeline owns a ''play control'' shared by all attached viewers and coordinating the rendering-for-viewing. Similarly, a render task may be attached to the timeline to pull the pipes needed for a given kind of generated output. The actual implementation of the play controller and the coordination of render tasks is located in the Backend, which uses the service of the Proc-Layer to pull the respective exit nodes of the render engine network.
                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      +!Timeline versus Timeline View
                                                                                                                                                                                                                                      +Actually, what the GUI creates and uses is the //view// of a given timeline. This makes no difference to start with, as the view is modelled to be a sub-concept of "timeline" and thus can stand-in. All different views of the //same// timeline also share one single play control instance, i.e. they all have one single playhead position. Doing it this way should be the default, because it's the least confusing. Anyway, it's also possible to create multiple //independent timelines// &mdash; in an extreme case even so when referring to the same top-level sequence. This configuration gives the ability to play the same arrangement in parallel with multiple independent play controllers (and thus independent playhead positions)
                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      +To complement this possibilities, I'd propose to give the //timeline view// the possibility to be re-linked to a sub-sequence. This way, it would stay connected to the main play control, but at the same time show a sub-sequence //in the way it will be treated as  embedded// within the top-level sequence. This would be the default operation mode when a meta-clip is opened (and showed in a separate tab with such a linked timeline view). The reason for this proposed handling is again to give the user the least surprising behaviour. Because, when &mdash; on the contrary &mdash; the sub-sequence would be opened as //separate timeline,// a different absolute time position and a different signal routing may result; doing such should be reserved for advanced use, e.g. when multiple editors cooperate on a single project and a sequence has to be prepared in isolation prior to being integrated in the global sequence (featuring the whole movie).
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      From a21a6b5d3dd803d09e7a5ff567b781e73a06154f Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Mon, 3 Nov 2008 08:00:32 +0100 Subject: [PATCH 40/59] Add dependencies to test-interfaces looks like one needs to add all dependencies manually when using _DEPENDENCIES at least works by that, maybe investigate this later --- tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 66367ffb4..a88377b92 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -72,6 +72,6 @@ check_PROGRAMS += test-interfaces test_interfaces_SOURCES = $(tests_srcdir)/backend/test-interfaces.c test_interfaces_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror test_interfaces_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) -lm -test_interfaces_DEPENDENCIES = examplepluginc.la +test_interfaces_DEPENDENCIES = examplepluginc.la liblumibackend.a liblumiera.a TESTS = $(tests_srcdir)/test.sh From 257b310699e3baf4bf9b491d7588d26a888bcbb7 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Mon, 3 Nov 2008 08:03:48 +0100 Subject: [PATCH 41/59] add an error_peek function, fix prototypes lumiera_error_peek() lets one investigate the error state without resetting it. --- src/lib/error.c | 11 ++++++++++- src/lib/error.h | 14 +++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/lib/error.c b/src/lib/error.c index 1d3fb50c3..6007dcbdb 100644 --- a/src/lib/error.c +++ b/src/lib/error.c @@ -60,7 +60,7 @@ lumiera_error_set (lumiera_err nerr) lumiera_err -lumiera_error () +lumiera_error (void) { pthread_once (&lumiera_error_initialized, lumiera_error_tls_init); @@ -69,3 +69,12 @@ lumiera_error () pthread_setspecific (lumiera_error_tls, NULL); return err; } + + +lumiera_err +lumiera_error_peek (void) +{ + pthread_once (&lumiera_error_initialized, lumiera_error_tls_init); + + return pthread_getspecific (lumiera_error_tls); +} diff --git a/src/lib/error.h b/src/lib/error.h index 5c4a8c145..5ad8a3142 100644 --- a/src/lib/error.h +++ b/src/lib/error.h @@ -88,7 +88,19 @@ lumiera_error_set (lumiera_err err); * @return pointer to any pending error of this thread, NULL if no error is pending */ lumiera_err -lumiera_error (); +lumiera_error (void); + + +/** + * Check current error state without clearing it + * Please avoid this function and use lumiera_error() if possible. Errors must be cleared else certain + * parts of the application refuse to cooperate with you. This shall only be used to decide if one + * wants to barf out of a loop or subroutine to deliver the error to a higher level. + * @return pointer to any pending error of this thread, NULL if no error is pending + */ +lumiera_err +lumiera_error_peek (void); + /* predefined errors From 2342c3a87ad519b0879ed0c191260dd3fce9080b Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Mon, 3 Nov 2008 08:07:22 +0100 Subject: [PATCH 42/59] New Plugin implementation * plugin{.h,.c} are back but work in progress * the interfaceregistry also manages a pluginregistry, makes no much sense to isolate it yet, both share a mutex and are commonly used together --- src/backend/Makefile.am | 2 + src/backend/interfaceregistry.c | 29 ++- src/backend/plugin.c | 374 +++++++++++--------------------- src/backend/plugin.h | 18 +- 4 files changed, 160 insertions(+), 263 deletions(-) diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index da39e71c6..be9b9cd90 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -29,6 +29,7 @@ liblumibackend_a_SOURCES = \ $(liblumibackend_a_srcdir)/filehandlecache.c \ $(liblumibackend_a_srcdir)/interface.c \ $(liblumibackend_a_srcdir)/interfaceregistry.c \ + $(liblumibackend_a_srcdir)/plugin.c \ $(liblumibackend_a_srcdir)/config.c \ $(liblumibackend_a_srcdir)/config_typed.c \ $(liblumibackend_a_srcdir)/config_wordlist.c \ @@ -47,6 +48,7 @@ noinst_HEADERS += \ $(liblumibackend_a_srcdir)/interface.h \ $(liblumibackend_a_srcdir)/interfaceregistry.h \ $(liblumibackend_a_srcdir)/interfacedescriptor.h \ + $(liblumibackend_a_srcdir)/plugin.h \ $(liblumibackend_a_srcdir)/config.h \ $(liblumibackend_a_srcdir)/configentry.h \ $(liblumibackend_a_srcdir)/configitem.h \ diff --git a/src/backend/interfaceregistry.c b/src/backend/interfaceregistry.c index cc175dd0a..05e2224a1 100644 --- a/src/backend/interfaceregistry.c +++ b/src/backend/interfaceregistry.c @@ -29,6 +29,7 @@ +#include "backend/plugin.h" #include "backend/interfaceregistry.h" /** @@ -39,17 +40,20 @@ */ NOBUG_DEFINE_FLAG_PARENT (interface_all, backend); +NOBUG_DEFINE_FLAG_PARENT (plugin, interface_all); NOBUG_DEFINE_FLAG_PARENT (interfaceregistry, interface_all); NOBUG_DEFINE_FLAG_PARENT (interface, interface_all); PSplay lumiera_interfaceregistry; +PSplay lumiera_pluginregistry; lumiera_mutex lumiera_interface_mutex; static int -cmp_fn (const void* keya, const void* keyb); +lumiera_interface_cmp_fn (const void* keya, const void* keyb); static const void* -key_fn (const PSplaynode node); +lumiera_interface_key_fn (const PSplaynode node); + static LumieraInterfacenode @@ -92,13 +96,20 @@ lumiera_interfaceregistry_init (void) NOBUG_INIT_FLAG (interface_all); NOBUG_INIT_FLAG (interfaceregistry); NOBUG_INIT_FLAG (interface); + NOBUG_INIT_FLAG (plugin); + TRACE (interfaceregistry); REQUIRE (!lumiera_interfaceregistry); + REQUIRE (!lumiera_pluginregistry); - lumiera_interfaceregistry = psplay_new (cmp_fn, key_fn, NULL); + lumiera_interfaceregistry = psplay_new (lumiera_interface_cmp_fn, lumiera_interface_key_fn, NULL); if (!lumiera_interfaceregistry) LUMIERA_DIE (ERRNO); + lumiera_pluginregistry = psplay_new (lumiera_plugin_cmp_fn, lumiera_plugin_key_fn, NULL); + if (!lumiera_pluginregistry) + LUMIERA_DIE (ERRNO); + lumiera_recmutex_init (&lumiera_interface_mutex, "interfaceregistry", &NOBUG_FLAG(interfaceregistry)); } @@ -114,6 +125,13 @@ lumiera_interfaceregistry_destroy (void) if (lumiera_interfaceregistry) psplay_destroy (lumiera_interfaceregistry); lumiera_interfaceregistry = NULL; + + TODO ("provide a delete function for the psplay tree to tear it down"); + REQUIRE (psplay_nelements (lumiera_pluginregistry) == 0, "plugins still loaded at destroy"); + + if (lumiera_pluginregistry) + psplay_delete (lumiera_pluginregistry); + lumiera_pluginregistry = NULL; } @@ -216,7 +234,7 @@ lumiera_interfaceregistry_interface_find (const char* interface, unsigned versio static int -cmp_fn (const void* keya, const void* keyb) +lumiera_interface_cmp_fn (const void* keya, const void* keyb) { const LumieraInterface a = (const LumieraInterface)keya; const LumieraInterface b = (const LumieraInterface)keyb; @@ -243,12 +261,11 @@ cmp_fn (const void* keya, const void* keyb) static const void* -key_fn (const PSplaynode node) +lumiera_interface_key_fn (const PSplaynode node) { return ((LumieraInterfacenode)node)->interface; } - /* // Local Variables: // mode: C diff --git a/src/backend/plugin.c b/src/backend/plugin.c index f6ecd7649..1b708c6be 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -18,72 +18,72 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include -#include -#include -#include -#include -#include - #include "lib/safeclib.h" +#include "lib/psplay.h" +#include "lib/mutex.h" +#include "lib/error.h" +#include "backend/interfaceregistry.h" +#include "backend/config.h" #include "backend/plugin.h" +#include + +#include + /** * @file * Plugin loader. */ +extern PSplay lumiera_pluginregistry; /* TODO should be set by the build system to the actual plugin path */ -#define LUMIERA_PLUGIN_PATH "~/.lumiera/plugins:/usr/local/lib/lumiera/plugins:.libs" - -NOBUG_DEFINE_FLAG (lumiera_plugin); /* errors */ LUMIERA_ERROR_DEFINE(PLUGIN_DLOPEN, "Could not open plugin"); -LUMIERA_ERROR_DEFINE(PLUGIN_HOOK, "Hook function failed"); -LUMIERA_ERROR_DEFINE(PLUGIN_NFILE, "No such plugin"); -LUMIERA_ERROR_DEFINE(PLUGIN_NIFACE, "No such interface"); -LUMIERA_ERROR_DEFINE(PLUGIN_REVISION, "Interface revision too old"); /* supported (planned) plugin types and their file extensions */ +#define LUMIERA_PLUGIN_TYPES \ + LUMIERA_PLUGIN_TYPE(DYNLIB, ".so") + +/* + only .so dynlibs for now, later we may support some more + LUMIERA_PLUGIN_TYPE(LUA, ".lua") + LUMIERA_PLUGIN_TYPE(CSOURCE, ".c") +*/ + +#define LUMIERA_PLUGIN_TYPE(type, ext) LUMIERA_PLUGIN_##type, enum lumiera_plugin_type { - LUMIERA_PLUGIN_NULL, - LUMIERA_PLUGIN_DYNLIB, - LUMIERA_PLUGIN_CSOURCE + LUMIERA_PLUGIN_TYPES + LUMIERA_PLUGIN_NONE }; +#undef LUMIERA_PLUGIN_TYPE -static const struct -{ - const char* const ext; - enum lumiera_plugin_type type; -} lumiera_plugin_extensions [] = +#define LUMIERA_PLUGIN_TYPE(type, ext) ext, +static const char* const lumiera_plugin_ext[] = { - {"so", LUMIERA_PLUGIN_DYNLIB}, - {"o", LUMIERA_PLUGIN_DYNLIB}, - {"c", LUMIERA_PLUGIN_CSOURCE}, - /* extend here */ - {NULL, LUMIERA_PLUGIN_NULL} + LUMIERA_PLUGIN_TYPES + NULL }; +#undef LUMIERA_PLUGIN_TYPE -struct lumiera_plugin + + +struct lumiera_plugin_struct { - /* short name as queried ("effects/audio/normalize") used for sorting/finding */ - const char* name; + psplaynode node; /* long names as looked up ("/usr/local/lib/lumiera/plugins/effects/audio/normalize.so") */ - const char* pathname; + const char* name; /* use count for all interfaces of this plugin */ - unsigned use_count; + unsigned refcnt; /* time when the last open or close action happened */ time_t last; @@ -96,242 +96,124 @@ struct lumiera_plugin }; -/* global plugin registry */ -void* lumiera_plugin_registry = NULL; -/* plugin operations are protected by one big mutex */ -pthread_mutex_t lumiera_plugin_mutex = PTHREAD_MUTEX_INITIALIZER; - -/** - * the compare function for the registry tree. - * Compares the names of two struct lumiera_plugin. - * @return 0 if a and b are equal, just like strcmp. */ -static int -lumiera_plugin_name_cmp (const void* a, const void* b) -{ - return strcmp (((struct lumiera_plugin*) a)->name, ((struct lumiera_plugin*) b)->name); -} - -void -lumiera_init_plugin (void) -{ - NOBUG_INIT_FLAG (lumiera_plugin); -} - -/** - * Find and set pathname for the plugin. - * Searches through given path for given plugin, trying to find the file's location in the filesystem. - * If found, self->pathname will be set to the found plugin file. - * @param self The lumiera_plugin to open look for. - * @param path The path to search trough (paths seperated by ":") - * @return 0 on success. -1 on error, or if plugin not found in path. - */ int -lumiera_plugin_lookup (struct lumiera_plugin* self, const char* path) +lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), + int (*callback_register) (LumieraPlugin)) { - if (!path) - return -1; + TRACE (plugin); + REQUIRE (callback_load); + REQUIRE (callback_register); - if (strlen(path) > 1023) - return -1; /*TODO error handling*/ - - char tpath[1024]; - TODO("dunno if PATH_MAX may be undefined (in case arbitary lengths are supported), I check that later"); - char pathname[1024] = {0}; - char* tmp; - - strcpy(tpath, path); - - /*for each in path*/ - for (char* tok = strtok_r (tpath, ":", &tmp); tok; tok = strtok_r (NULL, ":", &tmp)) + /* construct glob trail {.so,.c,.foo} ... */ + static char* exts_globs = NULL; + if (!exts_globs) { - /*for each extension*/ - for (int i = 0; lumiera_plugin_extensions[i].ext; ++i) + size_t exts_sz = 4; /* / * { } \0 less one comma */ + const char*const* itr = lumiera_plugin_ext; + while (*itr) { - /* path/name.extension */ - int r = snprintf(pathname, 1024, "%s/%s.%s", tok, self->name, lumiera_plugin_extensions[i].ext); - if (r >= 1024) - return -1; /*TODO error handling, name too long*/ + exts_sz += strlen (*itr) + 1; + ++itr; + } - TRACE (lumiera_plugin, "trying %s", pathname); + exts_globs = lumiera_malloc (exts_sz); + *exts_globs = '\0'; - if (!access(pathname, R_OK)) + itr = lumiera_plugin_ext; + strcat (exts_globs, "/*{"); + + while (*itr) + { + strcat (exts_globs, *itr); + strcat (exts_globs, ","); + ++itr; + } + exts_globs[exts_sz-2] = '}'; + TRACE (plugin, "initialized extension glob to '%s'", exts_globs); + } + + const char* path; + unsigned i = 0; + int flags = GLOB_PERIOD|GLOB_BRACE|GLOB_TILDE_CHECK; + glob_t globs; + + while ((path = lumiera_config_wordlist_get_nth ("plugin.path", i, ":"))) + { + path = lumiera_tmpbuf_snprintf (SIZE_MAX,"%s%s", path, exts_globs); + TRACE (plugin, "globbing path '%s'", path); + int ret = glob (path, flags, NULL, &globs); + if (ret == GLOB_NOSPACE) + LUMIERA_DIE (NO_MEMORY); + + flags |= GLOB_APPEND; + ++i; + } + + LUMIERA_RECMUTEX_SECTION (plugin, &lumiera_interface_mutex) + { + for (char** itr = globs.gl_pathv; *itr; ++itr) + { + + if (!psplay_find (lumiera_pluginregistry, *itr, 100)) { - /* got it */ - TRACE (lumiera_plugin, "found %s", pathname); - self->pathname = lumiera_strndup (pathname, PATH_MAX); + TRACE (plugin, "found new plugin '%s'", *itr); - self->type = lumiera_plugin_extensions[i].type; - return 0; + LumieraPlugin plugin = callback_load (*itr); + if (plugin) + callback_register (plugin); } } } - return -1; /* plugin not found */ + + globfree (&globs); + + return !lumiera_error_peek (); } -struct lumiera_interface* -lumiera_interface_open (const char* name, const char* interface, size_t min_revision) + + + +LumieraPlugin +lumiera_plugin_load (const char* plugin) { - //REQUIRE (min_revision > sizeof(struct lumiera_interface), "try to use an empty interface eh?"); - REQUIRE (interface, "interface name must be given"); + TRACE (plugin); + UNIMPLEMENTED(); + (void) plugin; - pthread_mutex_lock (&lumiera_plugin_mutex); - - struct lumiera_plugin plugin; - struct lumiera_plugin** found; - - plugin.name = name; /* for searching */ - - found = tsearch (&plugin, &lumiera_plugin_registry, lumiera_plugin_name_cmp); - if (!found) - LUMIERA_DIE (NO_MEMORY); - - if (*found == &plugin) - { - NOTICE (lumiera_plugin, "new plugin"); - - /* now really create new item */ - *found = lumiera_malloc (sizeof (struct lumiera_plugin)); - - if (name) /* NULL is main app, no lookup needed */ - { - /*lookup for $LUMIERA_PLUGIN_PATH*/ - (*found)->name = lumiera_strndup (name, PATH_MAX); - - if (!!lumiera_plugin_lookup (*found, getenv("LUMIERA_PLUGIN_PATH")) -#ifdef LUMIERA_PLUGIN_PATH - /* else lookup for -DLUMIERA_PLUGIN_PATH */ - && !!lumiera_plugin_lookup (*found, LUMIERA_PLUGIN_PATH) -#endif - ) - { - LUMIERA_ERROR_SET (lumiera_plugin, PLUGIN_NFILE); - goto elookup; - } - } - else - { - (*found)->name = NULL; - (*found)->pathname = NULL; - } - - (*found)->use_count = 0; - - PLANNED("if .so like then dlopen; else if .c like tcc compile"); - TODO("factor dlopen and dlsym out"); - - TRACE(lumiera_plugin, "trying to open %s", (*found)->pathname); - - (*found)->handle = dlopen ((*found)->pathname, RTLD_LAZY|RTLD_LOCAL); - if (!(*found)->handle) - { - ERROR (lumiera_plugin, "dlopen failed: %s", dlerror()); - LUMIERA_ERROR_SET (lumiera_plugin, PLUGIN_DLOPEN); - goto edlopen; - } - - /* if the plugin defines a 'lumiera_plugin_init' function, we call it, must return 0 on success */ - int (*init)(void) = dlsym((*found)->handle, "lumiera_plugin_init"); - if (init && init()) - { - //ERROR (lumiera_plugin, "lumiera_plugin_init failed: %s: %s", name, interface); - LUMIERA_ERROR_SET (lumiera_plugin, PLUGIN_HOOK); - goto einit; - } - } - /* we have the plugin, now get the interface descriptor */ - struct lumiera_interface* ret; - - dlerror(); - ret = dlsym ((*found)->handle, interface); - - const char *dlerr = dlerror(); - TRACE(lumiera_plugin, "%s", dlerr); - TODO ("need some way to tell 'interface not provided by plugin', maybe lumiera_plugin_error()?"); - if (dlerr) - { - //ERROR (lumiera_plugin, "plugin %s doesnt provide interface %s", name, interface); - LUMIERA_ERROR_SET (lumiera_plugin, PLUGIN_NIFACE); - goto edlsym; - } - - /* is the interface older than required? */ - if (ret->size < min_revision) - { - ERROR (lumiera_plugin, "plugin %s provides older interface %s revision than required", name, interface); - LUMIERA_ERROR_SET (lumiera_plugin, PLUGIN_REVISION); - goto erevision; - } - - ret->plugin = *found; - - /* if the interface provides a 'open' function, call it now, must return 0 on success */ - if (ret->open && ret->open()) - { - ERROR (lumiera_plugin, "open hook indicated an error"); - LUMIERA_ERROR_SET (lumiera_plugin, PLUGIN_HOOK); - goto eopen; - } - - (*found)->use_count++; - (*found)->last = time (NULL); - ret->use_count++; - - pthread_mutex_unlock (&lumiera_plugin_mutex); - return ret; - - /* Error cleanup */ - einit: - dlclose((*found)->handle); - eopen: - erevision: - edlsym: - edlopen: - elookup: - free ((char*)(*found)->name); - free (*found); - *found = &plugin; - tdelete (&plugin, &lumiera_plugin_registry, lumiera_plugin_name_cmp); - pthread_mutex_unlock (&lumiera_plugin_mutex); return NULL; } -void -lumiera_interface_close (void* ptr) + +int +lumiera_plugin_register (LumieraPlugin plugin) { - TRACE (lumiera_plugin, "%p", ptr); - if(!ptr) - return; + TRACE (plugin); + UNIMPLEMENTED(); - struct lumiera_interface* self = (struct lumiera_interface*) ptr; - - pthread_mutex_lock (&lumiera_plugin_mutex); - - struct lumiera_plugin* plugin = self->plugin; - - plugin->use_count--; - self->use_count--; - - /* if the interface provides a 'close' function, call it now */ - if (self->close) - self->close(); - - /* plugin not longer in use, unload it */ - if (!plugin->use_count) + LUMIERA_RECMUTEX_SECTION (plugin, &lumiera_interface_mutex) { - TODO ("we dont want to close here, instead store time of recent use and make a expire run, already planned in my head"); + (void) plugin; - /* if the plugin defines a 'lumiera_plugin_destroy' function, we call it */ - int (*destroy)(void) = dlsym(plugin->handle, "lumiera_plugin_destroy"); - if (destroy) - destroy(); - - /* and now cleanup */ - tdelete (plugin, &lumiera_plugin_registry, lumiera_plugin_name_cmp); - free ((char*)plugin->name); - dlclose(plugin->handle); - free (plugin); } - pthread_mutex_unlock (&lumiera_plugin_mutex); + return 0; } + + + + + +int +lumiera_plugin_cmp_fn (const void* keya, const void* keyb) +{ + return strcmp ((const char*)keya, (const char*)keyb); +} + + +const void* +lumiera_plugin_key_fn (const PSplaynode node) +{ + return ((LumieraPlugin)node)->name; +} + diff --git a/src/backend/plugin.h b/src/backend/plugin.h index 6696e395f..8c0e5e7ae 100644 --- a/src/backend/plugin.h +++ b/src/backend/plugin.h @@ -36,6 +36,7 @@ LUMIERA_ERROR_DECLARE(PLUGIN_DLOPEN); +LUMIERA_ERROR_DECLARE(PLUGIN_PLUGINPATH); NOBUG_DECLARE_FLAG (plugin); @@ -48,18 +49,11 @@ typedef struct lumiera_plugin_struct lumiera_plugin; typedef lumiera_plugin* LumieraPlugin; -/** - * Initialize the plugin system. - * always succeeds or aborts - */ -void -lumiera_pluginregistry_init (void); +int +lumiera_plugin_cmp_fn (const void* keya, const void* keyb); -/** - * destroy the plugin system, free all resources - */ -void -lumiera_pluginregistry_destroy (void); +const void* +lumiera_plugin_key_fn (const PSplaynode node); LumieraPlugin @@ -70,6 +64,8 @@ int lumiera_plugin_register (LumieraPlugin); + + /** * discover new plugins * traverses the configured plugin dirs and calls the callback_load function for any plugin From 9f8b0070a6510795c557f306e18a12323d81bcdc Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 3 Nov 2008 21:24:15 +0100 Subject: [PATCH 43/59] build option for SCons (verbose) --- SConstruct | 16 +++++++++++++--- tests/SConscript | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/SConstruct b/SConstruct index c6b0e0e66..20fa76840 100644 --- a/SConstruct +++ b/SConstruct @@ -63,6 +63,7 @@ def setupBasicEnvironment(): ,toolpath = [TOOLDIR] ,tools = ["default", "BuilderGCH", "BuilderDoxygen"] ) + handleVerboseMessages(env) env.Append ( CCCOM=' -std=gnu99') # workaround for a bug: CCCOM currently doesn't honor CFLAGS, only CCFLAGS env.Replace( VERSION=VERSION @@ -73,7 +74,6 @@ def setupBasicEnvironment(): , CPPDEFINES=['-DLUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines , CCFLAGS='-Wall ' # -fdiagnostics-show-option ) - RegisterIcon_Builder(env,SVGRENDERER) handleNoBugSwitches(env) @@ -113,6 +113,15 @@ def handleNoBugSwitches(env): elif level == 'RELEASE': env.Replace( DEBUG = 0 ) +def handleVerboseMessages(env): + """ toggle verbose build output """ + if not env['VERBOSE']: + # SetOption('silent', True) + env['CCCOMSTR'] = " Compiling $SOURCE" + env['CXXCOMSTR'] = " Compiling++ $SOURCE" + env['LINKCOMSTR'] = " Linking --> $TARGET" + env['LDMODULECOMSTR'] = " creating module [ $TARGET ]" + @@ -129,6 +138,7 @@ def defineCmdlineOptions(): ,BoolOption('DEBUG', 'Build with debugging information and no optimizations', False) ,BoolOption('OPTIMIZE', 'Build with strong optimization (-O3)', False) ,BoolOption('VALGRIND', 'Run Testsuite under valgrind control', True) + ,BoolOption('VERBOSE', 'Print full build commands', False) ,('TESTSUITES', 'Run only Testsuites matching the given pattern', '') # ,BoolOption('OPENGL', 'Include support for OpenGL preview rendering', False) # ,EnumOption('DIST_TARGET', 'Build target architecture', 'auto', @@ -153,7 +163,7 @@ Special Targets: build : just compile and link testcode: additionally compile the Testsuite check : build and run the Testsuite - doc : generate documetation (Doxygen) + doc : generate documentation (Doxygen) install : install created artifacts at PREFIX src.tar : create source tarball doc.tar : create developer doc tarball @@ -302,7 +312,7 @@ def defineBuildTargets(env, artifacts): artifacts['lumiera'] = env.Program('$BINDIR/lumiera', ['$SRCDIR/main.cpp']+ core ) - artifacts['plugins'] = env.SharedLibrary('$BINDIR/lumiera-plugin', objplug) + artifacts['plugins'] = env.LoadableModule('$BINDIR/lumiera-plugin', objplug) # the Lumiera GTK GUI envgtk = env.Clone().mergeConf(['gtkmm-2.4','cairomm-1.0','gdl-1.0','librsvg-2.0','xv','xext','sm']) diff --git a/tests/SConscript b/tests/SConscript index d28b70218..901c2280c 100644 --- a/tests/SConscript +++ b/tests/SConscript @@ -52,7 +52,7 @@ def treatPluginTestcase(env): prfx = path.join(tree,'example_plugin') oC = env.SharedObject(prfx, prfx+'.c') oCPP = env.SharedObject(prfx+'_cpp', prfx+'.cpp') - testplugin = ( env.SharedLibrary('#$BINDIR/.libs/examplepluginc', oC, SHLIBPREFIX='') + testplugin = ( env.LoadableModule('#$BINDIR/.libs/examplepluginc', oC, SHLIBPREFIX='') # doesn't compile yet... # + env.SharedLibrary('#$BINDIR/.libs/exampleplugincpp', oCPP, SHLIBPREFIX='') From b0b29e86a45e04991a9602a628cb37f5f2699cba Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 3 Nov 2008 21:27:03 +0100 Subject: [PATCH 44/59] forgot to add some UML --- doc/devel/uml/class144773.html | 25 ++++++ doc/devel/uml/class144901.html | 20 +++++ doc/devel/uml/class145029.html | 20 +++++ doc/devel/uml/class145157.html | 22 +++++ doc/devel/uml/class145285.html | 20 +++++ doc/devel/uml/class145413.html | 20 +++++ doc/devel/uml/class145541.html | 27 ++++++ doc/devel/uml/class145669.html | 24 ++++++ doc/devel/uml/class145797.html | 24 ++++++ doc/devel/uml/class145925.html | 23 +++++ doc/devel/uml/class146053.html | 24 ++++++ doc/devel/uml/class146181.html | 23 +++++ doc/devel/uml/class146309.html | 26 ++++++ doc/devel/uml/class146437.html | 24 ++++++ uml/lumiera/132741.diagram | 153 +++++++++++++++++++++++++++++++++ 15 files changed, 475 insertions(+) create mode 100644 doc/devel/uml/class144773.html create mode 100644 doc/devel/uml/class144901.html create mode 100644 doc/devel/uml/class145029.html create mode 100644 doc/devel/uml/class145157.html create mode 100644 doc/devel/uml/class145285.html create mode 100644 doc/devel/uml/class145413.html create mode 100644 doc/devel/uml/class145541.html create mode 100644 doc/devel/uml/class145669.html create mode 100644 doc/devel/uml/class145797.html create mode 100644 doc/devel/uml/class145925.html create mode 100644 doc/devel/uml/class146053.html create mode 100644 doc/devel/uml/class146181.html create mode 100644 doc/devel/uml/class146309.html create mode 100644 doc/devel/uml/class146437.html create mode 100644 uml/lumiera/132741.diagram diff --git a/doc/devel/uml/class144773.html b/doc/devel/uml/class144773.html new file mode 100644 index 000000000..86e164da0 --- /dev/null +++ b/doc/devel/uml/class144773.html @@ -0,0 +1,25 @@ + + + + + + +Class StreamType + + + + + +
                                                                                                                                                                                                                                      Class StreamType
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class StreamType

                                                                                                                                                                                                                                      Artifact : streamtype

                                                                                                                                                                                                                                      + +
                                                                                                                                                                                                                                      Relation <unidirectional association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation <unidirectional association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation <unidirectional association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      + + diff --git a/doc/devel/uml/class144901.html b/doc/devel/uml/class144901.html new file mode 100644 index 000000000..59beaefed --- /dev/null +++ b/doc/devel/uml/class144901.html @@ -0,0 +1,20 @@ + + + + + + +Class Prototype + + + + + +
                                                                                                                                                                                                                                      Class Prototype
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class Prototype

                                                                                                                                                                                                                                      Artifact : streamtype

                                                                                                                                                                                                                                      + diff --git a/doc/devel/uml/class145029.html b/doc/devel/uml/class145029.html new file mode 100644 index 000000000..13e240717 --- /dev/null +++ b/doc/devel/uml/class145029.html @@ -0,0 +1,20 @@ + + + + + + +Class ImplFacade + + + + + +
                                                                                                                                                                                                                                      Class ImplFacade
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class ImplFacade

                                                                                                                                                                                                                                      Artifact : streamtype

                                                                                                                                                                                                                                      + diff --git a/doc/devel/uml/class145157.html b/doc/devel/uml/class145157.html new file mode 100644 index 000000000..ca22769ab --- /dev/null +++ b/doc/devel/uml/class145157.html @@ -0,0 +1,22 @@ + + + + + + +Class StreamTypeID + + + + + +
                                                                                                                                                                                                                                      Class StreamTypeID
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class StreamTypeID
                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      + + diff --git a/doc/devel/uml/class145285.html b/doc/devel/uml/class145285.html new file mode 100644 index 000000000..914d312aa --- /dev/null +++ b/doc/devel/uml/class145285.html @@ -0,0 +1,20 @@ + + + + + + +Class MediaKind + + + + + +
                                                                                                                                                                                                                                      Class MediaKind
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : enum MediaKind
                                                                                                                                                                                                                                      • Java : package enum MediaKind
                                                                                                                                                                                                                                      + diff --git a/doc/devel/uml/class145413.html b/doc/devel/uml/class145413.html new file mode 100644 index 000000000..fa26d80d8 --- /dev/null +++ b/doc/devel/uml/class145413.html @@ -0,0 +1,20 @@ + + + + + + +Class STypeManager + + + + + +
                                                                                                                                                                                                                                      Class STypeManager
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class STypeManager

                                                                                                                                                                                                                                      Artifact : stypemanager

                                                                                                                                                                                                                                      + diff --git a/doc/devel/uml/class145541.html b/doc/devel/uml/class145541.html new file mode 100644 index 000000000..06bd62289 --- /dev/null +++ b/doc/devel/uml/class145541.html @@ -0,0 +1,27 @@ + + + + + + +Class Timeline + + + + + +
                                                                                                                                                                                                                                      Class Timeline
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class Timeline

                                                                                                                                                                                                                                      Directly inherited by : TimelineView

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      + +
                                                                                                                                                                                                                                      Relation <aggregation by value>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation <unidirectional association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation <unidirectional association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation globalBusses (<directional aggregation by value>)

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • Uml : # globalBusses : Pipe, multiplicity : *
                                                                                                                                                                                                                                      • C++ : protected: Pipe globalBusses
                                                                                                                                                                                                                                      + + diff --git a/doc/devel/uml/class145669.html b/doc/devel/uml/class145669.html new file mode 100644 index 000000000..d2fb577a5 --- /dev/null +++ b/doc/devel/uml/class145669.html @@ -0,0 +1,24 @@ + + + + + + +Class Project + + + + + +
                                                                                                                                                                                                                                      Class Project
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class Project
                                                                                                                                                                                                                                      + +
                                                                                                                                                                                                                                      Relation <aggregation by value>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation <aggregation by value>

                                                                                                                                                                                                                                      Declaration :

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

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class TimelineView : public Timeline
                                                                                                                                                                                                                                      + +
                                                                                                                                                                                                                                      Relation <unidirectional association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation <association>

                                                                                                                                                                                                                                      Declaration :

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

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

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

                                                                                                                                                                                                                                      Declaration :

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

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

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

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation <association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      + + diff --git a/doc/devel/uml/class146181.html b/doc/devel/uml/class146181.html new file mode 100644 index 000000000..31c08ed9c --- /dev/null +++ b/doc/devel/uml/class146181.html @@ -0,0 +1,23 @@ + + + + + + +Class RenderTask + + + + + +
                                                                                                                                                                                                                                      Class RenderTask
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

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

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      + + diff --git a/doc/devel/uml/class146309.html b/doc/devel/uml/class146309.html new file mode 100644 index 000000000..485390623 --- /dev/null +++ b/doc/devel/uml/class146309.html @@ -0,0 +1,26 @@ + + + + + + +Class Sequence + + + + + +
                                                                                                                                                                                                                                      Class Sequence
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class Sequence
                                                                                                                                                                                                                                      + +
                                                                                                                                                                                                                                      Relation <aggregation by value>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation subSequences (<unidirectional association>)

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • Uml : # subSequences : Sequence, multiplicity : *
                                                                                                                                                                                                                                      • C++ : protected: Sequence* subSequences
                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation <unidirectional association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation trackTree (<unidirectional association>)

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • Uml : # trackTree : Track, multiplicity : 1
                                                                                                                                                                                                                                      • C++ : protected: Track* trackTree
                                                                                                                                                                                                                                      + + diff --git a/doc/devel/uml/class146437.html b/doc/devel/uml/class146437.html new file mode 100644 index 000000000..57ebd91f2 --- /dev/null +++ b/doc/devel/uml/class146437.html @@ -0,0 +1,24 @@ + + + + + + +Class PlayheadCursor + + + + + +
                                                                                                                                                                                                                                      Class PlayheadCursor
                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                      + + + + +

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      • C++ : class PlayheadCursor
                                                                                                                                                                                                                                      + +
                                                                                                                                                                                                                                      Relation <association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                      Relation <association>

                                                                                                                                                                                                                                      Declaration :

                                                                                                                                                                                                                                      + + diff --git a/uml/lumiera/132741.diagram b/uml/lumiera/132741.diagram new file mode 100644 index 000000000..c3a8d44f4 --- /dev/null +++ b/uml/lumiera/132741.diagram @@ -0,0 +1,153 @@ +format 40 + +classcanvas 128005 class_ref 145669 // Project + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 161 115 2000 + end +classcanvas 128133 class_ref 145541 // Timeline + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 177 222 2000 + end +classcanvas 128261 class_ref 145797 // TimelineView + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 163 323 2000 + end +classcanvas 128645 class_ref 145925 // PlayControl + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 315 223 2000 + end +classcanvas 128773 class_ref 146053 // Monitor + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 456 90 2000 + end +classcanvas 128901 class_ref 146181 // RenderTask + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 456 32 2000 + end +classcanvas 129029 class_ref 146309 // Sequence + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 41 323 2000 + end +classcanvas 130437 class_ref 138117 // Pipe + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 317 294 2000 + end +classcanvas 132101 class_ref 146437 // PlayheadCursor + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 452 222 2000 + end +classcanvas 132997 class_ref 128389 // Track + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 99 611 2000 + end +classcanvas 133125 class_ref 128517 // MObject + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 163 485 2000 + end +classcanvas 133253 class_ref 129029 // Effect + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 211 611 2000 + end +classcanvas 133381 class_ref 129669 // Label + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 259 611 2000 + end +classcanvas 133509 class_ref 128901 // Clip + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_infonote default shadow default + xyz 163 611 2000 + end +relationcanvas 128389 relation_ref 154757 // + from ref 128261 z 1999 to ref 128133 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 129157 relation_ref 154885 // + from ref 128005 z 1999 to ref 128133 + no_role_a no_role_b + multiplicity_a_pos 173 197 3000 multiplicity_b_pos 173 166 3000 +relationcanvas 129285 relation_ref 155013 // + from ref 128133 z 1999 stereotype "<>" xyz 251 226 3000 to ref 128645 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 129413 relation_ref 155141 // + geometry VHr + from ref 128005 z 1999 to point 71 134 + line 129541 z 1999 to ref 129029 + no_role_a no_role_b + multiplicity_a_pos 47 298 3000 multiplicity_b_pos 144 145 3000 +relationcanvas 129669 relation_ref 155269 // + from ref 128133 z 1999 to ref 129029 + no_role_a no_role_b + multiplicity_a_pos 113 322 3000 no_multiplicity_b +relationcanvas 129797 relation_ref 155397 // + from ref 128261 z 1999 to ref 129029 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 129925 relation_ref 155525 // + from ref 129029 z 1999 stereotype "<>" xyz 33 389 3000 to point 71 387 + line 130309 z 1999 to point 46 387 + line 130181 z 1999 to ref 129029 + role_a_pos 23 401 3000 no_role_b + multiplicity_a_pos 42 369 3000 multiplicity_b_pos 75 369 3000 +relationcanvas 130565 relation_ref 155653 // + from ref 128133 z 1999 stereotype "<>" xyz 265 265 3000 to point 263 281 + line 131077 z 1999 to point 303 281 + line 131205 z 1999 to ref 130437 + role_a_pos 242 280 3000 no_role_b + multiplicity_a_pos 322 279 3000 multiplicity_b_pos 237 268 3000 +relationcanvas 131589 relation_ref 155781 // + from ref 128773 z 1999 stereotype "<>" xyz 274 147 3000 to point 282 172 + line 131845 z 1999 to ref 128133 + no_role_a no_role_b + multiplicity_a_pos 221 180 3000 no_multiplicity_b +relationcanvas 131717 relation_ref 155909 // + from ref 128901 z 1999 to point 272 156 + line 131973 z 1999 to ref 128133 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 132229 relation_ref 156037 // + from ref 128645 z 1999 stereotype "<>" xyz 391 226 3000 to ref 132101 + no_role_a no_role_b + multiplicity_a_pos 436 247 3000 no_multiplicity_b +relationcanvas 132357 relation_ref 156165 // + from ref 128773 z 1999 to ref 132101 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 132485 relation_ref 156293 // + from ref 128261 z 1999 to point 478 341 + line 132613 z 1999 to ref 132101 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 133765 relation_ref 156421 // + from ref 133509 z 1999 to ref 133125 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 133893 relation_ref 156549 // + from ref 133253 z 1999 to ref 133125 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 134021 relation_ref 156677 // + from ref 133381 z 1999 to ref 133125 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 134149 relation_ref 156805 // + from ref 132997 z 1999 to ref 133125 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 134405 relation_ref 156933 // + from ref 129029 z 1999 to point 99 363 + line 134533 z 1999 to ref 133125 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +relationcanvas 134661 relation_ref 157061 // + from ref 129029 z 1999 to point 99 364 + line 134789 z 1999 to point 118 463 + line 134917 z 1999 to ref 132997 + role_a_pos 68 538 3000 no_role_b + multiplicity_a_pos 104 586 3000 no_multiplicity_b +relationcanvas 135045 relation_ref 145029 // + from ref 132997 z 1999 stereotype "<>" xyz 35 599 3000 to point 70 630 + line 135173 z 1999 to point 70 661 + line 135301 z 1999 to ref 132997 + role_a_pos 37 612 3000 no_role_b + multiplicity_a_pos 91 657 3000 no_multiplicity_b +end From 4d2fe242d0f42ed320a006f27e4fe66ea658cf35 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 4 Nov 2008 07:50:42 +0100 Subject: [PATCH 45/59] Some more interfaces improvements * add a lumiera_interface_version() function for runtime type and version checking of interfaces * the 'lumieraorg__plugin' interface is now private * add a macro to construct a interface instance name string --- src/backend/interface.c | 10 ++++++++++ src/backend/interface.h | 26 ++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/backend/interface.c b/src/backend/interface.c index 917c663d9..26fa3a42e 100644 --- a/src/backend/interface.c +++ b/src/backend/interface.c @@ -229,6 +229,16 @@ lumiera_interface_close (LumieraInterface self) } +unsigned +lumiera_interface_version (LumieraInterface self, const char* iname) +{ + if (self && iname && !strcmp (self->interface, iname)) + return self->version; + + return ~0; +} + + /* internal function, does no locking! */ static void lumiera_interfacenode_close (LumieraInterfacenode self) diff --git a/src/backend/interface.h b/src/backend/interface.h index 7b97fd82e..222fbbc62 100644 --- a/src/backend/interface.h +++ b/src/backend/interface.h @@ -102,9 +102,18 @@ * @param iname name of the interface * @param version major version of the interface * @param dname name for the instance + * @return constructed identifier */ -#define LUMIERA_INTERFACE_DNAME(iname, version, dname) PPMPL_CAT (LUMIERA_INTERFACE_INAME(iname, version), _##dname) +#define LUMIERA_INTERFACE_DNAME(iname, version, dname) PPMPL_CAT (LUMIERA_INTERFACE_INAME (iname, version), _##dname) +/** + * Construct a definition string r for an interface + * @param iname name of the interface + * @param version major version of the interface + * @param dname name for the instance + * @return constructed string + */ +#define LUMIERA_INTERFACE_DSTRING(iname, version, dname) PPMPL_STRINGIFY (LUMIERA_INTERFACE_DNAME (iname, version, dname)) /** * Return a reference (pointer) to an interface implementation @@ -293,7 +302,7 @@ queryfunc (void) \ */ #define LUMIERA_PLUGIN(acquire, release, luid, ...) \ LUMIERA_EXPORT(plugin_interfaces, __VA_ARGS__) \ -LUMIERA_INTERFACE_INSTANCE (lumieraorg_plugin, 0, \ +LUMIERA_INTERFACE_INSTANCE (lumieraorg__plugin, 0, \ lumieraorg_plugin, \ NULL, \ acquire, \ @@ -374,7 +383,7 @@ struct lumiera_interface_struct /** * Plugin interface */ -LUMIERA_INTERFACE_DECLARE (lumieraorg_plugin, 0, +LUMIERA_INTERFACE_DECLARE (lumieraorg__plugin, 0, LUMIERA_INTERFACE_SLOT (LumieraInterface*, plugin_interfaces, (void)), ); @@ -402,7 +411,16 @@ lumiera_interface_open (const char* interface, unsigned version, size_t minminor * consider 'self' to be invalidated after this call */ void -lumiera_interface_close (LumieraInterface iface); +lumiera_interface_close (LumieraInterface self); + +/** + * Runtime check for interface type and version + * @param self interface to check + * @param iname name of the interface + * @return version of the interface or ~0 (-1) if iname doesn't match the requested name + */ +unsigned +lumiera_interface_version (LumieraInterface self, const char* iname); #endif /* LUMIERA_INTERFACE_H */ From c30c98bebd4d4951e26f75f4ed2e9b0fc5f34aca Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 5 Nov 2008 11:07:49 +0100 Subject: [PATCH 46/59] add a LUMIERA_INTERFACE_CLOSE macro This is a small typesafe wrapper around the interface_close() function and since we need INTERFACE_OPEN wraped too this makes it more orthogonal --- src/backend/interface.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backend/interface.h b/src/backend/interface.h index 222fbbc62..c84238d1c 100644 --- a/src/backend/interface.h +++ b/src/backend/interface.h @@ -320,6 +320,9 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg__plugin, 0, #define LUMIERA_INTERFACE_OPEN(interface, version, minminor, name) \ LUMIERA_INTERFACE_CAST(interface, version) lumiera_interface_open (#interface, version, minminor, #name) +#define LUMIERA_INTERFACE_CLOSE(handle) \ + lumiera_interface_close (&(handle)->interface_header_) + typedef struct lumiera_interfaceslot_struct lumiera_interfaceslot; typedef lumiera_interfaceslot* LumieraInterfaceslot; From 7c2415838b95f92d2f16c94bebf913d4f7d4d846 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 4 Nov 2008 08:03:18 +0100 Subject: [PATCH 47/59] WIP: big plugin update * fix configure.ac to check for dlopen, introduce $(LUMIERA_PLUGIN_LIBS) * Generic pluginloader finished, all plugins get loaded and registered at start for now, it is prepared for on-demand loading and unloading but not implemented because that needs the plugindb. - plugin unloading not yet finished, this asserts at the end --- configure.ac | 5 + src/backend/Makefile.am | 1 + src/backend/plugin.c | 223 +++++++++++++++++++++++++++------------- src/backend/plugin.h | 19 +++- 4 files changed, 171 insertions(+), 77 deletions(-) diff --git a/configure.ac b/configure.ac index ae9f0d79b..4f705e01b 100644 --- a/configure.ac +++ b/configure.ac @@ -87,6 +87,10 @@ AC_LANG_PUSH([C]) AC_CHECK_HEADER([execinfo.h], AC_DEFINE(HAVE_EXECINFO_H)) # there is a warning in nobug, disabled til fixed AC_CHECK_HEADER([valgrind/valgrind.h], AC_DEFINE(HAVE_VALGRIND_VALGRIND_H)) +AC_CHECK_LIB(dl, dlopen, [LUMIERA_PLUGIN_LIBS="$LUMIERA_PLUGIN_LIBS -ldl"], + [AC_MSG_ERROR([Dynamic linking not supported, report a bug])] +) + AC_LANG_POP([C]) @@ -160,6 +164,7 @@ AC_CHECK_LIB(Xv, XvQueryAdaptors, [LUMIERA_GUI_LIBS="$LUMIERA_GUI_LIBS -lXv"], # END X11 Dependancies +AC_SUBST(LUMIERA_PLUGIN_LIBS) AC_SUBST(LUMIERA_GUI_CFLAGS) AC_SUBST(LUMIERA_GUI_LIBS) diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index be9b9cd90..d8c0c159e 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -30,6 +30,7 @@ liblumibackend_a_SOURCES = \ $(liblumibackend_a_srcdir)/interface.c \ $(liblumibackend_a_srcdir)/interfaceregistry.c \ $(liblumibackend_a_srcdir)/plugin.c \ + $(liblumibackend_a_srcdir)/plugin_dynlib.c \ $(liblumibackend_a_srcdir)/config.c \ $(liblumibackend_a_srcdir)/config_typed.c \ $(liblumibackend_a_srcdir)/config_wordlist.c \ diff --git a/src/backend/plugin.c b/src/backend/plugin.c index 1b708c6be..66ebd345c 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -18,6 +18,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + #include "lib/safeclib.h" #include "lib/psplay.h" #include "lib/mutex.h" @@ -41,40 +43,56 @@ extern PSplay lumiera_pluginregistry; /* TODO should be set by the build system to the actual plugin path */ /* errors */ +LUMIERA_ERROR_DEFINE(PLUGIN_INIT, "Initialization error"); LUMIERA_ERROR_DEFINE(PLUGIN_DLOPEN, "Could not open plugin"); +LUMIERA_ERROR_DEFINE(PLUGIN_WTF, "Not a Lumiera plugin"); +LUMIERA_ERROR_DEFINE(PLUGIN_REGISTER, "Could not register plugin"); +LUMIERA_ERROR_DEFINE(PLUGIN_VERSION, "Plugin Version unsupported"); -/* - supported (planned) plugin types and their file extensions -*/ +#define LUMIERA_PLUGIN_TYPE_PLANNED(name, ext) -#define LUMIERA_PLUGIN_TYPES \ - LUMIERA_PLUGIN_TYPE(DYNLIB, ".so") +/** + * Supported (and planned) plugin types and their file extensions + * This maps filename extensions to implementations (of the respective _load_NAME and _unload_NAME functions) + * So far we only support platform dynamic libraries, later we may add plugins implemented in lua + * and c source modules which get compiled on the fly. + */ +#define LUMIERA_PLUGIN_TYPES \ + LUMIERA_PLUGIN_TYPE_PLANNED(DYNLIB, ".so") \ + LUMIERA_PLUGIN_TYPE_PLANNED(DYNLIB, ".lum") \ + LUMIERA_PLUGIN_TYPE_PLANNED(LUA, ".lua") \ + LUMIERA_PLUGIN_TYPE_PLANNED(CSOURCE, ".c") -/* - only .so dynlibs for now, later we may support some more - LUMIERA_PLUGIN_TYPE(LUA, ".lua") - LUMIERA_PLUGIN_TYPE(CSOURCE, ".c") -*/ -#define LUMIERA_PLUGIN_TYPE(type, ext) LUMIERA_PLUGIN_##type, -enum lumiera_plugin_type - { - LUMIERA_PLUGIN_TYPES - LUMIERA_PLUGIN_NONE - }; +/** + * record the extension and a callback function for loading the associated plugin for each plugin type + */ +struct lumiera_plugintype_struct +{ + LumieraPlugin (*lumiera_plugin_load_fn)(const char*); + void (*lumiera_plugin_unload_fn)(LumieraPlugin); + const char* ext; +}; +typedef struct lumiera_plugintype_struct lumiera_plugintype; +typedef lumiera_plugintype* LumieraPlugintype; + +/* forward declare loader functions for all types */ +#define LUMIERA_PLUGIN_TYPE(type, ext) \ + LumieraPlugin lumiera_plugin_load_##type (const char*); \ + void lumiera_plugin_unload_##type (LumieraPlugin); +LUMIERA_PLUGIN_TYPES #undef LUMIERA_PLUGIN_TYPE -#define LUMIERA_PLUGIN_TYPE(type, ext) ext, -static const char* const lumiera_plugin_ext[] = +/* and now setup a table which will be used for dispatching loaders depending on the type of the plugin */ +#define LUMIERA_PLUGIN_TYPE(type, ext) {lumiera_plugin_load_##type, lumiera_plugin_unload_##type, ext}, +static lumiera_plugintype lumiera_plugin_types[] = { LUMIERA_PLUGIN_TYPES - NULL + {NULL, NULL, NULL} }; #undef LUMIERA_PLUGIN_TYPE - - struct lumiera_plugin_struct { psplaynode node; @@ -88,14 +106,46 @@ struct lumiera_plugin_struct /* time when the last open or close action happened */ time_t last; - /* kind of plugin */ - enum lumiera_plugin_type type; + /* when loading plugins en masse we do not want to fail completely if one doesnt cooperate, instead we record local errors here */ + lumiera_err error; - /* dlopen handle */ + /* the 'plugin' interface itself */ + LumieraInterface plugin; + + /* generic handle for the plugin, dlopen handle, etc */ void* handle; }; +LumieraPlugin +lumiera_plugin_new (const char* name) +{ + LumieraPlugin self = lumiera_malloc (sizeof (*self)); + + psplaynode_init (&self->node); + self->name = lumiera_strndup (name, SIZE_MAX); + self->refcnt = 0; + time (&self->last); + self->error = LUMIERA_ERROR_PLUGIN_INIT; + self->plugin = NULL; + self->handle = NULL; + return self; +} + + +LumieraPlugin +lumiera_plugin_init (LumieraPlugin self, void* handle, LumieraInterface plugin) +{ + self->error = lumiera_error (); + self->plugin = plugin; + self->handle = handle; + return self; +} + + + + +static char* init_exts_globs (); int lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), @@ -108,30 +158,7 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), /* construct glob trail {.so,.c,.foo} ... */ static char* exts_globs = NULL; if (!exts_globs) - { - size_t exts_sz = 4; /* / * { } \0 less one comma */ - const char*const* itr = lumiera_plugin_ext; - while (*itr) - { - exts_sz += strlen (*itr) + 1; - ++itr; - } - - exts_globs = lumiera_malloc (exts_sz); - *exts_globs = '\0'; - - itr = lumiera_plugin_ext; - strcat (exts_globs, "/*{"); - - while (*itr) - { - strcat (exts_globs, *itr); - strcat (exts_globs, ","); - ++itr; - } - exts_globs[exts_sz-2] = '}'; - TRACE (plugin, "initialized extension glob to '%s'", exts_globs); - } + exts_globs = init_exts_globs (&exts_globs); const char* path; unsigned i = 0; @@ -150,21 +177,18 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), ++i; } - LUMIERA_RECMUTEX_SECTION (plugin, &lumiera_interface_mutex) - { - for (char** itr = globs.gl_pathv; *itr; ++itr) - { - - if (!psplay_find (lumiera_pluginregistry, *itr, 100)) - { - TRACE (plugin, "found new plugin '%s'", *itr); - - LumieraPlugin plugin = callback_load (*itr); - if (plugin) - callback_register (plugin); - } - } - } + if (globs.gl_pathc) + LUMIERA_RECMUTEX_SECTION (plugin, &lumiera_interface_mutex) + { + for (char** itr = globs.gl_pathv; *itr; ++itr) + { + if (!psplay_find (lumiera_pluginregistry, *itr, 100)) + { + TRACE (plugin, "found new plugin '%s'", *itr); + callback_register (callback_load (*itr)); + } + } + } globfree (&globs); @@ -172,37 +196,90 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), } - - - LumieraPlugin lumiera_plugin_load (const char* plugin) { TRACE (plugin); - UNIMPLEMENTED(); - (void) plugin; + /* dispatch on ext, call the registered function */ + const char* ext = strrchr (plugin, '.'); + + LumieraPlugintype itr = lumiera_plugin_types; + while (itr->ext) + { + if (!strcmp (itr->ext, ext)) + return itr->lumiera_plugin_load_fn (plugin); + ++itr; + } return NULL; } - int lumiera_plugin_register (LumieraPlugin plugin) { TRACE (plugin); - UNIMPLEMENTED(); + if (!plugin) + return 1; LUMIERA_RECMUTEX_SECTION (plugin, &lumiera_interface_mutex) { - (void) plugin; - + if (psplay_insert (lumiera_pluginregistry, &plugin->node, 100)) + { + if (!plugin->error) + { + switch (lumiera_interface_version (plugin->plugin, "lumieraorg__plugin")) + { + case 0: + { + TRACE (plugin, "registering %s", plugin->name); + LUMIERA_INTERFACE_HANDLE(lumieraorg__plugin, 0) handle = + LUMIERA_INTERFACE_CAST(lumieraorg__plugin, 0) plugin->plugin; + lumiera_interfaceregistry_bulkregister_interfaces (handle->plugin_interfaces (), plugin); + } + break; + default: + LUMIERA_ERROR_SET (plugin, PLUGIN_VERSION); + } + } + } + else + { + LUMIERA_ERROR_SET (plugin, PLUGIN_REGISTER); + } } - return 0; + return !!lumiera_error_peek(); } +static char* init_exts_globs () +{ + char* exts_globs; + size_t exts_sz = 4; /* / * { } \0 less one comma */ + LumieraPlugintype itr = lumiera_plugin_types; + while (itr->ext) + { + exts_sz += strlen (itr->ext) + 1; + ++itr; + } + + exts_globs = lumiera_malloc (exts_sz); + *exts_globs = '\0'; + + itr = lumiera_plugin_types; + strcat (exts_globs, "/*{"); + + while (itr->ext) + { + strcat (exts_globs, itr->ext); + strcat (exts_globs, ","); + ++itr; + } + exts_globs[exts_sz-2] = '}'; + TRACE (plugin, "initialized extension glob to '%s'", exts_globs); + return exts_globs; +} int lumiera_plugin_cmp_fn (const void* keya, const void* keyb) diff --git a/src/backend/plugin.h b/src/backend/plugin.h index 8c0e5e7ae..03b963990 100644 --- a/src/backend/plugin.h +++ b/src/backend/plugin.h @@ -21,12 +21,14 @@ #ifndef LUMIERA_PLUGIN_H #define LUMIERA_PLUGIN_H +#include "lib/psplay.h" +#include "lib/error.h" + +#include "backend/interface.h" #include #include -#include "lib/error.h" - /** * @file * Lumiera plugins defines 'interfaces' as shown in interface.h, the plugin system handles the loading @@ -35,8 +37,11 @@ */ +LUMIERA_ERROR_DECLARE(PLUGIN_INIT); LUMIERA_ERROR_DECLARE(PLUGIN_DLOPEN); -LUMIERA_ERROR_DECLARE(PLUGIN_PLUGINPATH); +LUMIERA_ERROR_DECLARE(PLUGIN_WTF); +LUMIERA_ERROR_DECLARE(PLUGIN_REGISTER); +LUMIERA_ERROR_DECLARE(PLUGIN_VERSION); NOBUG_DECLARE_FLAG (plugin); @@ -47,6 +52,7 @@ NOBUG_DECLARE_FLAG (plugin); struct lumiera_plugin_struct; typedef struct lumiera_plugin_struct lumiera_plugin; typedef lumiera_plugin* LumieraPlugin; +enum lumiera_plugin_type; int @@ -55,6 +61,11 @@ lumiera_plugin_cmp_fn (const void* keya, const void* keyb); const void* lumiera_plugin_key_fn (const PSplaynode node); +LumieraPlugin +lumiera_plugin_new (const char* name); + +LumieraPlugin +lumiera_plugin_init (LumieraPlugin self, void* handle, LumieraInterface plugin); LumieraPlugin lumiera_plugin_load (const char* plugin); @@ -68,7 +79,7 @@ lumiera_plugin_register (LumieraPlugin); /** * discover new plugins - * traverses the configured plugin dirs and calls the callback_load function for any plugin + * traverses the configured plugin paths and calls the callback_load function for any plugin * not actually loaded. If callback_load returns a plugin (and not NULL) then this is feed to * the callback_register function. */ From 3155ae068f65c156705528eb60b77585aeead9ac Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 4 Nov 2008 08:05:53 +0100 Subject: [PATCH 48/59] Loading of dynamic modules * loads dynamic libs as module. * file extensions .so and .lum (LUmieraModule) - no unloading yet --- src/backend/plugin.c | 4 +-- src/backend/plugin_dynlib.c | 58 +++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/backend/plugin_dynlib.c diff --git a/src/backend/plugin.c b/src/backend/plugin.c index 66ebd345c..264cc8df5 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -58,8 +58,8 @@ LUMIERA_ERROR_DEFINE(PLUGIN_VERSION, "Plugin Version unsupported"); * and c source modules which get compiled on the fly. */ #define LUMIERA_PLUGIN_TYPES \ - LUMIERA_PLUGIN_TYPE_PLANNED(DYNLIB, ".so") \ - LUMIERA_PLUGIN_TYPE_PLANNED(DYNLIB, ".lum") \ + LUMIERA_PLUGIN_TYPE(DYNLIB, ".so") \ + LUMIERA_PLUGIN_TYPE(DYNLIB, ".lum") \ LUMIERA_PLUGIN_TYPE_PLANNED(LUA, ".lua") \ LUMIERA_PLUGIN_TYPE_PLANNED(CSOURCE, ".c") diff --git a/src/backend/plugin_dynlib.c b/src/backend/plugin_dynlib.c new file mode 100644 index 000000000..62b105078 --- /dev/null +++ b/src/backend/plugin_dynlib.c @@ -0,0 +1,58 @@ +/* + plugin_dynlib.c - Lumiera Plugin loader for dynamic libraries + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "backend/plugin.h" + +#include +#include + +/** + * @file + * Plugin loader for dynamic libraries. + */ + +LumieraPlugin +lumiera_plugin_load_DYNLIB (const char* name) +{ + TRACE (plugin); + LumieraPlugin self = lumiera_plugin_new (name); + LumieraInterface plugin = NULL; + + void* handle = dlopen (name, RTLD_LAZY|RTLD_LOCAL); + if (handle) + { + plugin = (LumieraInterface) dlsym (handle, LUMIERA_INTERFACE_DSTRING (lumieraorg__plugin, 0, lumieraorg_plugin)); + + if (!plugin) + LUMIERA_ERROR_SET (plugin, PLUGIN_WTF); + } + else + LUMIERA_ERROR_SET (plugin, PLUGIN_DLOPEN); + + return lumiera_plugin_init (self, handle, plugin); +} + + +void +lumiera_plugin_unload_DYNLIB (LumieraPlugin self) +{ + (void) self; + UNIMPLEMENTED(); +} From 2646b9035b50e6c1394333051f8e17a65d0110a4 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 5 Nov 2008 05:33:37 +0100 Subject: [PATCH 49/59] some plugin docwork --- src/backend/plugin.h | 93 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/src/backend/plugin.h b/src/backend/plugin.h index 03b963990..fe2204596 100644 --- a/src/backend/plugin.h +++ b/src/backend/plugin.h @@ -32,8 +32,28 @@ /** * @file * Lumiera plugins defines 'interfaces' as shown in interface.h, the plugin system handles the loading - * of all kinds of plugins under the hood, invoked from the interface system. Anything defined here is - * called internally and should not be used by other parts of the application. + * of all kinds of plugins under the hood, invoked from the interface system. Most things defined here + * are called internally and should not be used by other parts of the application. + * + * Plugin discovery + * The plugin_discover() function offers a automatic way to load and register new plugins. It traverses + * all configured plugin directories. It takes to function for loading and registering plugins as + * parameter, by now this only uses the here defined plugin_load() and plugin_register() functions + * which lets it load any newly found plugin unconditionally. Later these callbacks will be replaced by + * a smarter system (plugindb) which makes it possible to load plugins on-demand and select proper + * plugins based on their version and capabilities. + * + * Plugin loading + * Plugins are loaded and initialized in a sequence of steps: + * plugin_load() dispatches to a specific loader function depending on the type (extension) of a plugin. + * This loader allocates a new plugin structure with plugin_new() and then does it work and eventually + * finalizing the plugin structure initialization with plugin_init() by providing a handle to a + * lumieraorg__plugin interface. plugin_init() also stores the current error state (which might be clean) + * into the plugin. After that the plugin can be registered which records it in the pluginregistry and if + * its error state is clean, registering all interfaces it offers in the interface registry. With that + * the plugin is ready to be used. Plugins with the error state set should still be registered to prevent + * further discovery runs to try loading them again. + * */ @@ -54,27 +74,65 @@ typedef struct lumiera_plugin_struct lumiera_plugin; typedef lumiera_plugin* LumieraPlugin; enum lumiera_plugin_type; - -int -lumiera_plugin_cmp_fn (const void* keya, const void* keyb); - -const void* -lumiera_plugin_key_fn (const PSplaynode node); - +/** + * Allocates an preinitializes a plugin structure + * @internal + * @param name path/filename of the plugin + * @return new allocated/preinitialized plugin structure with its error state set to LUMIERA_ERROR_PLUGIN_INIT + */ LumieraPlugin lumiera_plugin_new (const char* name); +/** + * Complete plugin initialization + * @internal + * Stores any pending error (from loading) in self which clears out the LUMIERA_ERROR_PLUGIN_INIT error state + * which was initialized by lumiera_plugin_new(), stores the handle and plugin pointers in the plugin struct. + * @param self pointer to the plugin struct + * @param handle opaque handle refering to some plugin type specific data + * @param plugin a lumieraorg__plugin interface which will be used to initialize this plugin + */ LumieraPlugin lumiera_plugin_init (LumieraPlugin self, void* handle, LumieraInterface plugin); + +/** + * Tries to load a plugin + * Creates a new plugin structure and tries to load and initialize the plugin. + * The plugins error state may be set on any problem which should be queried later. + * @param plugin path/filename of the plugin to load + * @return pointer to the new plugin structure (always, never NULL, check error state) + */ LumieraPlugin lumiera_plugin_load (const char* plugin); + +/** + * Register a plugin and its interfaces. + * Registers the plugin (unconditionally) at the pluginregistry. + * When the error state of the plugin is NULL then use its lumieraorg__plugin interface + * to register all interfaces offered by the plugin at the interface registry. + * Registered plugins will be automatic unloaded at application end. + * @param self the plugin to be registered (calling with NULL is a no-op) + * @return 1 on success (including calling with NULL) and 0 when a error occured + */ int -lumiera_plugin_register (LumieraPlugin); +lumiera_plugin_register (LumieraPlugin self); +lumiera_err +lumiera_plugin_error (LumieraPlugin self); + + +/** + * Tries to unload a plugin. + * When the Plugin is unused, then all resources associated with it are freed and it will be removed from memory + * @param plugin name of the plugin to be unloaded. + * @return 0 on success, else the number if users which keeping the plugin loaded + */ +unsigned +lumiera_plugin_unload (LumieraPlugin self); /** @@ -88,17 +146,12 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), int (*callback_register) (LumieraPlugin)); - - - -/** - * Tries to unload a plugin. - * When the Plugin is unused, then all resources associated with it are freed and it will be removed from memory - * @param plugin name of the plugin to be unloaded. - * @return 0 on success, else the number if users which keeping the plugin loaded - */ +/* psplay support functions */ int -lumiera_plugin_unload (const char* plugin); +lumiera_plugin_cmp_fn (const void* keya, const void* keyb); + +const void* +lumiera_plugin_key_fn (const PSplaynode node); #endif /* LUMIERA_PLUGIN_H */ From c35e5fb0f9cdf85072545575eb062e619b5ca049 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 5 Nov 2008 08:04:34 +0100 Subject: [PATCH 50/59] Plugin unloading, at least manually works --- src/backend/plugin.c | 73 +++++++++++++++++++++++++++++++++++-- src/backend/plugin.h | 29 +++++++++++++-- src/backend/plugin_dynlib.c | 6 +-- 3 files changed, 98 insertions(+), 10 deletions(-) diff --git a/src/backend/plugin.c b/src/backend/plugin.c index 264cc8df5..5b0d87728 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -38,13 +38,15 @@ * Plugin loader. */ +/* just some declarations */ extern PSplay lumiera_pluginregistry; +static char* init_exts_globs (); -/* TODO should be set by the build system to the actual plugin path */ +/* TODO default plugin path should be set by the build system */ /* errors */ LUMIERA_ERROR_DEFINE(PLUGIN_INIT, "Initialization error"); -LUMIERA_ERROR_DEFINE(PLUGIN_DLOPEN, "Could not open plugin"); +LUMIERA_ERROR_DEFINE(PLUGIN_OPEN, "Could not open plugin"); LUMIERA_ERROR_DEFINE(PLUGIN_WTF, "Not a Lumiera plugin"); LUMIERA_ERROR_DEFINE(PLUGIN_REGISTER, "Could not register plugin"); LUMIERA_ERROR_DEFINE(PLUGIN_VERSION, "Plugin Version unsupported"); @@ -93,6 +95,8 @@ static lumiera_plugintype lumiera_plugin_types[] = #undef LUMIERA_PLUGIN_TYPE + + struct lumiera_plugin_struct { psplaynode node; @@ -143,9 +147,20 @@ lumiera_plugin_init (LumieraPlugin self, void* handle, LumieraInterface plugin) } +lumiera_err +lumiera_plugin_error (LumieraPlugin self) +{ + REQUIRE (self); + return self->error; +} +void * +lumiera_plugin_handle (LumieraPlugin self) +{ + REQUIRE (self); + return self->handle; +} -static char* init_exts_globs (); int lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), @@ -214,6 +229,7 @@ lumiera_plugin_load (const char* plugin) return NULL; } + int lumiera_plugin_register (LumieraPlugin plugin) { @@ -251,6 +267,57 @@ lumiera_plugin_register (LumieraPlugin plugin) } +unsigned +lumiera_plugin_unload (LumieraPlugin self) +{ + TRACE (plugin); + + if (!self) + return 0; + + if (self->refcnt) + return self->refcnt; + + /* dispatch on ext, call the registered function */ + const char* ext = strrchr (self->name, '.'); + + LumieraPlugintype itr = lumiera_plugin_types; + while (itr->ext) + { + if (!strcmp (itr->ext, ext)) + { + //unregister plugin + if (psplay_remove (lumiera_pluginregistry, &self->node)) + { + if (!self->error) + { + LUMIERA_INTERFACE_HANDLE(lumieraorg__plugin, 0) handle = + LUMIERA_INTERFACE_CAST(lumieraorg__plugin, 0) self->plugin; + + lumiera_interfaceregistry_bulkremove_interfaces (handle->plugin_interfaces ()); + } + itr->lumiera_plugin_unload_fn (self); + break; + } + } + ++itr; + } + + return 0; +} + + +LumieraPlugin +lumiera_plugin_lookup (const char* name) +{ + LumieraPlugin ret = NULL; + + if (name) + LUMIERA_RECMUTEX_SECTION (plugin, &lumiera_interface_mutex) + ret = (LumieraPlugin) psplay_find (lumiera_pluginregistry, name, 100); + + return ret; +} static char* init_exts_globs () diff --git a/src/backend/plugin.h b/src/backend/plugin.h index fe2204596..dcf9180f1 100644 --- a/src/backend/plugin.h +++ b/src/backend/plugin.h @@ -58,7 +58,7 @@ LUMIERA_ERROR_DECLARE(PLUGIN_INIT); -LUMIERA_ERROR_DECLARE(PLUGIN_DLOPEN); +LUMIERA_ERROR_DECLARE(PLUGIN_OPEN); LUMIERA_ERROR_DECLARE(PLUGIN_WTF); LUMIERA_ERROR_DECLARE(PLUGIN_REGISTER); LUMIERA_ERROR_DECLARE(PLUGIN_VERSION); @@ -107,7 +107,6 @@ LumieraPlugin lumiera_plugin_load (const char* plugin); - /** * Register a plugin and its interfaces. * Registers the plugin (unconditionally) at the pluginregistry. @@ -121,20 +120,42 @@ int lumiera_plugin_register (LumieraPlugin self); +/** + * Query the error state of a plugin + * @param self plugin to query + * @return error identifier, NULL if no error was set + */ lumiera_err lumiera_plugin_error (LumieraPlugin self); +/** + * Query the plugin handle + * @param self plugin to query + * @return opaque handle set by the loader functions + */ +void* +lumiera_plugin_handle (LumieraPlugin self); + /** * Tries to unload a plugin. * When the Plugin is unused, then all resources associated with it are freed and it will be removed from memory - * @param plugin name of the plugin to be unloaded. - * @return 0 on success, else the number if users which keeping the plugin loaded + * @param plugin the plugin to be unloaded. + * @return 0 on success, else the refcount of users which keeping the plugin loaded */ unsigned lumiera_plugin_unload (LumieraPlugin self); +/** + * Lookup a plugin handle in the pluginregistry + * @param name name of the plugin to be looked up + * @return plugin handle on success, NULL if the plugin is not found in the registry + */ +LumieraPlugin +lumiera_plugin_lookup (const char* name); + + /** * discover new plugins * traverses the configured plugin paths and calls the callback_load function for any plugin diff --git a/src/backend/plugin_dynlib.c b/src/backend/plugin_dynlib.c index 62b105078..75ce4aa89 100644 --- a/src/backend/plugin_dynlib.c +++ b/src/backend/plugin_dynlib.c @@ -44,7 +44,7 @@ lumiera_plugin_load_DYNLIB (const char* name) LUMIERA_ERROR_SET (plugin, PLUGIN_WTF); } else - LUMIERA_ERROR_SET (plugin, PLUGIN_DLOPEN); + LUMIERA_ERROR_SET (plugin, PLUGIN_OPEN); return lumiera_plugin_init (self, handle, plugin); } @@ -53,6 +53,6 @@ lumiera_plugin_load_DYNLIB (const char* name) void lumiera_plugin_unload_DYNLIB (LumieraPlugin self) { - (void) self; - UNIMPLEMENTED(); + TRACE (plugin); + dlclose (lumiera_plugin_handle (self)); } From 240e7cb295623040b0d788b611ecddafba7feb27 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 5 Nov 2008 09:43:59 +0100 Subject: [PATCH 51/59] plugin_unload must lock the registry tree --- src/backend/plugin.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/backend/plugin.c b/src/backend/plugin.c index 5b0d87728..69bac0525 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -286,19 +286,20 @@ lumiera_plugin_unload (LumieraPlugin self) { if (!strcmp (itr->ext, ext)) { - //unregister plugin - if (psplay_remove (lumiera_pluginregistry, &self->node)) + LUMIERA_RECMUTEX_SECTION (plugin, &lumiera_interface_mutex) { - if (!self->error) + if (psplay_remove (lumiera_pluginregistry, &self->node)) { - LUMIERA_INTERFACE_HANDLE(lumieraorg__plugin, 0) handle = - LUMIERA_INTERFACE_CAST(lumieraorg__plugin, 0) self->plugin; - - lumiera_interfaceregistry_bulkremove_interfaces (handle->plugin_interfaces ()); + if (!self->error) + { + LUMIERA_INTERFACE_HANDLE(lumieraorg__plugin, 0) handle = + LUMIERA_INTERFACE_CAST(lumieraorg__plugin, 0) self->plugin; + lumiera_interfaceregistry_bulkremove_interfaces (handle->plugin_interfaces ()); + } } - itr->lumiera_plugin_unload_fn (self); - break; } + itr->lumiera_plugin_unload_fn (self); + break; } ++itr; } From c26cd391b0160ca494eb033db4b445f771292f93 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 5 Nov 2008 09:47:52 +0100 Subject: [PATCH 52/59] automatic plugin unloading at interfaceregistry_destroy() All open plugins will be unloaded when the registry gets destroyed. If there are still interfaces open, this will assert at ALPHA builds. --- src/backend/interfaceregistry.c | 20 +++++++++----------- src/backend/plugin.c | 28 ++++++++++++++++++++++++++++ src/backend/plugin.h | 2 ++ src/backend/plugin_dynlib.c | 4 +++- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/backend/interfaceregistry.c b/src/backend/interfaceregistry.c index 05e2224a1..180c2043f 100644 --- a/src/backend/interfaceregistry.c +++ b/src/backend/interfaceregistry.c @@ -106,7 +106,7 @@ lumiera_interfaceregistry_init (void) if (!lumiera_interfaceregistry) LUMIERA_DIE (ERRNO); - lumiera_pluginregistry = psplay_new (lumiera_plugin_cmp_fn, lumiera_plugin_key_fn, NULL); + lumiera_pluginregistry = psplay_new (lumiera_plugin_cmp_fn, lumiera_plugin_key_fn, lumiera_plugin_delete_fn); if (!lumiera_pluginregistry) LUMIERA_DIE (ERRNO); @@ -118,20 +118,18 @@ void lumiera_interfaceregistry_destroy (void) { TRACE (interfaceregistry); - REQUIRE (!psplay_nelements (lumiera_interfaceregistry)); - - lumiera_mutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(interfaceregistry)); - - if (lumiera_interfaceregistry) - psplay_destroy (lumiera_interfaceregistry); - lumiera_interfaceregistry = NULL; - - TODO ("provide a delete function for the psplay tree to tear it down"); - REQUIRE (psplay_nelements (lumiera_pluginregistry) == 0, "plugins still loaded at destroy"); if (lumiera_pluginregistry) psplay_delete (lumiera_pluginregistry); lumiera_pluginregistry = NULL; + + lumiera_mutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(interfaceregistry)); + + REQUIRE (!psplay_nelements (lumiera_interfaceregistry), "some interfaces still registered at shutdown"); + + if (lumiera_interfaceregistry) + psplay_destroy (lumiera_interfaceregistry); + lumiera_interfaceregistry = NULL; } diff --git a/src/backend/plugin.c b/src/backend/plugin.c index 69bac0525..23d9aeed1 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -362,3 +362,31 @@ lumiera_plugin_key_fn (const PSplaynode node) return ((LumieraPlugin)node)->name; } + +void +lumiera_plugin_delete_fn (PSplaynode node) +{ + LumieraPlugin self = (LumieraPlugin) node; + + ENSURE (!self->refcnt, "plugin %s still in use at shutdown", self->name); + + + const char* ext = strrchr (self->name, '.'); + + LumieraPlugintype itr = lumiera_plugin_types; + while (itr->ext) + { + if (!strcmp (itr->ext, ext)) + { + if (!self->error) + { + LUMIERA_INTERFACE_HANDLE(lumieraorg__plugin, 0) handle = + LUMIERA_INTERFACE_CAST(lumieraorg__plugin, 0) self->plugin; + lumiera_interfaceregistry_bulkremove_interfaces (handle->plugin_interfaces ()); + } + itr->lumiera_plugin_unload_fn (self); + break; + } + ++itr; + } +} diff --git a/src/backend/plugin.h b/src/backend/plugin.h index dcf9180f1..b7ccd5326 100644 --- a/src/backend/plugin.h +++ b/src/backend/plugin.h @@ -174,5 +174,7 @@ lumiera_plugin_cmp_fn (const void* keya, const void* keyb); const void* lumiera_plugin_key_fn (const PSplaynode node); +void +lumiera_plugin_delete_fn (PSplaynode node); #endif /* LUMIERA_PLUGIN_H */ diff --git a/src/backend/plugin_dynlib.c b/src/backend/plugin_dynlib.c index 75ce4aa89..50030843c 100644 --- a/src/backend/plugin_dynlib.c +++ b/src/backend/plugin_dynlib.c @@ -54,5 +54,7 @@ void lumiera_plugin_unload_DYNLIB (LumieraPlugin self) { TRACE (plugin); - dlclose (lumiera_plugin_handle (self)); + void* handle = lumiera_plugin_handle (self); + if (handle) + dlclose (handle); } From 7afce647fbeaf376019507ce472664c2f927382a Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 5 Nov 2008 11:11:25 +0100 Subject: [PATCH 53/59] few tool functions for the plugin implementation * plugin_name() to figure out the name of the plugin * plugin_refinc() and plugin_refdec() to manage the refcount --- src/backend/plugin.c | 25 +++++++++++++++++++++++-- src/backend/plugin.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/backend/plugin.c b/src/backend/plugin.c index 23d9aeed1..f66c73456 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -154,7 +154,8 @@ lumiera_plugin_error (LumieraPlugin self) return self->error; } -void * + +void* lumiera_plugin_handle (LumieraPlugin self) { REQUIRE (self); @@ -162,6 +163,27 @@ lumiera_plugin_handle (LumieraPlugin self) } +const char* +lumiera_plugin_name (LumieraPlugin self) +{ + return self?self->name:NULL; +} + + +void +lumiera_plugin_refinc (LumieraPlugin self) +{ + ++self->refcnt; +} + + +void +lumiera_plugin_refdec (LumieraPlugin self) +{ + --self->refcnt; +} + + int lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), int (*callback_register) (LumieraPlugin)) @@ -370,7 +392,6 @@ lumiera_plugin_delete_fn (PSplaynode node) ENSURE (!self->refcnt, "plugin %s still in use at shutdown", self->name); - const char* ext = strrchr (self->name, '.'); LumieraPlugintype itr = lumiera_plugin_types; diff --git a/src/backend/plugin.h b/src/backend/plugin.h index b7ccd5326..26451edac 100644 --- a/src/backend/plugin.h +++ b/src/backend/plugin.h @@ -137,6 +137,34 @@ void* lumiera_plugin_handle (LumieraPlugin self); +/** + * Query the plugin name + * The name is the path and filname under which it was loaded + * @param self plugin to query + * @return pointer to the name string + */ +const char* +lumiera_plugin_name (LumieraPlugin self); + + +/** + * Increment refcount + * @internal + * @param self plugin which refcount to increment + */ +void +lumiera_plugin_refinc (LumieraPlugin self); + + +/** + * Decrement refcount + * @internal + * @param self plugin which refcount to decrement + */ +void +lumiera_plugin_refdec (LumieraPlugin self); + + /** * Tries to unload a plugin. * When the Plugin is unused, then all resources associated with it are freed and it will be removed from memory From fa6b6d54e9b2c9d6dd349bb003b0a8f735eea9a4 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 5 Nov 2008 11:12:48 +0100 Subject: [PATCH 54/59] hook the plugin refcounting in The plugin refcounter is driven from interface opening/closing, this is quite internal. The 'last' time in plugin now records the last time the refcounter dropped to 0, this is just sufficient enough to find out how long a plugin is unused. --- src/backend/interface.c | 9 ++++++++- src/backend/interfaceregistry.c | 2 -- src/backend/plugin.c | 5 +++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/backend/interface.c b/src/backend/interface.c index 26fa3a42e..22e94cbcc 100644 --- a/src/backend/interface.c +++ b/src/backend/interface.c @@ -22,6 +22,7 @@ #include "lib/mutex.h" #include "lib/safeclib.h" +#include "backend/plugin.h" #include "backend/interface.h" #include "backend/interfaceregistry.h" @@ -133,8 +134,9 @@ depwalk (LumieraInterfacenode self, LumieraInterfacenode* stack) if (!cycle) { + if ((*dep)->plugin) + lumiera_plugin_refinc ((*dep)->plugin); ++(*dep)->refcnt; - (*dep)->lnk = *stack; *stack = *dep; @@ -184,7 +186,10 @@ lumiera_interface_open_interfacenode (LumieraInterfacenode self) if (!cycle) { + if (self->plugin) + lumiera_plugin_refinc (self->plugin); ++self->refcnt; + self->lnk = stack; stack = self; int collect_dependencies_bak = collect_dependencies; @@ -290,6 +295,8 @@ lumiera_interfacenode_close (LumieraInterfacenode self) stack = self->lnk; self->lnk = NULL; + if (self->plugin) + lumiera_plugin_refdec (self->plugin); --self->refcnt; } } diff --git a/src/backend/interfaceregistry.c b/src/backend/interfaceregistry.c index 180c2043f..969ab23e0 100644 --- a/src/backend/interfaceregistry.c +++ b/src/backend/interfaceregistry.c @@ -65,7 +65,6 @@ lumiera_interfacenode_new (LumieraInterface iface, LumieraPlugin plugin) self->interface = iface; self->refcnt = 0; self->plugin = plugin; - FIXME ("plugin handling (refcnt, atime)"); self->lnk = NULL; self->deps_size = 0; self->deps = NULL; @@ -80,7 +79,6 @@ lumiera_interfacenode_delete (LumieraInterfacenode self) if (self) { REQUIRE (self->refcnt == 0); - FIXME ("plugin handling"); lumiera_free (self->deps); lumiera_free (self); } diff --git a/src/backend/plugin.c b/src/backend/plugin.c index f66c73456..768157946 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -107,7 +107,7 @@ struct lumiera_plugin_struct /* use count for all interfaces of this plugin */ unsigned refcnt; - /* time when the last open or close action happened */ + /* time when the refcounter dropped to 0 last time */ time_t last; /* when loading plugins en masse we do not want to fail completely if one doesnt cooperate, instead we record local errors here */ @@ -180,7 +180,8 @@ lumiera_plugin_refinc (LumieraPlugin self) void lumiera_plugin_refdec (LumieraPlugin self) { - --self->refcnt; + if (!--self->refcnt) + time (&self->last); } From d5c61c0e9ddc8496b3963fc139c7390dfd51754c Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 5 Nov 2008 11:13:42 +0100 Subject: [PATCH 55/59] let plugin_discover() barf out when the plugin.path config cant be found --- src/backend/plugin.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backend/plugin.c b/src/backend/plugin.c index 768157946..0bba34409 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -215,6 +215,9 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), ++i; } + if (lumiera_error_peek ()) + return 0; + if (globs.gl_pathc) LUMIERA_RECMUTEX_SECTION (plugin, &lumiera_interface_mutex) { From 038f1279466c25dfa41c64e2149620d80d5cd4d6 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 4 Nov 2008 08:07:48 +0100 Subject: [PATCH 56/59] testsuite updates * Makefile.am removed -lm, added $(LUMIERA_PLUGIN_LIBS) * simple test for the plugin loader * remove the old 20plugin.tests, new 31plugin.tests --- tests/20plugin.tests | 24 ------------- tests/31plugin.tests | 29 ++++++++++++++++ tests/Makefile.am | 18 +++++----- tests/backend/test-interfaces.c | 61 +++++++++++++++++++++++++++++++-- 4 files changed, 97 insertions(+), 35 deletions(-) delete mode 100644 tests/20plugin.tests create mode 100644 tests/31plugin.tests diff --git a/tests/20plugin.tests b/tests/20plugin.tests deleted file mode 100644 index d1d9fba2f..000000000 --- a/tests/20plugin.tests +++ /dev/null @@ -1,24 +0,0 @@ -TESTING "test plugin example code" ./test-plugin - -PLANNED "C plugin example" C <hello (); + german->goodbye ("Welt!"); + + english->hello (); + english->goodbye ("World!"); + + LUMIERA_INTERFACE_CLOSE (german); + LUMIERA_INTERFACE_CLOSE (english); + + lumiera_interfaceregistry_destroy (); + lumiera_config_destroy (); } TESTS_END From c04f1e77d6736dcb86aea876ce8efa5636dc2fac Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Thu, 6 Nov 2008 04:13:13 +0100 Subject: [PATCH 57/59] set LUMIERA_PLUGIN_PATH to $pkglibdir as default --- src/backend/Makefile.am | 3 ++- src/backend/plugin.c | 15 +++++++++------ tests/31plugin.tests | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index d8c0c159e..f37f51a57 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -18,7 +18,8 @@ liblumibackend_a_srcdir = $(top_srcdir)/src/backend noinst_LIBRARIES += liblumibackend.a -liblumibackend_a_CFLAGS = $(CFLAGS) -std=gnu99 -Wextra -Wall -Werror +liblumibackend_a_CPPFLAGS = $(AM_CPPFLAGS) -DLUMIERA_PLUGIN_PATH="\"$(pkglibdir)\"" +liblumibackend_a_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror liblumibackend_a_SOURCES = \ $(liblumibackend_a_srcdir)/mediaaccessfacade.cpp \ diff --git a/src/backend/plugin.c b/src/backend/plugin.c index 0bba34409..ea189b57e 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -33,6 +33,10 @@ #include +#ifndef LUMIERA_PLUGIN_PATH +#error TODO: hey ichthyo, please figure the $pkglib path out by scons and use it as -DLUMIERA_PLUGIN_PATH for this source +#endif + /** * @file * Plugin loader. @@ -193,6 +197,8 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), REQUIRE (callback_load); REQUIRE (callback_register); + lumiera_config_setdefault ("plugin.path ="LUMIERA_PLUGIN_PATH); + /* construct glob trail {.so,.c,.foo} ... */ static char* exts_globs = NULL; if (!exts_globs) @@ -205,7 +211,7 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), while ((path = lumiera_config_wordlist_get_nth ("plugin.path", i, ":"))) { - path = lumiera_tmpbuf_snprintf (SIZE_MAX,"%s%s", path, exts_globs); + path = lumiera_tmpbuf_snprintf (SIZE_MAX,"%s/%s", path, exts_globs); TRACE (plugin, "globbing path '%s'", path); int ret = glob (path, flags, NULL, &globs); if (ret == GLOB_NOSPACE) @@ -215,9 +221,6 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin), ++i; } - if (lumiera_error_peek ()) - return 0; - if (globs.gl_pathc) LUMIERA_RECMUTEX_SECTION (plugin, &lumiera_interface_mutex) { @@ -350,7 +353,7 @@ lumiera_plugin_lookup (const char* name) static char* init_exts_globs () { char* exts_globs; - size_t exts_sz = 4; /* / * { } \0 less one comma */ + size_t exts_sz = 3; /* * { } \0 less one comma */ LumieraPlugintype itr = lumiera_plugin_types; while (itr->ext) { @@ -362,7 +365,7 @@ static char* init_exts_globs () *exts_globs = '\0'; itr = lumiera_plugin_types; - strcat (exts_globs, "/*{"); + strcat (exts_globs, "*{"); while (itr->ext) { diff --git a/tests/31plugin.tests b/tests/31plugin.tests index d2107dd3c..776f79da6 100644 --- a/tests/31plugin.tests +++ b/tests/31plugin.tests @@ -2,7 +2,7 @@ TESTING "testing plugins" ./test-interfaces TEST "discovering plugins, missing path" plugin_discover < Date: Thu, 6 Nov 2008 05:23:47 +0100 Subject: [PATCH 58/59] LUMIERA_PLUGIN is dead, long life LUMIERA_PLUGIN removes the difference in compiled in and plugin interfaces. * All interfaces are now defined with LUMIERA_EXPORT(...) * The definition of LUMIERA_PLUGIN at compile time takes action to compile as plugin which gets automatically managed. * compiled in (core) interfaces need still be registered, this is simplified with the LUMIERA_INTERFACE_REGISTEREXPORTED and LUMIERA_INTERFACE_UNREGISTEREXPORTED macros which become no-ops for plugins. --- src/backend/interface.h | 64 +++++++++++++++++------------ tests/Makefile.am | 2 +- tests/backend/example_plugin.c | 45 ++++++++++----------- tests/backend/test-interfaces.c | 72 ++++++++++++++++----------------- 4 files changed, 96 insertions(+), 87 deletions(-) diff --git a/src/backend/interface.h b/src/backend/interface.h index c84238d1c..e962a2d10 100644 --- a/src/backend/interface.h +++ b/src/backend/interface.h @@ -268,16 +268,16 @@ LUMIERA_INTERFACE_INSTANCE (iname, version, /** * Generate interface container suitable for enumerating interfaces. * This takes a list of interface definitions, instantiates them and places pointers to them - * into a zero terminated array which address is returned by the a created function. - * For interfaces generated by he core, the user is responsible to register these at the - * plugindb dynamically - * @param queryfunc name of the function to be created. - * @param ... list of LUMIERA_INTERFACE_DEFINE() for all interfaces this plugin provides. + * into a zero terminated array which address is returned by a static function named 'lumiera_plugin_interfaces'. + * For interfaces generated by he core, the user is responsible to register these dynamically. + * When LUMIERA_PLUGIN is defined, things change and an additional 'lumieraorg__plugin' interface is generated. + * The plugin loader then uses this to register the provided interfaces automatically. + * @param ... list of LUMIERA_INTERFACE_DEFINE()/LUMIERA_INTERFACE_INLINE() for all interfaces this plugin provides. */ -#define LUMIERA_EXPORT(queryfunc, ...) \ +#define LUMIERA_EXPORT(...) \ PPMPL_FOREACH_L1(_P1_, __VA_ARGS__) \ static LumieraInterface* \ -queryfunc (void) \ +lumiera_plugin_interfaces (void) \ { \ static LumieraInterface interfaces[] = \ { \ @@ -285,30 +285,42 @@ queryfunc (void) \ NULL \ }; \ return interfaces; \ -} +} \ +LUMIERA_PLUGININTERFACE /** - * Generate interface container suitable for a lumiera plugin. - * This takes a list of interface definitions and places pointers to them into a zero terminated array. Further - * it instances a local 'plugin interface' which will be picked up by the plugin loader to query the array of - * provided interfaces. - * @param descriptor pointer to an interface instance which provides a description of this plugin, might be NULL - * @param acquire a function which is called whenever the plugin interface is opened for using, might be NULL - * @param release a function which is called whenever this plugin interface is closed after use, might be NULL - * @param luid unique identifier for the this plugin interfaces query, use the magic word LUIDGEN here and run the - * lumiera uuid generator tool (to be written) over the source file to generate luid's automatically - * @param ... list of LUMIERA_INTERFACE_DEFINE() for all interfaces this plugin provides. + * Create a plugin interface when being copiled as plugin */ -#define LUMIERA_PLUGIN(acquire, release, luid, ...) \ -LUMIERA_EXPORT(plugin_interfaces, __VA_ARGS__) \ -LUMIERA_INTERFACE_INSTANCE (lumieraorg__plugin, 0, \ - lumieraorg_plugin, \ - NULL, \ - acquire, \ - release, \ - LUMIERA_INTERFACE_MAP (plugin_interfaces, luid, plugin_interfaces) \ +#ifdef LUMIERA_PLUGIN +#define LUMIERA_PLUGININTERFACE \ +LUMIERA_INTERFACE_INSTANCE (lumieraorg__plugin, 0, \ + lumieraorg_plugin, \ + NULL, \ + NULL, \ + NULL, \ + LUMIERA_INTERFACE_MAP (plugin_interfaces, \ + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", \ + lumiera_plugin_interfaces) \ ); +#define LUMIERA_INTERFACE_REGISTEREXPORTED +#define LUMIERA_INTERFACE_UNREGISTEREXPORTED +#else +#define LUMIERA_PLUGININTERFACE +/** + * Register all exported interfaces when not a plugin + * This is a no-op when LUMIERA_PLUGIN is defined, since plugins are automatically registered + */ +#define LUMIERA_INTERFACE_REGISTEREXPORTED \ + lumiera_interfaceregistry_bulkregister_interfaces (lumiera_plugin_interfaces(), NULL) +/** + * Unregister all exported interfaces when not a plugin + * This is a no-op when LUMIERA_PLUGIN is defined, since plugins are automatically registered + */ +#define LUMIERA_INTERFACE_UNREGISTEREXPORTED \ + lumiera_interfaceregistry_bulkremove_interfaces (lumiera_plugin_interfaces()) +#endif + /** * create a handle for a interface (WIP) diff --git a/tests/Makefile.am b/tests/Makefile.am index 12be3704d..ce422a4e8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -65,7 +65,7 @@ test_config_LDADD = liblumibackend.a liblumiera.a $(NOBUGMT_LUMIERA_LIBS) check_LTLIBRARIES += examplepluginc.la examplepluginc_la_SOURCES = $(tests_srcdir)/backend/example_plugin.c -examplepluginc_la_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ +examplepluginc_la_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -DLUMIERA_PLUGIN -I$(top_srcdir)/src/ examplepluginc_la_LDFLAGS = -module -avoid-version -no-undefined -rpath /dev/null check_PROGRAMS += test-interfaces diff --git a/tests/backend/example_plugin.c b/tests/backend/example_plugin.c index 346585190..66a93c838 100644 --- a/tests/backend/example_plugin.c +++ b/tests/backend/example_plugin.c @@ -103,26 +103,25 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, ); -LUMIERA_PLUGIN (NULL, NULL, - "\046\150\040\062\077\110\134\143\236\244\346\365\072\377\371\263", - LUMIERA_INTERFACE_DEFINE (lumieraorg_testhello, 0, - lumieraorg_hello_german, - LUMIERA_INTERFACE_REF (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor), - NULL, - NULL, - LUMIERA_INTERFACE_MAP (hello, "\167\012\306\023\031\151\006\362\026\003\125\017\170\022\100\333", - hallo), - LUMIERA_INTERFACE_MAP (goodbye, "\324\267\214\166\340\213\155\053\157\125\064\264\167\235\020\223", - tschuess) - ), - LUMIERA_INTERFACE_DEFINE (lumieraorg_testhello, 0, - lumieraorg_hello_english, - LUMIERA_INTERFACE_REF (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor), - NULL, - NULL, - LUMIERA_INTERFACE_MAP (hello, "\326\247\370\247\032\103\223\357\262\007\356\042\051\330\073\116", - hello), - LUMIERA_INTERFACE_MAP (goodbye, "\365\141\371\047\101\230\050\106\071\231\022\235\325\112\354\241", - bye) - ) - ) +LUMIERA_EXPORT( + LUMIERA_INTERFACE_DEFINE (lumieraorg_testhello, 0, + lumieraorg_hello_german, + LUMIERA_INTERFACE_REF (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor), + NULL, + NULL, + LUMIERA_INTERFACE_MAP (hello, "\167\012\306\023\031\151\006\362\026\003\125\017\170\022\100\333", + hallo), + LUMIERA_INTERFACE_MAP (goodbye, "\324\267\214\166\340\213\155\053\157\125\064\264\167\235\020\223", + tschuess) + ), + LUMIERA_INTERFACE_DEFINE (lumieraorg_testhello, 0, + lumieraorg_hello_english, + LUMIERA_INTERFACE_REF (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor), + NULL, + NULL, + LUMIERA_INTERFACE_MAP (hello, "\326\247\370\247\032\103\223\357\262\007\356\042\051\330\073\116", + hello), + LUMIERA_INTERFACE_MAP (goodbye, "\365\141\371\047\101\230\050\106\071\231\022\235\325\112\354\241", + bye) + ) + ) diff --git a/tests/backend/test-interfaces.c b/tests/backend/test-interfaces.c index f4355cc3b..a087da735 100644 --- a/tests/backend/test-interfaces.c +++ b/tests/backend/test-interfaces.c @@ -146,28 +146,6 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, -LUMIERA_EXPORT (interfaces_defined_here, - LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_one, 0, - lumieraorg_first_test, - LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor), - testacquire, - testrelease, - LUMIERA_INTERFACE_MAP (foo1, "\214\310\136\372\003\344\163\377\075\100\070\200\375\221\227\324", - testfunc), - LUMIERA_INTERFACE_MAP (bar1, "\262\253\067\211\157\052\212\140\114\334\231\250\340\075\214\030", - testfunc) - ), - LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_two, 0, - lumieraorg_second_test, - LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor), - testacquire, - testrelease, - LUMIERA_INTERFACE_MAP (foo2, "\110\152\002\271\363\052\324\272\373\045\132\270\277\000\271\217", - testfunc), - LUMIERA_INTERFACE_MAP (bar2, "\376\042\027\336\355\113\132\233\350\312\170\077\377\370\356\167", - testfunc) - ) - ); /* @@ -267,7 +245,27 @@ testrelease_four (LumieraInterface self) } -LUMIERA_EXPORT (dependencytests, +LUMIERA_EXPORT ( + LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_one, 0, + lumieraorg_first_test, + LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor), + testacquire, + testrelease, + LUMIERA_INTERFACE_MAP (foo1, "\214\310\136\372\003\344\163\377\075\100\070\200\375\221\227\324", + testfunc), + LUMIERA_INTERFACE_MAP (bar1, "\262\253\067\211\157\052\212\140\114\334\231\250\340\075\214\030", + testfunc) + ), + LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_two, 0, + lumieraorg_second_test, + LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor), + testacquire, + testrelease, + LUMIERA_INTERFACE_MAP (foo2, "\110\152\002\271\363\052\324\272\373\045\132\270\277\000\271\217", + testfunc), + LUMIERA_INTERFACE_MAP (bar2, "\376\042\027\336\355\113\132\233\350\312\170\077\377\370\356\167", + testfunc) + ), LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_void, 0, lumieraorg_dependencytest_one, LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor), @@ -301,7 +299,7 @@ TEST ("basic") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (interfaces_defined_here(), NULL); + lumiera_interfaceregistry_bulkregister_interfaces (lumiera_plugin_interfaces(), NULL); /* some ugly lowlevel handling tests */ @@ -317,14 +315,14 @@ TEST ("basic") handle2->foo2 ("this is foo2"); - lumiera_interfaceregistry_bulkremove_interfaces (interfaces_defined_here()); + LUMIERA_INTERFACE_UNREGISTEREXPORTED; lumiera_interfaceregistry_destroy (); } TEST ("open_close") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (interfaces_defined_here(), NULL); + lumiera_interfaceregistry_bulkregister_interfaces (lumiera_plugin_interfaces(), NULL); LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_one, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_one, 0, 0, lumieraorg_first_test); @@ -334,14 +332,14 @@ TEST ("open_close") lumiera_interface_close ((LumieraInterface)handle); - lumiera_interfaceregistry_bulkremove_interfaces (interfaces_defined_here()); + LUMIERA_INTERFACE_UNREGISTEREXPORTED; lumiera_interfaceregistry_destroy (); } TEST ("dependencies_one") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); + LUMIERA_INTERFACE_REGISTEREXPORTED; LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_one); @@ -351,7 +349,7 @@ TEST ("dependencies_one") lumiera_interface_close ((LumieraInterface)handle); - lumiera_interfaceregistry_bulkremove_interfaces (dependencytests()); + LUMIERA_INTERFACE_UNREGISTEREXPORTED; lumiera_interfaceregistry_destroy (); } @@ -359,7 +357,7 @@ TEST ("dependencies_one") TEST ("dependencies_two") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); + LUMIERA_INTERFACE_REGISTEREXPORTED; LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two); @@ -369,14 +367,14 @@ TEST ("dependencies_two") lumiera_interface_close ((LumieraInterface)handle); - lumiera_interfaceregistry_bulkremove_interfaces (dependencytests()); + LUMIERA_INTERFACE_UNREGISTEREXPORTED; lumiera_interfaceregistry_destroy (); } TEST ("dependencies_three") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); + LUMIERA_INTERFACE_REGISTEREXPORTED; LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_three); @@ -386,7 +384,7 @@ TEST ("dependencies_three") lumiera_interface_close ((LumieraInterface)handle); - lumiera_interfaceregistry_bulkremove_interfaces (dependencytests()); + LUMIERA_INTERFACE_UNREGISTEREXPORTED; lumiera_interfaceregistry_destroy (); } @@ -394,7 +392,7 @@ TEST ("dependencies_three") TEST ("dependencies_four") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); + LUMIERA_INTERFACE_REGISTEREXPORTED; LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_four); @@ -404,7 +402,7 @@ TEST ("dependencies_four") lumiera_interface_close ((LumieraInterface)handle); - lumiera_interfaceregistry_bulkremove_interfaces (dependencytests()); + LUMIERA_INTERFACE_UNREGISTEREXPORTED; lumiera_interfaceregistry_destroy (); } @@ -413,7 +411,7 @@ TEST ("dependencies_four") TEST ("dependencies_all") { lumiera_interfaceregistry_init (); - lumiera_interfaceregistry_bulkregister_interfaces (dependencytests(), NULL); + LUMIERA_INTERFACE_REGISTEREXPORTED; TRACE (tests, "OPEN one"); LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle_one = @@ -450,7 +448,7 @@ TEST ("dependencies_all") lumiera_interface_close ((LumieraInterface)handle_one); - lumiera_interfaceregistry_bulkremove_interfaces (dependencytests()); + LUMIERA_INTERFACE_UNREGISTEREXPORTED; lumiera_interfaceregistry_destroy (); } From 58bcc59a908cc8ae98bf2b6cd4c28262565559b3 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Thu, 6 Nov 2008 05:38:33 +0100 Subject: [PATCH 59/59] The incomplete Guide to Lumiera Configuration This shall become a reference of all (most) lumiera configuation keys. So far this is only prelimary located in the doc/devel dir and will be moved to the documentation wiki as soon as it becomes available. --- doc/devel/config_guide.txt | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 doc/devel/config_guide.txt diff --git a/doc/devel/config_guide.txt b/doc/devel/config_guide.txt new file mode 100644 index 000000000..a4a5d711d --- /dev/null +++ b/doc/devel/config_guide.txt @@ -0,0 +1,80 @@ +The incomplete Guide to Lumiera Configuration +============================================== + +DONT EDIT THE CONFIG IF YOU DONT KNOW WHAT YOU ARE DOING! +Misconfiguration will break Lumiera and may destroy all your data! + +Order is roughly alphabetically, depending on the mood of the writer. +Defaults are noted if present. Not all are implemented yet. + +General Introduction +-------------------- + +Lumiera uses plaintext files with a INI file like syntax for +configuration. This Syntax is strictly line based. There are only a +few syntactic elements. + +TODO:describe config syntax here + +Config Subsystem +---------------- + +The path where Lumiera searches its configuration. Single components are +separated by colons as in PATH and other such environment variables. +Here it might be handy that any Lumiera configuration can be +overridden by a environment variable: +'LUMIERA_CONFIG_PATH=somewhere:else lumiera ...' +A default are initialized at installation time, this is important to +bootstrap the whole configuration system. + + config.path + + +The config system check for a preferred format when writing config +entries. For each key 'foo.bar', these can be overridden with a key +'config.format.foo.bar' linking to the desired format. + + config.formatkey ='config.format.%s' + + +The following are links to the default formatting when no explicit +format is set for a key. Changing these to a wrong type will break the +system! + + config.formatdef.link < config.formatstr.link + config.formatdef.number < config.formatstr.number.dec + config.formatdef.real < config.formatstr.real + config.formatdef.string < config.formatstr.string + config.formatdef.word < config.formatstr.word + config.formatdef.bool < config.formatstr.bool + + +This are the low level formating specifications for the buildin +types, DONT TOUCH THESE! + + config.formatstr.link = '< %s' + config.formatstr.number.dec = '= %lld' + config.formatstr.number.hex = '= 0x%llX' + config.formatstr.number.oct = '= 0%llo' + config.formatstr.real = '= %Lg' + config.formatstr.real.dec = '= %Lf' + config.formatstr.real.sci = '= %Le' + config.formatstr.string = '= %s' + config.formatstr.string.dquoted = '= \"%s\"' + config.formatstr.string.quoted = '= ''%s''' + config.formatstr.word = '= %s' + config.formatstr.bool = '= %d' + + +Plugin System +------------- + +The path where Lumiera searches its plugins. Single components are +separated by colons as in PATH and other such environment variables. +Here it might be handy that any Lumiera configuration can be +overridden by a environment variable: +'LUMIERA_PLUGIN_PATH=somewhere:else lumiera ...' +Sensible defaults are initialized at installation time. + + plugin.path +