From 9a881c95dff2fa707b3cb64de1c99041df83158e Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 6 Dec 2010 03:40:15 +0100 Subject: [PATCH 01/30] Enable lock/unlock and disable/enable individual tracks in the GUI --- src/gui/widgets/timeline/timeline-track.cpp | 42 ++++++++++++++++++++- src/gui/widgets/timeline/timeline-track.hpp | 14 ++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index b6c69a698..1803a12d2 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -40,8 +40,10 @@ Track::Track(TimelineWidget &timeline_widget, shared_ptr track) : timelineWidget(timeline_widget), model_track(track), + enabled(true), expanded(true), expandDirection(None), + locked(false), headerWidget(*this), enableButton(Gtk::StockID("track_enabled"), WindowManager::MenuIconSize), lockButton(Gtk::StockID("track_unlocked"), WindowManager::MenuIconSize) @@ -51,8 +53,8 @@ Track::Track(TimelineWidget &timeline_widget, titleMenuButton.set_relief(RELIEF_HALF); titleMenuButton.unset_flags(CAN_FOCUS); - buttonBar.append(enableButton); - buttonBar.append(lockButton); + buttonBar.append(enableButton, mem_fun(this, &Track::on_enable)); + buttonBar.append(lockButton, mem_fun(this, &Track::on_lock)); headerWidget.set_child_widget(headerBox); @@ -71,6 +73,10 @@ Track::Track(TimelineWidget &timeline_widget, update_name(); + // Setup tooltips + enableButton.set_tooltip_text(_("Disable track")); + lockButton.set_tooltip_text(_("Lock track")); + // Setup the context menu Menu::MenuList& context_list = contextMenu.items(); //context_list.push_back( Menu_Helpers::MenuElem(_("_Add Track"), @@ -226,6 +232,38 @@ Track::update_name() titleMenuButton.set_label(model_track->get_name()); } +void +Track::on_enable() +{ + enabled = !enabled; + if (enabled) + { + enableButton.set_stock_id(Gtk::StockID("track_enabled"), WindowManager::MenuIconSize); + enableButton.set_tooltip_text(_("Disable track")); + } + else + { + enableButton.set_stock_id(Gtk::StockID("track_disabled"), WindowManager::MenuIconSize); + enableButton.set_tooltip_text(_("Enable track")); + } +} + +void +Track::on_lock() +{ + locked = !locked; + if (locked) + { + lockButton.set_stock_id(Gtk::StockID("track_locked"), WindowManager::MenuIconSize); + lockButton.set_tooltip_text(_("Unlock track")); + } + else + { + lockButton.set_stock_id(Gtk::StockID("track_unlocked"), WindowManager::MenuIconSize); + lockButton.set_tooltip_text(_("Lock track")); + } +} + void Track::on_set_name() { diff --git a/src/gui/widgets/timeline/timeline-track.hpp b/src/gui/widgets/timeline/timeline-track.hpp index fbb6b56cc..1b1b967d4 100644 --- a/src/gui/widgets/timeline/timeline-track.hpp +++ b/src/gui/widgets/timeline/timeline-track.hpp @@ -141,6 +141,8 @@ private: private: //----- Event Handlers -----// + void on_enable(); + void on_lock(); void on_set_name(); /** @@ -157,12 +159,17 @@ protected: private: + /** + * True if this track is enabled. + */ + bool enabled; + /** * This bool is true if this branch is expanded. false if it is * collapsed. **/ bool expanded; - + /** * This enum specifies which direction the expand/collapse animation * is moving - if any. @@ -187,6 +194,11 @@ private: **/ boost::scoped_ptr expand_timer; + /** + * True if this track is locked. + */ + bool locked; + //----- Header Widgets ------// timeline::TimelineHeaderWidget headerWidget; From df15c3d654a26f9e99bfaa21b96210ec0493054a Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 6 Dec 2010 03:41:07 +0100 Subject: [PATCH 02/30] Change format of placeholder in About/Credits to stop it from being a clickable link --- src/gui/gtk-lumiera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index 65b448f40..624a7f68f 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -116,7 +116,7 @@ GtkLumiera::get_app_authors() "Joel Holdsworth", "Christian Thaeter", "Hermann Vosseler", - ""}; + "[Other Authors Here]"}; const int count = sizeof(app_authors) / sizeof(gchar*); std::vector list(count); From c6f03f79bcfb597916921169de90d4f24eb87990 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 6 Dec 2010 04:40:06 +0100 Subject: [PATCH 03/30] Fix minor typo --- doc/index.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/index.txt b/doc/index.txt index ace219395..c76749e3c 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -3,7 +3,7 @@ [icon="warning.png"] WARNING: Website under construction -This documentation section contains documentation for both users and developpers. +This documentation section contains documentation for both users and developers. === User @@ -11,7 +11,7 @@ The user manual containing the full reference for using Lumiera : * link:manual.html[User Manual] _(planned)_ -=== Developper +=== Developer Informations about the structure of Lumiera, they give an overview on the main components of the application : * link:design/index.html[Design Documents] From 167220648912a36ceded625637ea9a552a2b1564 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 6 Dec 2010 04:45:08 +0100 Subject: [PATCH 04/30] Fix typo and update binary name in INSTALL --- INSTALL | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL b/INSTALL index 3ecc05196..6478bb3c3 100644 --- a/INSTALL +++ b/INSTALL @@ -67,11 +67,11 @@ make check This will take some time. After it has finished: -./lumigui +./lumiera [NewbiesTut] -Contibuting +Contributing Nothing is easier, follow the basic instructions at http://www.kernel.org/pub/ software/scm/git/docs/gittutorial.html, notably the From 29098045388b00184c12938fdd8e4a9a4e03fd0b Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 6 Dec 2010 13:40:32 +0100 Subject: [PATCH 05/30] Add preliminary implementation of a menu option Window/Close Window --- src/gui/window-manager.cpp | 22 ++++++++++++++++++++++ src/gui/window-manager.hpp | 9 +++++++++ src/gui/workspace/actions.cpp | 11 +++++++++++ src/gui/workspace/actions.hpp | 1 + src/gui/workspace/workspace-window.cpp | 8 +++++++- src/gui/workspace/workspace-window.hpp | 2 ++ 6 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/gui/window-manager.cpp b/src/gui/window-manager.cpp index 0e6319816..d2f91f3b2 100644 --- a/src/gui/window-manager.cpp +++ b/src/gui/window-manager.cpp @@ -56,6 +56,8 @@ WindowManager::new_window(gui::model::Project &source_project, windowList.push_back(window); window->show(); + + update_close_window_in_menus(); } bool @@ -107,11 +109,31 @@ WindowManager::on_window_closed(GdkEventAny* event) REQUIRE(main); main->quit(); } + + update_close_window_in_menus(); // Unless this is false, the window won't close return false; } +void +WindowManager::update_close_window_in_menus() +{ + bool enable = windowList.size() > 1; + + list< shared_ptr >::iterator iterator = + windowList.begin(); + + while (iterator != windowList.end()) + { + shared_ptr workspace_window(*iterator); + REQUIRE(workspace_window); + + workspace_window->set_close_window_sensitive(enable); + iterator++; + } +} + GdkColor WindowManager::read_style_colour_property( Gtk::Widget &widget, const gchar *property_name, diff --git a/src/gui/window-manager.hpp b/src/gui/window-manager.hpp index 341c25fcb..0b320d966 100644 --- a/src/gui/window-manager.hpp +++ b/src/gui/window-manager.hpp @@ -94,6 +94,15 @@ private: private: + /** + * On creating and closing of any window, handle enabling or disabling of the + * Window/Close Window menu option. + * + * It should be enabled when there is more than one window and disabled + * otherwise. + **/ + void update_close_window_in_menus(); + /** * Registers the custom icon sizes. **/ diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index af8d94952..99b52d210 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -123,6 +123,9 @@ Actions::populate_main_actions(RefPtr uiManager) actionGroup->add(Action::create("WindowNewWindow", StockID("new_window")), mem_fun(*this, &Actions::on_menu_window_new_window)); + actionGroup->add(Action::create("WindowCloseWindow", + _("Close Window")), + mem_fun(*this, &Actions::on_menu_window_close_window)); actionGroup->add(Action::create("WindowShowPanel", _("_Show Panel"))); // Help Menu @@ -169,6 +172,7 @@ Actions::populate_main_actions(RefPtr uiManager) " " " " " " + " " " " " " " " @@ -335,6 +339,13 @@ Actions::on_menu_window_new_window() workspaceWindow.get_controller()); } +void +Actions::on_menu_window_close_window() +{ + workspaceWindow.hide(); + // delete &workspaceWindow; +} + void Actions::on_menu_show_panel(int panel_index) { diff --git a/src/gui/workspace/actions.hpp b/src/gui/workspace/actions.hpp index c6e843832..8d0a68e6b 100644 --- a/src/gui/workspace/actions.hpp +++ b/src/gui/workspace/actions.hpp @@ -93,6 +93,7 @@ private: void on_menu_track_add(); void on_menu_window_new_window(); + void on_menu_window_close_window(); void on_menu_show_panel(int panel_index); void on_menu_help_about(); diff --git a/src/gui/workspace/workspace-window.cpp b/src/gui/workspace/workspace-window.cpp index 5a74c526f..791e49c99 100644 --- a/src/gui/workspace/workspace-window.cpp +++ b/src/gui/workspace/workspace-window.cpp @@ -117,7 +117,13 @@ WorkspaceWindow::create_ui() show_all_children(); } - + +void +WorkspaceWindow::set_close_window_sensitive(bool enable) +{ + uiManager->get_action("/MenuBar/WindowMenu/WindowCloseWindow") + ->set_sensitive(enable); +} } // namespace workspace } // namespace gui diff --git a/src/gui/workspace/workspace-window.hpp b/src/gui/workspace/workspace-window.hpp index b00b009a6..18727ab39 100644 --- a/src/gui/workspace/workspace-window.hpp +++ b/src/gui/workspace/workspace-window.hpp @@ -69,6 +69,8 @@ public: PanelManager& get_panel_manager(); + void set_close_window_sensitive(bool enable); + private: void create_ui(); From 890d5a6a9b97fcc36cee1fa758b4b52e708ef657 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 6 Dec 2010 13:44:39 +0100 Subject: [PATCH 06/30] Add notice that one might want gtk2-engines to INSTALL --- INSTALL | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/INSTALL b/INSTALL index 6478bb3c3..ee8aebf2f 100644 --- a/INSTALL +++ b/INSTALL @@ -27,6 +27,10 @@ For Ubuntu Hardy also: * libgtkmm-2.4-dev * libxv-dev +Optionally, you may also want to install: + + * gtk2-engines + also check http://gnuradio.org/trac/wiki/UbuntuInstall#InstallationOptions to see that all your installations options are met. From cc95c0df97bbc2906dbecd8c870a65cbd1d68279 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 6 Dec 2010 13:46:50 +0100 Subject: [PATCH 07/30] Fix two minor typos --- src/gui/workspace/actions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index 99b52d210..5c6bc3747 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -253,13 +253,13 @@ Actions::update_action_state() void Actions::on_menu_file_new_project() { - g_message("A File|New menu item was selecteda."); + g_message("A File|New menu item was selected."); } void Actions::on_menu_file_open_project() { - g_message("A File|Open menu item was selecteda."); + g_message("A File|Open menu item was selected."); } void From 46d4b4ac668d0ceb0576cc09aa15c465a86a72cc Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Wed, 8 Dec 2010 23:33:14 +0100 Subject: [PATCH 08/30] First version of timecode widget adapted from Ardour. --- src/gui/Makefile.am | 4 + src/gui/panels/timeline-panel.cpp | 12 +- src/gui/panels/timeline-panel.hpp | 4 +- src/gui/util/convert.cpp | 44 + src/gui/util/convert.hpp | 38 + src/gui/widgets/timecode-widget.cpp | 1353 +++++++++++++++++++++++++++ src/gui/widgets/timecode-widget.hpp | 192 ++++ 7 files changed, 1636 insertions(+), 11 deletions(-) create mode 100644 src/gui/util/convert.cpp create mode 100644 src/gui/util/convert.hpp create mode 100644 src/gui/widgets/timecode-widget.cpp create mode 100644 src/gui/widgets/timecode-widget.hpp diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 7f578eae1..55218452e 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -95,6 +95,8 @@ gtk_gui_la_SOURCES = \ $(lumigui_srcdir)/panels/timeline-panel.hpp \ $(lumigui_srcdir)/panels/viewer-panel.cpp \ $(lumigui_srcdir)/panels/viewer-panel.hpp \ + $(lumigui_srcdir)/util/convert.cpp \ + $(lumigui_srcdir)/util/convert.hpp \ $(lumigui_srcdir)/util/rectangle.cpp \ $(lumigui_srcdir)/util/rectangle.hpp \ $(lumigui_srcdir)/widgets/button-bar.cpp \ @@ -104,6 +106,8 @@ gtk_gui_la_SOURCES = \ $(lumigui_srcdir)/widgets/mini-button.hpp \ $(lumigui_srcdir)/widgets/panel-bar.cpp \ $(lumigui_srcdir)/widgets/panel-bar.hpp \ + $(lumigui_srcdir)/widgets/timecode-widget.cpp \ + $(lumigui_srcdir)/widgets/timecode-widget.hpp \ $(lumigui_srcdir)/widgets/timeline-widget.cpp \ $(lumigui_srcdir)/widgets/timeline-widget.hpp \ $(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.cpp \ diff --git a/src/gui/panels/timeline-panel.cpp b/src/gui/panels/timeline-panel.cpp index a93e49251..f85b83bc1 100644 --- a/src/gui/panels/timeline-panel.cpp +++ b/src/gui/panels/timeline-panel.cpp @@ -49,8 +49,7 @@ const int TimelinePanel::ZoomToolSteps = 2; // 2 seems comfortable TimelinePanel::TimelinePanel(workspace::PanelManager &panel_manager, GdlDockItem *dock_item) : Panel(panel_manager, dock_item, get_title(), get_stock_id()), - timeIndicator(), - timeIndicatorButton(), + timeCode("sequence_clock", "timecode_widget", true), previousButton(Stock::MEDIA_PREVIOUS), rewindButton(Stock::MEDIA_REWIND), playPauseButton(Stock::MEDIA_PLAY), @@ -82,11 +81,7 @@ TimelinePanel::TimelinePanel(workspace::PanelManager &panel_manager, panelBar.pack_start(sequenceChooser, PACK_SHRINK); // Setup the toolbar - timeIndicatorButton.add(timeIndicator); - timeIndicatorButton.set_relief(Gtk::RELIEF_NONE); - timeIndicatorButton.set_focus_on_click(false); - - toolbar.append(timeIndicatorButton); + toolbar.append(timeCode); toolbar.append(previousButton); toolbar.append(rewindButton); @@ -114,7 +109,6 @@ TimelinePanel::TimelinePanel(workspace::PanelManager &panel_manager, // Setup tooltips sequenceChooser .set_tooltip_text(_("Change sequence")); - timeIndicatorButton .set_tooltip_text(_("Go to time code")); previousButton .set_tooltip_text(_("To beginning")); rewindButton .set_tooltip_text(_("Rewind")); @@ -374,7 +368,7 @@ TimelinePanel::set_tool(timeline::ToolType tool) void TimelinePanel::show_time(gavl_time_t time) { - timeIndicator.set_text(lumiera_tmpbuf_print_time(time)); + // timeIndicator.set_text(lumiera_tmpbuf_print_time(time)); } bool diff --git a/src/gui/panels/timeline-panel.hpp b/src/gui/panels/timeline-panel.hpp index eaec9e02b..01a618b26 100644 --- a/src/gui/panels/timeline-panel.hpp +++ b/src/gui/panels/timeline-panel.hpp @@ -27,6 +27,7 @@ #define TIMELINE_PANEL_HPP #include "panel.hpp" +#include "../widgets/timecode-widget.hpp" #include "../widgets/timeline-widget.hpp" using namespace gui::widgets; @@ -168,8 +169,7 @@ private: timelineStates; // Toolbar Widgets - Gtk::Label timeIndicator; - Gtk::Button timeIndicatorButton; + TimeCode timeCode; MiniButton previousButton; MiniButton rewindButton; diff --git a/src/gui/util/convert.cpp b/src/gui/util/convert.cpp new file mode 100644 index 000000000..e9fe0e293 --- /dev/null +++ b/src/gui/util/convert.cpp @@ -0,0 +1,44 @@ +/* + convert.cpp - Defines utility functions for conversions + + Copyright (C) Lumiera.org + 2006, Paul Davis + 2010, Stefan Kangas + + 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 + +#include "convert.hpp" + +namespace gui { +namespace util { + +double +atof (const string& s) +{ + return std::atof (s.c_str()); +} + +int +atoi (const string& s) +{ + return std::atoi (s.c_str()); +} + +} // namespace util +} // namespace gui diff --git a/src/gui/util/convert.hpp b/src/gui/util/convert.hpp new file mode 100644 index 000000000..887040251 --- /dev/null +++ b/src/gui/util/convert.hpp @@ -0,0 +1,38 @@ +/* + convert.hpp - Declares utility functions for conversions + + Copyright (C) Lumiera.org + 2006, Paul Davis + 2010, Stefan Kangas + + 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 + +using std::string; + +namespace gui { +namespace util { + +double atof(const string& s); + +int atoi(const string& s); + +} // namespace util +} // namespace gui + + diff --git a/src/gui/widgets/timecode-widget.cpp b/src/gui/widgets/timecode-widget.cpp new file mode 100644 index 000000000..964f22c16 --- /dev/null +++ b/src/gui/widgets/timecode-widget.cpp @@ -0,0 +1,1353 @@ +/* + timecode-widget.cpp - Implementation of the timecode widget + + Copyright (C) Lumiera.org + 1999, Paul Davis + 2010, Stefan Kangas +#include +#include // for sprintf +#include +#include + +#include +#include + +#include "timecode-widget.hpp" +#include "../util/convert.hpp" + +#include "../../lib/lumitime.hpp" + +extern "C" { +#include "../../lib/time.h" +} + +using namespace sigc; +using namespace Gtk; +using namespace std; + +using gui::util::atof; +using gui::util::atoi; + +namespace gui { +namespace widgets { + +// TODO: frame rate should not be a constant, but instead be per sequence +const float framerate = 25; + +sigc::signal TimeCode::ModeChanged; + +const unsigned int TimeCode::field_length[(int) TimeCode::VFrames+1] = { + 2, /* SMPTE_Hours */ + 2, /* SMPTE_Minutes */ + 2, /* SMPTE_Seconds */ + 2, /* SMPTE_Frames */ + 2, /* MS_Hours */ + 2, /* MS_Minutes */ + 5, /* MS_Seconds */ + 10 /* VFrames */ +}; + +TimeCode::TimeCode(std::string clock_name, std::string widget_name, bool allow_edit) /*, bool duration,*/ + : _name(clock_name), + // is_duration(duration), + editable(allow_edit), + colon1(":"), + colon2(":"), + colon3(":"), + colon4(":"), + colon5(":") +{ + last_when = 0; + last_pdelta = 0; + last_sdelta = 0; + key_entry_state = 0; + ops_menu = 0; + dragging = false; + + audio_frames_ebox.add(audio_frames_label); + + frames_packer.set_homogeneous(false); + frames_packer.set_border_width(2); + frames_packer.pack_start(audio_frames_ebox, false, false); + + frames_packer_hbox.pack_start(frames_packer, true, false); + + hours_ebox.add(hours_label); + minutes_ebox.add(minutes_label); + seconds_ebox.add(seconds_label); + frames_ebox.add(frames_label); + ms_hours_ebox.add(ms_hours_label); + ms_minutes_ebox.add(ms_minutes_label); + ms_seconds_ebox.add(ms_seconds_label); + + smpte_packer.set_homogeneous(false); + smpte_packer.set_border_width(2); + smpte_packer.pack_start(hours_ebox, false, false); + smpte_packer.pack_start(colon1, false, false); + smpte_packer.pack_start(minutes_ebox, false, false); + smpte_packer.pack_start(colon2, false, false); + smpte_packer.pack_start(seconds_ebox, false, false); + smpte_packer.pack_start(colon3, false, false); + smpte_packer.pack_start(frames_ebox, false, false); + + smpte_packer_hbox.pack_start(smpte_packer, true, false); + + minsec_packer.set_homogeneous(false); + minsec_packer.set_border_width(2); + minsec_packer.pack_start(ms_hours_ebox, false, false); + minsec_packer.pack_start(colon4, false, false); + minsec_packer.pack_start(ms_minutes_ebox, false, false); + minsec_packer.pack_start(colon5, false, false); + minsec_packer.pack_start(ms_seconds_ebox, false, false); + + minsec_packer_hbox.pack_start(minsec_packer, true, false); + + clock_frame.set_shadow_type(Gtk::SHADOW_IN); + clock_frame.set_name("BaseFrame"); + + clock_frame.add(clock_base); + + set_widget_name(widget_name); + + // Set mode to force update + _mode = Off; + set_mode(SMPTE); + + pack_start(clock_frame, true, true); + + /* the clock base handles button releases for menu popup regardless of + editable status. if the clock is editable, the clock base is where + we pass focus to after leaving the last editable "field", which + will then shutdown editing till the user starts it up again. + + it does this because the focus out event on the field disables + keyboard event handling, and we don't connect anything up to + notice focus in on the clock base. hence, keyboard event handling + stays disabled. + */ + + clock_base.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK); + clock_base.signal_button_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_release_event), SMPTE_Hours)); + + // Session::SMPTEOffsetChanged.connect(mem_fun(*this, &TimeCode::smpte_offset_changed)); + + if (editable) { + setup_events(); + } + + set(last_when, true); +} + +void +TimeCode::set_widget_name(string name) +{ + Widget::set_name(name); + + clock_base.set_name(name); + + audio_frames_label.set_name(name); + hours_label.set_name(name); + minutes_label.set_name(name); + seconds_label.set_name(name); + frames_label.set_name(name); + ms_hours_label.set_name(name); + ms_minutes_label.set_name(name); + ms_seconds_label.set_name(name); + hours_ebox.set_name(name); + minutes_ebox.set_name(name); + seconds_ebox.set_name(name); + frames_ebox.set_name(name); + audio_frames_ebox.set_name(name); + ms_hours_ebox.set_name(name); + ms_minutes_ebox.set_name(name); + ms_seconds_ebox.set_name(name); + + colon1.set_name(name); + colon2.set_name(name); + colon3.set_name(name); + colon4.set_name(name); + colon5.set_name(name); + + queue_draw(); +} + +void +TimeCode::setup_events() +{ + clock_base.set_can_focus(true); + + const Gdk::EventMask eventMask = + Gdk::BUTTON_PRESS_MASK| + Gdk::BUTTON_RELEASE_MASK| + Gdk::KEY_PRESS_MASK| + Gdk::KEY_RELEASE_MASK| + Gdk::FOCUS_CHANGE_MASK| + Gdk::POINTER_MOTION_MASK| + Gdk::SCROLL_MASK; + + hours_ebox.add_events(eventMask); + minutes_ebox.add_events(eventMask); + seconds_ebox.add_events(eventMask); + frames_ebox.add_events(eventMask); + ms_hours_ebox.add_events(eventMask); + ms_minutes_ebox.add_events(eventMask); + ms_seconds_ebox.add_events(eventMask); + audio_frames_ebox.add_events(eventMask); + + hours_ebox.set_can_focus(true); + minutes_ebox.set_can_focus(true); + seconds_ebox.set_can_focus(true); + frames_ebox.set_can_focus(true); + audio_frames_ebox.set_can_focus(true); + ms_hours_ebox.set_can_focus(true); + ms_minutes_ebox.set_can_focus(true); + ms_seconds_ebox.set_can_focus(true); + + hours_ebox.signal_motion_notify_event().connect(bind(mem_fun( + *this, &TimeCode::field_motion_notify_event), SMPTE_Hours)); + minutes_ebox.signal_motion_notify_event().connect(bind(mem_fun( + *this, &TimeCode::field_motion_notify_event), SMPTE_Minutes)); + seconds_ebox.signal_motion_notify_event().connect(bind(mem_fun( + *this, &TimeCode::field_motion_notify_event), SMPTE_Seconds)); + frames_ebox.signal_motion_notify_event().connect(bind(mem_fun( + *this, &TimeCode::field_motion_notify_event), SMPTE_Frames)); + audio_frames_ebox.signal_motion_notify_event().connect(bind(mem_fun( + *this, &TimeCode::field_motion_notify_event), VFrames)); + ms_hours_ebox.signal_motion_notify_event().connect(bind(mem_fun( + *this, &TimeCode::field_motion_notify_event), MS_Hours)); + ms_minutes_ebox.signal_motion_notify_event().connect(bind(mem_fun( + *this, &TimeCode::field_motion_notify_event), MS_Minutes)); + ms_seconds_ebox.signal_motion_notify_event().connect(bind(mem_fun( + *this, &TimeCode::field_motion_notify_event), MS_Seconds)); + + hours_ebox.signal_button_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_press_event), SMPTE_Hours)); + minutes_ebox.signal_button_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_press_event), SMPTE_Minutes)); + seconds_ebox.signal_button_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_press_event), SMPTE_Seconds)); + frames_ebox.signal_button_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_press_event), SMPTE_Frames)); + audio_frames_ebox.signal_button_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_press_event), VFrames)); + ms_hours_ebox.signal_button_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_press_event), MS_Hours)); + ms_minutes_ebox.signal_button_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_press_event), MS_Minutes)); + ms_seconds_ebox.signal_button_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_press_event), MS_Seconds)); + + hours_ebox.signal_button_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_release_event), SMPTE_Hours)); + minutes_ebox.signal_button_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_release_event), SMPTE_Minutes)); + seconds_ebox.signal_button_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_release_event), SMPTE_Seconds)); + frames_ebox.signal_button_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_release_event), SMPTE_Frames)); + audio_frames_ebox.signal_button_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_release_event), VFrames)); + ms_hours_ebox.signal_button_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_release_event), MS_Hours)); + ms_minutes_ebox.signal_button_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_release_event), MS_Minutes)); + ms_seconds_ebox.signal_button_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_release_event), MS_Seconds)); + + hours_ebox.signal_scroll_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_scroll_event), SMPTE_Hours)); + minutes_ebox.signal_scroll_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_scroll_event), SMPTE_Minutes)); + seconds_ebox.signal_scroll_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_scroll_event), SMPTE_Seconds)); + frames_ebox.signal_scroll_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_scroll_event), SMPTE_Frames)); + audio_frames_ebox.signal_scroll_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_scroll_event), VFrames)); + ms_hours_ebox.signal_scroll_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_scroll_event), MS_Hours)); + ms_minutes_ebox.signal_scroll_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_scroll_event), MS_Minutes)); + ms_seconds_ebox.signal_scroll_event().connect(bind(mem_fun( + *this, &TimeCode::field_button_scroll_event), MS_Seconds)); + + hours_ebox.signal_key_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_press_event), SMPTE_Hours)); + minutes_ebox.signal_key_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_press_event), SMPTE_Minutes)); + seconds_ebox.signal_key_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_press_event), SMPTE_Seconds)); + frames_ebox.signal_key_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_press_event), SMPTE_Frames)); + audio_frames_ebox.signal_key_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_press_event), VFrames)); + ms_hours_ebox.signal_key_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_press_event), MS_Hours)); + ms_minutes_ebox.signal_key_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_press_event), MS_Minutes)); + ms_seconds_ebox.signal_key_press_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_press_event), MS_Seconds)); + + hours_ebox.signal_key_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_release_event), SMPTE_Hours)); + minutes_ebox.signal_key_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_release_event), SMPTE_Minutes)); + seconds_ebox.signal_key_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_release_event), SMPTE_Seconds)); + frames_ebox.signal_key_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_release_event), SMPTE_Frames)); + audio_frames_ebox.signal_key_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_release_event), VFrames)); + ms_hours_ebox.signal_key_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_release_event), MS_Hours)); + ms_minutes_ebox.signal_key_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_release_event), MS_Minutes)); + ms_seconds_ebox.signal_key_release_event().connect(bind(mem_fun( + *this, &TimeCode::field_key_release_event), MS_Seconds)); + + hours_ebox.signal_focus_in_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_in_event), SMPTE_Hours)); + minutes_ebox.signal_focus_in_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_in_event), SMPTE_Minutes)); + seconds_ebox.signal_focus_in_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_in_event), SMPTE_Seconds)); + frames_ebox.signal_focus_in_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_in_event), SMPTE_Frames)); + audio_frames_ebox.signal_focus_in_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_in_event), VFrames)); + ms_hours_ebox.signal_focus_in_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_in_event), MS_Hours)); + ms_minutes_ebox.signal_focus_in_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_in_event), MS_Minutes)); + ms_seconds_ebox.signal_focus_in_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_in_event), MS_Seconds)); + + hours_ebox.signal_focus_out_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_out_event), SMPTE_Hours)); + minutes_ebox.signal_focus_out_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_out_event), SMPTE_Minutes)); + seconds_ebox.signal_focus_out_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_out_event), SMPTE_Seconds)); + frames_ebox.signal_focus_out_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_out_event), SMPTE_Frames)); + audio_frames_ebox.signal_focus_out_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_out_event), VFrames)); + ms_hours_ebox.signal_focus_out_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_out_event), MS_Hours)); + ms_minutes_ebox.signal_focus_out_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_out_event), MS_Minutes)); + ms_seconds_ebox.signal_focus_out_event().connect(bind(mem_fun( + *this, &TimeCode::field_focus_out_event), MS_Seconds)); + + clock_base.signal_focus_in_event().connect(mem_fun( + *this, &TimeCode::drop_focus_handler)); +} + +bool +TimeCode::drop_focus_handler(GdkEventFocus* ignored) +{ + // Keyboard::magic_widget_drop_focus(); + return false; +} + +void +TimeCode::on_realize() +{ + HBox::on_realize(); + + /* styles are not available until the widgets are bound to a window */ + + set_size_requests(); +} + +void +TimeCode::set(gavl_time_t when, bool force) +{ + if (!force && when == last_when) + return; + + switch (_mode) { + case SMPTE: + set_smpte(when, force); + break; + + case MinSec: + set_minsec(when, force); + break; + + case Frames: + set_frames(when, force); + break; + + case Off: + break; + } + + last_when = when; +} + +// void +// TimeCode::smpte_offset_changed() +// { +// gavl_time_t current; + +// switch (_mode) { +// case SMPTE: +// // if(is_duration) { +// // current = current_duration(); +// // } else { +// current = current_time(); +// // } +// set(current, true); +// break; +// default: +// break; +// } +// } + +void +TimeCode::set_frames(gavl_time_t when, bool force) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "%u", (unsigned int)when); + audio_frames_label.set_text(buf); +} + +void +TimeCode::set_minsec(gavl_time_t when, bool force) +{ + char buf[32]; + + lumiera::Time t(when); + + int hrs = t.getHours(); + int mins = t.getMins(); + float secs = t.getSecs(); + + if (force || hrs != ms_last_hrs) + { + sprintf(buf, "%02d", hrs); + ms_hours_label.set_text(buf); + ms_last_hrs = hrs; + } + + if (force || mins != ms_last_mins) + { + sprintf(buf, "%02d", mins); + ms_minutes_label.set_text(buf); + ms_last_mins = mins; + } + + if (force || secs != ms_last_secs) + { + sprintf(buf, "%06.3f", secs); + ms_seconds_label.set_text(buf); + ms_last_secs = secs; + } +} + +void +TimeCode::set_smpte(gavl_time_t when, bool force) +{ + char buf[32]; + + lumiera::Time t(when); + + int smpte_negative = when < 0; + int smpte_hours = t.getHours(); + int smpte_minutes = t.getMins(); + int smpte_seconds = t.getSecs(); + int smpte_frames = 0; //t.getFrames(framerate); + + // if (is_duration) { + // session->smpte_duration(when, smpte); + // } else { + // session->smpte_time(when, smpte); + // } + + if (force || smpte_hours != last_hrs || smpte_negative != last_negative) + { + if (smpte_negative) + { + sprintf(buf, "-%02d", smpte_hours); + } + else + { + sprintf(buf, " %02d", smpte_hours); + } + hours_label.set_text(buf); + last_hrs = smpte_hours; + last_negative = smpte_negative; + } + + if (force || smpte_minutes != last_mins) + { + sprintf(buf, "%02d", smpte_minutes); + minutes_label.set_text(buf); + last_mins = smpte_minutes; + } + + if (force || smpte_seconds != last_secs) + { + sprintf(buf, "%02d", smpte_seconds); + seconds_label.set_text(buf); + last_secs = smpte_seconds; + } + + if (force || smpte_frames != last_frames) + { + sprintf(buf, "%02d", smpte_frames); + frames_label.set_text(buf); + last_frames = smpte_frames; + } +} + +void +TimeCode::focus() +{ + switch (_mode) { + case SMPTE: + hours_ebox.grab_focus(); + break; + + case MinSec: + ms_hours_ebox.grab_focus(); + break; + + case Frames: + frames_ebox.grab_focus(); + break; + + case Off: + break; + } +} + +bool +TimeCode::field_key_press_event(GdkEventKey *ev, Field field) +{ + /* all key activity is handled on key release */ + return true; +} + +bool +TimeCode::field_key_release_event(GdkEventKey *ev, Field field) +{ + Label *label = 0; + string new_text; + char new_char = 0; + bool move_on = false; + + switch (field) { + case SMPTE_Hours: + label = &hours_label; + break; + case SMPTE_Minutes: + label = &minutes_label; + break; + case SMPTE_Seconds: + label = &seconds_label; + break; + case SMPTE_Frames: + label = &frames_label; + break; + + case VFrames: + label = &audio_frames_label; + break; + + case MS_Hours: + label = &ms_hours_label; + break; + case MS_Minutes: + label = &ms_minutes_label; + break; + case MS_Seconds: + label = &ms_seconds_label; + break; + + default: + return false; + } + + switch (ev->keyval) { + case GDK_0: + case GDK_KP_0: + new_char = '0'; + break; + case GDK_1: + case GDK_KP_1: + new_char = '1'; + break; + case GDK_2: + case GDK_KP_2: + new_char = '2'; + break; + case GDK_3: + case GDK_KP_3: + new_char = '3'; + break; + case GDK_4: + case GDK_KP_4: + new_char = '4'; + break; + case GDK_5: + case GDK_KP_5: + new_char = '5'; + break; + case GDK_6: + case GDK_KP_6: + new_char = '6'; + break; + case GDK_7: + case GDK_KP_7: + new_char = '7'; + break; + case GDK_8: + case GDK_KP_8: + new_char = '8'; + break; + case GDK_9: + case GDK_KP_9: + new_char = '9'; + break; + + case GDK_period: + case GDK_KP_Decimal: + if (_mode == MinSec && field == MS_Seconds) { + new_char = '.'; + } else { + return false; + } + break; + + case GDK_Tab: + case GDK_Return: + case GDK_KP_Enter: + move_on = true; + break; + + case GDK_Escape: + key_entry_state = 0; + clock_base.grab_focus(); + ChangeAborted(); /* EMIT SIGNAL */ + return true; + + default: + return false; + } + + if (!move_on) { + + if (key_entry_state == 0) { + + /* initialize with a fresh new string */ + + if (field != VFrames) { + for (unsigned int xn = 0; xn < field_length[field] - 1; ++xn) { + new_text += '0'; + } + } else { + new_text = ""; + } + + } else { + + string existing = label->get_text(); + if (existing.length() >= field_length[field]) { + new_text = existing.substr(1, field_length[field] - 1); + } else { + new_text = existing.substr(0, field_length[field] - 1); + } + } + + new_text += new_char; + label->set_text(new_text); + key_entry_state++; + } + + if (key_entry_state == field_length[field]) { + move_on = true; + } + + if (move_on) { + + if (key_entry_state) { + + switch (field) { + case SMPTE_Hours: + case SMPTE_Minutes: + case SMPTE_Seconds: + case SMPTE_Frames: + // Check SMPTE fields for sanity (may also adjust fields) + smpte_sanitize_display(); + break; + default: + break; + } + + ValueChanged(); /* EMIT_SIGNAL */ + } + + /* move on to the next field. + */ + + switch (field) { + + /* SMPTE */ + + case SMPTE_Hours: + minutes_ebox.grab_focus(); + break; + case SMPTE_Minutes: + seconds_ebox.grab_focus(); + break; + case SMPTE_Seconds: + frames_ebox.grab_focus(); + break; + case SMPTE_Frames: + clock_base.grab_focus(); + break; + + /* frames */ + + case VFrames: + clock_base.grab_focus(); + break; + + /* Min:Sec */ + + case MS_Hours: + ms_minutes_ebox.grab_focus(); + break; + case MS_Minutes: + ms_seconds_ebox.grab_focus(); + break; + case MS_Seconds: + clock_base.grab_focus(); + break; + + default: + break; + } + + } + + //if user hit Enter, lose focus + switch (ev->keyval) { + case GDK_Return: + case GDK_KP_Enter: + clock_base.grab_focus(); + } + + return true; +} + +bool +TimeCode::field_focus_in_event(GdkEventFocus *ev, Field field) +{ + key_entry_state = 0; + + // Keyboard::magic_widget_grab_focus(); + + switch (field) { + case SMPTE_Hours: + hours_ebox.set_flags(Gtk::HAS_FOCUS); + hours_ebox.set_state(Gtk::STATE_ACTIVE); + break; + case SMPTE_Minutes: + minutes_ebox.set_flags(Gtk::HAS_FOCUS); + minutes_ebox.set_state(Gtk::STATE_ACTIVE); + break; + case SMPTE_Seconds: + seconds_ebox.set_flags(Gtk::HAS_FOCUS); + seconds_ebox.set_state(Gtk::STATE_ACTIVE); + break; + case SMPTE_Frames: + frames_ebox.set_flags(Gtk::HAS_FOCUS); + frames_ebox.set_state(Gtk::STATE_ACTIVE); + break; + + case VFrames: + audio_frames_ebox.set_flags(Gtk::HAS_FOCUS); + audio_frames_ebox.set_state(Gtk::STATE_ACTIVE); + break; + + case MS_Hours: + ms_hours_ebox.set_flags(Gtk::HAS_FOCUS); + ms_hours_ebox.set_state(Gtk::STATE_ACTIVE); + break; + case MS_Minutes: + ms_minutes_ebox.set_flags(Gtk::HAS_FOCUS); + ms_minutes_ebox.set_state(Gtk::STATE_ACTIVE); + break; + case MS_Seconds: + ms_seconds_ebox.set_flags(Gtk::HAS_FOCUS); + ms_seconds_ebox.set_state(Gtk::STATE_ACTIVE); + break; + } + + return false; +} + +bool +TimeCode::field_focus_out_event(GdkEventFocus *ev, Field field) +{ + switch (field) { + + case SMPTE_Hours: + hours_ebox.unset_flags(Gtk::HAS_FOCUS); + hours_ebox.set_state(Gtk::STATE_NORMAL); + break; + case SMPTE_Minutes: + minutes_ebox.unset_flags(Gtk::HAS_FOCUS); + minutes_ebox.set_state(Gtk::STATE_NORMAL); + break; + case SMPTE_Seconds: + seconds_ebox.unset_flags(Gtk::HAS_FOCUS); + seconds_ebox.set_state(Gtk::STATE_NORMAL); + break; + case SMPTE_Frames: + frames_ebox.unset_flags(Gtk::HAS_FOCUS); + frames_ebox.set_state(Gtk::STATE_NORMAL); + break; + + case VFrames: + audio_frames_ebox.unset_flags(Gtk::HAS_FOCUS); + audio_frames_ebox.set_state(Gtk::STATE_NORMAL); + break; + + case MS_Hours: + ms_hours_ebox.unset_flags(Gtk::HAS_FOCUS); + ms_hours_ebox.set_state(Gtk::STATE_NORMAL); + break; + case MS_Minutes: + ms_minutes_ebox.unset_flags(Gtk::HAS_FOCUS); + ms_minutes_ebox.set_state(Gtk::STATE_NORMAL); + break; + case MS_Seconds: + ms_seconds_ebox.unset_flags(Gtk::HAS_FOCUS); + ms_seconds_ebox.set_state(Gtk::STATE_NORMAL); + break; + } + + // Keyboard::magic_widget_drop_focus(); + + return false; +} + +bool +TimeCode::field_button_release_event (GdkEventButton *ev, Field field) +{ + if (dragging) + { + gdk_pointer_ungrab(GDK_CURRENT_TIME); + dragging = false; + if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 + || (ev->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) + { + // we actually dragged so return without setting editing focus, or we shift clicked + return true; + } + } + + if (!editable) + { + if (ops_menu == 0) { + build_ops_menu(); + } + ops_menu->popup(1, ev->time); + return true; + } + + switch (ev->button) + { + case 1: + switch (field) + { + case SMPTE_Hours: + hours_ebox.grab_focus(); + break; + case SMPTE_Minutes: + minutes_ebox.grab_focus(); + break; + case SMPTE_Seconds: + seconds_ebox.grab_focus(); + break; + case SMPTE_Frames: + frames_ebox.grab_focus(); + break; + + case VFrames: + audio_frames_ebox.grab_focus(); + break; + + case MS_Hours: + ms_hours_ebox.grab_focus(); + break; + case MS_Minutes: + ms_minutes_ebox.grab_focus(); + break; + case MS_Seconds: + ms_seconds_ebox.grab_focus(); + break; + } + break; + + case 3: + if (ops_menu == 0) { + build_ops_menu(); + } + ops_menu->popup(1, ev->time); + return true; + + default: + break; + } + + return true; +} + +bool +TimeCode::field_button_press_event(GdkEventButton *ev, Field field) +{ + return false; + // if (session == 0) return false; + + // gavl_time_t frames = 0; + + switch (ev->button) { + case 1: + // if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { + // set (frames, true); + // ValueChanged (); /* EMIT_SIGNAL */ + // } + + /* make absolutely sure that the pointer is grabbed */ + gdk_pointer_grab(ev->window,false , + GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK), + NULL,NULL,ev->time); + dragging = true; + drag_accum = 0; + drag_start_y = ev->y; + drag_y = ev->y; + break; + + case 2: + // if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { + // set (frames, true); + // ValueChanged (); /* EMIT_SIGNAL */ + // } + break; + + case 3: + /* used for context sensitive menu */ + return false; + break; + + default: + return false; + break; + } + + return true; +} + +bool +TimeCode::field_button_scroll_event (GdkEventScroll *ev, Field field) +{ + return false; + + // if (session == 0) { + // return false; + // } + + // gavl_time_t frames = 0; + + switch (ev->direction) { + + case GDK_SCROLL_UP: + // frames = get_frames (field); + // if (frames != 0) { + // // if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + // // frames *= 10; + // // } + // set (current_time() + frames, true); + // ValueChanged (); /* EMIT_SIGNAL */ + // } + break; + + case GDK_SCROLL_DOWN: + // frames = get_frames (field); + // if (frames != 0) { + // // if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + // // frames *= 10; + // // } + + // if ((double)current_time() - (double)frames < 0.0) { + // set (0, true); + // } else { + // set (current_time() - frames, true); + // } + + // ValueChanged (); /* EMIT_SIGNAL */ + // } + break; + + default: + return false; + break; + } + + return true; +} + +bool +TimeCode::field_motion_notify_event (GdkEventMotion *ev, Field field) +{ + if (!dragging) + { + return false; + } + + float pixel_frame_scale_factor = 0.2f; + +/* + if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + pixel_frame_scale_factor = 0.1f; + } + + if (Keyboard::modifier_state_contains (ev->state, + Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) { + + pixel_frame_scale_factor = 0.025f; + } +*/ + double y_delta = ev->y - drag_y; + + drag_accum += y_delta*pixel_frame_scale_factor; + + drag_y = ev->y; + + if (trunc(drag_accum) != 0) + { + gavl_time_t frames; + gavl_time_t pos ; + int dir; + dir = (drag_accum < 0 ? 1:-1); + pos = current_time(); + frames = get_frames(field,pos,dir); + + if (frames != 0 && frames * drag_accum < current_time()) + { + // minus because up is negative in computer-land + set ((gavl_time_t) floor (pos - drag_accum * frames), false); + } + else + { + set (0 , false); + } + + drag_accum = 0; + ValueChanged(); /* EMIT_SIGNAL */ + } + + return true; +} + +gavl_time_t +TimeCode::get_frames(Field field, gavl_time_t pos, int dir) +{ + gavl_time_t frames = 0; + // switch (field) + // { + // case SMPTE_Hours: + // frames = (gavl_time_t) floor (3600.0 * session->frame_rate()); + // break; + // case SMPTE_Minutes: + // frames = (gavl_time_t) floor (60.0 * session->frame_rate()); + // break; + // case SMPTE_Seconds: + // frames = session->frame_rate(); + // break; + // case SMPTE_Frames: + // frames = (gavl_time_t) floor (session->frame_rate() / session->smpte_frames_per_second()); + // break; + + // case VFrames: + // frames = 1; + // break; + + // case MS_Hours: + // frames = (gavl_time_t) floor (3600.0 * session->frame_rate()); + // break; + // case MS_Minutes: + // frames = (gavl_time_t) floor (60.0 * session->frame_rate()); + // break; + // case MS_Seconds: + // frames = session->frame_rate(); + // break; + // } + + return frames; +} + +gavl_time_t +TimeCode::current_time(gavl_time_t pos) const +{ + gavl_time_t ret = 0; + + switch (_mode) + { + case SMPTE: + ret = smpte_time_from_display(); + break; + + case MinSec: + ret = minsec_time_from_display(); + break; + + case Frames: + ret = audio_time_from_display(); + break; + + case Off: + break; + } + + return ret; +} + +gavl_time_t +TimeCode::current_duration(gavl_time_t pos) const +{ + gavl_time_t ret = 0; + + switch (_mode) + { + case SMPTE: + ret = smpte_time_from_display(); + break; + + case MinSec: + ret = minsec_time_from_display(); + break; + + case Frames: + ret = audio_time_from_display(); + break; + + case Off: + break; + } + + return ret; +} + +void +TimeCode::smpte_sanitize_display() +{ + // Check SMPTE fields for sanity, possibly adjusting values + if (atoi(minutes_label.get_text()) > 59) + { + minutes_label.set_text("59"); + } + + if (atoi(seconds_label.get_text()) > 59) + { + seconds_label.set_text("59"); + } + + if (atoi(frames_label.get_text()) > framerate - 1) + { + char buf[32]; + sprintf(buf, "%02d", int(framerate - 1)); + frames_label.set_text(buf); + } + + // TODO: Drop frames + + // if (session->smpte_drop_frames()) { + // if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) { + // frames_label.set_text("02"); + // } + // } +} + +gavl_time_t +TimeCode::smpte_time_from_display() const +{ + // TODO + + // SMPTE::Time smpte; + // gavl_time_t sample; + + // smpte.hours = atoi (hours_label.get_text()); + // smpte.minutes = atoi (minutes_label.get_text()); + // smpte.seconds = atoi (seconds_label.get_text()); + // smpte.frames = atoi (frames_label.get_text()); + // smpte.rate = session->smpte_frames_per_second(); + // smpte.drop= session->smpte_drop_frames(); + + // session->smpte_to_sample(smpte, sample, false /* use_offset */, false /* use_subframes */ ); + + return 0; +} + +gavl_time_t +TimeCode::minsec_time_from_display () const +{ + // TODO + + // int hrs = atoi (ms_hours_label.get_text()); + // int mins = atoi (ms_minutes_label.get_text()); + // float secs = atof (ms_seconds_label.get_text()); + + // gavl_time_t sr = session->frame_rate(); + + // return (gavl_time_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr)); + + return 0; +} + +gavl_time_t +TimeCode::audio_time_from_display () const +{ + return (gavl_time_t) atoi (audio_frames_label.get_text()); +} + +void +TimeCode::build_ops_menu () +{ + using namespace Menu_Helpers; + ops_menu = new Menu; + MenuList& ops_items = ops_menu->items(); + ops_menu->set_name ("LumieraContextMenu"); + + ops_items.push_back (MenuElem ("SMPTE", bind (mem_fun(*this, &TimeCode::set_mode), SMPTE))); + ops_items.push_back (MenuElem ("Minutes:Seconds", bind (mem_fun(*this, &TimeCode::set_mode), MinSec))); + ops_items.push_back (MenuElem ("Frames", bind (mem_fun(*this, &TimeCode::set_mode), Frames))); + ops_items.push_back (MenuElem ("Off", bind (mem_fun(*this, &TimeCode::set_mode), Off))); +} + +void +TimeCode::set_mode(Mode m) +{ + /* slightly tricky: this is called from within the ARDOUR_UI + constructor by some of its clock members. at that time + the instance pointer is unset, so we have to be careful. + the main idea is to drop keyboard focus in case we had + started editing the clock and then we switch clock mode. + */ + + clock_base.grab_focus(); + + if (_mode == m) + return; + + clock_base.remove(); + + _mode = m; + + switch (_mode) + { + case SMPTE: + clock_base.add(smpte_packer_hbox); + break; + + case MinSec: + clock_base.add(minsec_packer_hbox); + break; + + case Frames: + clock_base.add(frames_packer_hbox); + break; + + case Off: + clock_base.add(off_hbox); + break; + } + + set_size_requests(); + + set(last_when, true); + clock_base.show_all(); + key_entry_state = 0; + + ModeChanged(); /* EMIT SIGNAL */ +} + +void +TimeCode::set_size_requests() +{ + /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */ + + switch (_mode) { + case SMPTE: + set_size_request_to_display_given_text(hours_label, "-00", 5, 5); + set_size_request_to_display_given_text(minutes_label, "00", 5, 5); + set_size_request_to_display_given_text(seconds_label, "00", 5, 5); + set_size_request_to_display_given_text(frames_label, "00", 5, 5); + break; + + case MinSec: + set_size_request_to_display_given_text(ms_hours_label, "00", 5, 5); + set_size_request_to_display_given_text(ms_minutes_label, "00", 5, 5); + set_size_request_to_display_given_text(ms_seconds_label, "00.000", 5, 5); + break; + + case Frames: + set_size_request_to_display_given_text(audio_frames_label, "0000000000", 5, 5); + break; + + case Off: + set_size_request_to_display_given_text(off_hbox, "00000", 5, 5); + break; + + } +} + +void +TimeCode::set_size_request_to_display_given_text(Gtk::Widget &w, const gchar *text, + gint hpadding, gint vpadding) +{ + int width, height; + w.ensure_style(); + + get_ink_pixel_size(w.create_pango_layout(text), width, height); + w.set_size_request(width + hpadding, height + vpadding); +} + +void +TimeCode::get_ink_pixel_size (Glib::RefPtr layout, + int& width, + int& height) +{ + Pango::Rectangle ink_rect = layout->get_ink_extents (); + + width = (ink_rect.get_width() + PANGO_SCALE / 2) / PANGO_SCALE; + height = (ink_rect.get_height() + PANGO_SCALE / 2) / PANGO_SCALE; +} + +} // namespace widgets +} // namespace gui + diff --git a/src/gui/widgets/timecode-widget.hpp b/src/gui/widgets/timecode-widget.hpp new file mode 100644 index 000000000..cb63060ed --- /dev/null +++ b/src/gui/widgets/timecode-widget.hpp @@ -0,0 +1,192 @@ +/* + timecode-widget.hpp - Declaration of the timecode widget + + Copyright (C) 1999 Paul Davis + + Copyright (C) Lumiera.org + 2010, Stefan Kangas + +#include +#include +#include +#include +#include + +namespace gui { +namespace widgets { + +class TimeCode : public Gtk::HBox +{ +public: + enum Mode { + SMPTE, + MinSec, + Frames, + Off + }; + + TimeCode(std::string clock_name, std::string widget_name, bool editable /*, bool is_duration = false*/); + + Mode mode() const { return _mode; } + + void focus(); + + void set(gavl_time_t, bool force = false); + void set_mode(Mode); + + void set_widget_name(std::string); + + std::string name() const { return _name; } + + gavl_time_t current_time(gavl_time_t position = 0) const; + gavl_time_t current_duration(gavl_time_t position = 0) const; + + sigc::signal ValueChanged; + sigc::signal ChangeAborted; + + static sigc::signal ModeChanged; + // static std::vector clocks; + + static bool has_focus() { return _has_focus; } + +private: + Mode _mode; + unsigned int key_entry_state; + std::string _name; + // bool is_duration; + bool editable; + + Gtk::Menu *ops_menu; + + Gtk::HBox smpte_packer_hbox; + Gtk::HBox smpte_packer; + + Gtk::HBox minsec_packer_hbox; + Gtk::HBox minsec_packer; + + Gtk::HBox frames_packer_hbox; + Gtk::HBox frames_packer; + + enum Field { + SMPTE_Hours, + SMPTE_Minutes, + SMPTE_Seconds, + SMPTE_Frames, + MS_Hours, + MS_Minutes, + MS_Seconds, + VFrames + }; + + Gtk::EventBox audio_frames_ebox; + Gtk::Label audio_frames_label; + + Gtk::HBox off_hbox; + + Gtk::EventBox hours_ebox; + Gtk::EventBox minutes_ebox; + Gtk::EventBox seconds_ebox; + Gtk::EventBox frames_ebox; + + Gtk::EventBox ms_hours_ebox; + Gtk::EventBox ms_minutes_ebox; + Gtk::EventBox ms_seconds_ebox; + + Gtk::Label hours_label; + Gtk::Label minutes_label; + Gtk::Label seconds_label; + Gtk::Label frames_label; + Gtk::Label colon1, colon2, colon3; + + Gtk::Label ms_hours_label; + Gtk::Label ms_minutes_label; + Gtk::Label ms_seconds_label; + Gtk::Label colon4, colon5; + + Gtk::EventBox clock_base; + Gtk::Frame clock_frame; + + gavl_time_t last_when; + bool last_pdelta; + bool last_sdelta; + + int last_hrs; + int last_mins; + int last_secs; + int last_frames; + bool last_negative; + + int ms_last_hrs; + int ms_last_mins; + float ms_last_secs; + + bool dragging; + double drag_start_y; + double drag_y; + double drag_accum; + + void on_realize(); + + bool field_motion_notify_event(GdkEventMotion *ev, Field); + bool field_button_press_event(GdkEventButton *ev, Field); + bool field_button_release_event(GdkEventButton *ev, Field); + bool field_button_scroll_event(GdkEventScroll *ev, Field); + bool field_key_press_event(GdkEventKey *, Field); + bool field_key_release_event(GdkEventKey *, Field); + bool field_focus_in_event(GdkEventFocus *, Field); + bool field_focus_out_event(GdkEventFocus *, Field); + bool drop_focus_handler(GdkEventFocus*); + + void set_smpte(gavl_time_t, bool); + void set_minsec(gavl_time_t, bool); + void set_frames(gavl_time_t, bool); + + gavl_time_t get_frames(Field, gavl_time_t pos = 0, int dir=1); + + void smpte_sanitize_display(); + gavl_time_t smpte_time_from_display() const; + gavl_time_t minsec_time_from_display() const; + gavl_time_t audio_time_from_display() const; + + void build_ops_menu(); + void setup_events(); + + void smpte_offset_changed(); + void set_size_requests(); + + static const unsigned int field_length[(int)VFrames+1]; + static bool _has_focus; + + void set_size_request_to_display_given_text(Gtk::Widget &w, const gchar *text, + gint hpadding, gint vpadding); + + void get_ink_pixel_size(Glib::RefPtr layout, + int& width, int& height); + +}; + +} // namespace widgets +} // namespace gui + +#endif // TIMECODE_WIDGET_HPP From 459b1a061f12bb405ab3945b5991e977cc1b6859 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 18 Dec 2010 02:22:25 +0100 Subject: [PATCH 09/30] Autotools fixes --- src/proc/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/proc/Makefile.am b/src/proc/Makefile.am index 4d0cdc17f..56ef795df 100644 --- a/src/proc/Makefile.am +++ b/src/proc/Makefile.am @@ -108,9 +108,11 @@ liblumiprocmobjectbuilder_la_CXXFLAGS = $(AM_CXXFLAGS) $(LUMIERA_PROC_CFLAGS) -W liblumiprocmobjectbuilder_la_SOURCES = \ $(liblumiprocmobjectbuilder_la_srcdir)/assembler.cpp \ $(liblumiprocmobjectbuilder_la_srcdir)/conmanager.cpp \ + $(liblumiprocmobjectbuilder_la_srcdir)/model-port-registry.cpp \ + $(liblumiprocmobjectbuilder_la_srcdir)/operationpoint.cpp \ $(liblumiprocmobjectbuilder_la_srcdir)/nodecreatortool.cpp \ - $(liblumiprocmobjectbuilder_la_srcdir)/segmentation.cpp \ $(liblumiprocmobjectbuilder_la_srcdir)/segmentation-tool.cpp \ + $(liblumiprocmobjectbuilder_la_srcdir)/segmentation.cpp \ $(liblumiprocmobjectbuilder_la_srcdir)/toolfactory.cpp From 12949265081359e545ee51b2a9498a82c3f38846 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 20 Dec 2010 07:37:41 +0100 Subject: [PATCH 10/30] Time Quantisation: theoretical analysis and initial design draft --- doc/devel/uml/fig142725.png | Bin 0 -> 14152 bytes uml/lumiera/128517 | 394 ++++++++++++++++++++++++++++++++++-- uml/lumiera/131077 | 2 +- uml/lumiera/132485 | 2 +- uml/lumiera/142725.diagram | 142 +++++++++++++ uml/lumiera/5.session | 19 +- uml/lumiera/lumiera.prj | 2 +- wiki/renderengine.html | 90 +++++++- 8 files changed, 615 insertions(+), 36 deletions(-) create mode 100644 doc/devel/uml/fig142725.png create mode 100644 uml/lumiera/142725.diagram diff --git a/doc/devel/uml/fig142725.png b/doc/devel/uml/fig142725.png new file mode 100644 index 0000000000000000000000000000000000000000..e69ceab0e28613de3f80e6fd2e6fcd910b196690 GIT binary patch literal 14152 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 literal 0 HcmV?d00001 diff --git a/uml/lumiera/128517 b/uml/lumiera/128517 index 1adaeed67..eef0810c5 100644 --- a/uml/lumiera/128517 +++ b/uml/lumiera/128517 @@ -1,6 +1,6 @@ format 58 "CommonLib" // CommonLib - revision 20 + revision 22 modified_by 5 "hiv" // class settings //class diagram settings @@ -811,6 +811,380 @@ ${items}}; end end + classview 135685 "Time Handling" + //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_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties 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 show_stereotype_properties 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 show_stereotype_properties 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 show_stereotype_properties 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 show_stereotype_properties 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 show_stereotype_properties default + classdiagram 142725 "Time flavours" + draw_all_relations no hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + size A4 + end + + class 134917 "Time" + visibility public + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + comment "denotes a temporal position (time point) in continuous time. +This implies a time origin (point of reference), which is kept implicit and depends on the context. +" + classrelation 206085 // + relation 195205 ---|> + a public + cpp default "${type}" + classrelation_ref 206085 // + b parent class_ref 168709 // TimeValue + end + end + + class 168581 "TimeSpan" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 206341 // + relation 195461 ---|> + a public + cpp default "${type}" + classrelation_ref 206341 // + b parent class_ref 168837 // Duration + end + + classrelation 206469 // start () + relation 195589 ---> + a role_name "start" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 206469 // start () + b parent class_ref 134917 // Time + end + end + + class 168709 "TimeValue" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + end + + class 168837 "Duration" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 206213 // + relation 195333 ---|> + a public + cpp default "${type}" + classrelation_ref 206213 // + b parent class_ref 168709 // TimeValue + end + end + + class 168965 "QuTime" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 206853 // + relation 195973 ---> + stereotype "refers_to" + a role_name "" multiplicity "1" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 206853 // + b multiplicity "*" parent class_ref 169093 // Quantiser + end + + classrelation 208133 // + relation 197253 ---|> + a public + cpp default "${type}" + classrelation_ref 208133 // + b parent class_ref 134917 // Time + end + + classrelation 208901 // + relation 198021 ---> + stereotype "yield" + a role_name "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 208901 // + b parent class_ref 170629 // TCode + end + end + + class 169093 "Quantiser" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 206981 // + relation 196101 ---> + stereotype "use" + a role_name "" multiplicity "1" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 206981 // + b parent class_ref 169221 // TimeGrid + end + + classrelation 209029 // + relation 198149 o--> + stereotype "provide" + a role_name "" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 209029 // + b parent class_ref 170757 // Format + end + end + + class 169221 "TimeGrid" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + attribute 134277 "origin" + protected type class_ref 134917 // Time + multiplicity "1" + cpp_decl " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; +" + java_decl "" + php_decl "" + python_decl "" + idl_decl "" + end + + attribute 134405 "scale" + protected type class_ref 168837 // Duration + cpp_decl " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value}; +" + java_decl "" + php_decl "" + python_decl "" + idl_decl "" + end + end + + class 170373 "TimeVar" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 208261 // + relation 197381 ---|> + a public + cpp default "${type}" + classrelation_ref 208261 // + b parent class_ref 168709 // TimeValue + end + + classrelation 208389 // val () + relation 197509 ---> + a role_name "val" multiplicity "1" protected + cpp default " ${comment}${static}${mutable}${volatile}${const}${type}* ${name}${value}; +" + classrelation_ref 208389 // val () + b multiplicity "*" parent class_ref 134917 // Time + end + end + + class 170501 "QuTimeSpan" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 208517 // + relation 197637 ---|> + a public + cpp default "${type}" + classrelation_ref 208517 // + b parent class_ref 168581 // TimeSpan + end + end + + class 170629 "TCode" + visibility package + nformals 1 + formal name "F" type "class" explicit_default_value "" + explicit_extends "" + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 208645 // + relation 197765 -_-> + a default + cpp default "#include in source" + classrelation_ref 208645 // + b parent class_ref 170629 // TCode + end + + classrelation 208773 // + relation 197893 -_-> + a default + cpp default "#include in source" + classrelation_ref 208773 // + b parent class_ref 170757 // Format + end + end + + class 170757 "Format" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + end + + class 170885 "FrameNr" + visibility package + nactuals 1 + actual class class_ref 170629 // TCode + rank 0 explicit_value "" + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 209157 // + relation 198277 ---|> + a public + cpp default "${type}" + classrelation_ref 209157 // + b parent class_ref 170629 // TCode + end + end + + class 171013 "CompoundGrid" + visibility package + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + php_decl "" + python_2_2 python_decl "" + idl_decl "" + explicit_switch_type "" + + classrelation 209285 // + relation 198405 ---|> + a public + cpp default "${type}" + classrelation_ref 209285 // + b parent class_ref 169221 // TimeGrid + end + end + end + package_ref 131077 // ConfigQuery package_ref 132485 // Containers @@ -1161,24 +1535,6 @@ ${inlines} end end - class 134917 "Time" - visibility public - cpp_decl "${comment}${template}class ${name}${inherit} - { -${members} }; -${inlines} -" - java_decl "" - php_decl "" - python_2_2 python_decl "" - idl_decl "" - explicit_switch_type "" - - comment "denotes a temporal position (time point), based on timeline start. - -investigate posix.4 realtime timers, wrap these here" - end - class 135301 "Factory" visibility public nformals 1 diff --git a/uml/lumiera/131077 b/uml/lumiera/131077 index a6ef47693..3b38a2e50 100644 --- a/uml/lumiera/131077 +++ b/uml/lumiera/131077 @@ -1,6 +1,6 @@ format 58 "ConfigQuery" // CommonLib::ConfigQuery - revision 18 + revision 19 modified_by 5 "hiv" // class settings //class diagram settings diff --git a/uml/lumiera/132485 b/uml/lumiera/132485 index 099d2b342..d1bbeacbe 100644 --- a/uml/lumiera/132485 +++ b/uml/lumiera/132485 @@ -1,6 +1,6 @@ format 58 "Containers" // CommonLib::Containers - revision 1 + revision 2 modified_by 5 "hiv" // class settings //class diagram settings diff --git a/uml/lumiera/142725.diagram b/uml/lumiera/142725.diagram new file mode 100644 index 000000000..c38a9266c --- /dev/null +++ b/uml/lumiera/142725.diagram @@ -0,0 +1,142 @@ +format 58 + +classcanvas 128005 class_ref 134917 // Time + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 249 118 2000 +end +classcanvas 128133 class_ref 168581 // TimeSpan + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 38 218 2000 +end +classcanvas 128261 class_ref 168709 // TimeValue + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 36 24 2000 +end +classcanvas 128389 class_ref 168837 // Duration + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 42 118 2000 +end +classcanvas 129669 class_ref 168965 // QuTime + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 245 324 2000 +end +classcanvas 130181 class_ref 169093 // Quantiser + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 393 324 2000 +end +classcanvas 130565 class_ref 169221 // TimeGrid + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 508 324 2000 +end +classcanvas 130949 class_ref 170373 // TimeVar + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 114 118 2000 +end +classcanvas 131589 class_ref 170501 // QuTimeSpan + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 103 324 2000 +end +classcanvas 131973 class_ref 170629 // TCode + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 248 413 2000 +end +classcanvas 132101 class_ref 170757 // Format + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 393 397 2000 +end +classcanvas 132997 class_ref 170885 // FrameNr + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 238 496 2000 +end +classcanvas 133253 class_ref 171013 // CompoundGrid + draw_all_relations default hide_attributes default hide_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default member_max_width 0 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 show_stereotype_properties default + xyz 480 439 2000 +end +relationcanvas 128517 relation_ref 195205 // + geometry VHV unfixed + from ref 128005 z 1999 to point 269 88 + line 128645 z 1999 to point 66 88 + line 128773 z 1999 to ref 128261 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 128901 relation_ref 195333 // + from ref 128389 z 1999 to ref 128261 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 129285 relation_ref 195461 // + from ref 128133 z 1999 to ref 128389 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 129413 relation_ref 195589 // + from ref 128133 z 1999 to ref 128005 + role_a_pos 111 214 3000 no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 130437 relation_ref 195973 // + from ref 129669 z 1999 stereotype "<>" xyz 309 330 3000 to ref 130181 + no_role_a no_role_b + multiplicity_a_pos 376 349 3000 multiplicity_b_pos 305 349 3000 +end +relationcanvas 130693 relation_ref 196101 // + decenter_end 353 + from ref 130181 z 1999 stereotype "<>" xyz 457 333 3000 to ref 130565 + no_role_a no_role_b + multiplicity_a_pos 491 352 3000 no_multiplicity_b +end +relationcanvas 130821 relation_ref 197253 // + from ref 129669 z 1999 to ref 128005 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 131077 relation_ref 197381 // + geometry VHV + from ref 130949 z 1999 to point 138 88 + line 131205 z 1999 to point 66 88 + line 131333 z 1999 to ref 128261 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 131461 relation_ref 197509 // + from ref 130949 z 1999 to ref 128005 + role_a_pos 175 124 3000 no_role_b + multiplicity_a_pos 230 140 3000 multiplicity_b_pos 176 143 3000 +end +relationcanvas 131717 relation_ref 197637 // + from ref 131589 z 1999 to point 65 290 + line 131845 z 1999 to ref 128133 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 132485 relation_ref 197893 // + from ref 131973 z 1999 to point 290 413 + line 132869 z 1999 to ref 132101 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 132613 relation_ref 198021 // + from ref 129669 z 1999 stereotype "<>" xyz 275 378 3000 to ref 131973 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 132741 relation_ref 198149 // + decenter_end 595 + from ref 130181 z 1999 stereotype "<>" xyz 360 377 3000 to ref 132101 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 133125 relation_ref 198277 // + decenter_begin 581 + from ref 132997 z 1999 to ref 131973 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +relationcanvas 133381 relation_ref 198405 // + decenter_begin 658 + from ref 133253 z 1999 to ref 130565 + no_role_a no_role_b + no_multiplicity_a no_multiplicity_b +end +end diff --git a/uml/lumiera/5.session b/uml/lumiera/5.session index 5e7b8f6a0..a3d4a7eab 100644 --- a/uml/lumiera/5.session +++ b/uml/lumiera/5.session @@ -4,10 +4,8 @@ diagrams 631 352 100 4 0 0 objectdiagram_ref 138885 // ModelAssetRelations 730 488 100 4 0 0 - classdiagram_ref 128133 // Session structure - 835 697 100 4 300 0 - active activitydiagram_ref 129413 // build flow - 627 621 100 4 0 0 + active classdiagram_ref 142725 // Time flavours + 595 629 100 4 0 0 end show_stereotypes selected @@ -36,15 +34,10 @@ open expansionregion_ref 128133 // establish partitioning usecaseview_ref 128261 // config examples classview_ref 128133 // Engine Workings - class_ref 164485 // Request - class_ref 164613 // Provision - class_ref 166021 // ActiveProvision - class_ref 164741 // Binding - class_ref 166277 // Index - class_ref 145285 // MediaKind - - package_ref 131077 // ConfigQuery - class_ref 152965 // Handle + classdiagram_ref 142725 // Time flavours + class_ref 134917 // Time + class_ref 169221 // TimeGrid + classview_ref 128645 // Service Components classview_ref 128266 // SmartPointers end end diff --git a/uml/lumiera/lumiera.prj b/uml/lumiera/lumiera.prj index ae9d839be..d6e97d779 100644 --- a/uml/lumiera/lumiera.prj +++ b/uml/lumiera/lumiera.prj @@ -1,6 +1,6 @@ format 58 "lumiera" - revision 65 + revision 66 modified_by 5 "hiv" cpp_root_dir "../../src/" diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 5837913f4..06edfffaf 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2081,7 +2081,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]]
@@ -2110,6 +2110,10 @@ Finally, this example shows an ''automation'' data set controlling some paramete
 * shaping the GUI/~Proc-Interface, based on MObjectRef and the [[Command frontend|CommandHandling]]
 * defining PlacementScope in order to allow for [[discovering session contents|Query]]
 * working out a [[Wiring concept|Wiring]] and the foundations of OutputManagement
+* shaping the foundations of the [[player subsystem|Player]]
+* detail considerations regarding [[time and time quantisation|TimeQuant]]
+* designing how to [[build|BuildFixture]] the [[Fixture]] (...{{red{WIP}}}...)
+
 
@@ -3970,6 +3974,33 @@ We need a way of addressing existing [[pipes|Pipe]]. Besides, as the Pipes and T <<tasksum end>>
+
+
With //play process//&nbsp; we denote an ongoing effort to calculate a stream of frames for playback or rendering.
+The play process is an conceptual entity linking together several activities in the [[Backend]] and the RenderEngine. Creating a play process is the central service provided by the [[player subsystem|Player]]: it maintains a registration entry for the process to keep track of associated entities, resources allocated and calls dispatched as a consequence, and it wires and exposes a PlayController to serve as an interface and information hub.
+
+''Note'': the player is in no way engaged in any of the actual calculation and management tasks necessary to make this stream of calculations happen. The play process code contained within the player subsystem is largely comprised of organisational concerns and not especially performance critical.
+* the [[Backend]] is responsible for scheduling and dispatching the calculations
+* the RenderEngine has the ability to cary out individual frame calculations
+* the OutputSlot exposed by the [[output manager|OutputManagement]] is responsible for accepting timed frame delivery
+
+
+
Within Lumiera, &raquo;Player&laquo; denotes the [[Subsystem]] responsible for organising and tracking //ongoing playback and render processes.// &rarr; [[PlayProcess]]
+The player subsystem does not perform or even manage any render operations, nor does it handle the outputs directly.
+Yet it adresses some central concerns:
+
+;uniformity
+:all playback and render processes are on equal footing, handled in a similar way.
+;integration
+:the player cares for the necessary integration with the other subsystems
+:it consults the OutputManagement, retrieves the necessary informations from the [[Session]] and coordinates [[Backend]] calls.
+;time quantisation
+:the player translates continuous time values into discrete frame counts.
+:to perform this [[quantisation|TimeQuant]], the help of the session for building a TimeGrid for each output channel is required.
+
+!{{red{WIP 12/10}}} under construction
+The player subsystem is currently about to be designed and built up; some time ago, __Joel Holdsworth__ and __Ichthyo__ did a design study with a PlayerDummy, which is currently hooked up with the TransportControl in the Lumiera GUI.
+
+
__Joelholdsworth__ and __Ichthyo__ created this player mockup in 1/2009 to find out about the implementation details regarding integration and colaboration between the layers. There is no working render engine yet, thus we use a ~DummyImageGenerator for creating faked yuv frames to display. Within the GUI, there is a ~PlaybackController hooked up with the transport controls on the timeline pane.
 # first everything was contained within ~PlaybackController, which spawns a thread for periodically creating those dummy frames
@@ -6495,6 +6526,63 @@ Thus no server and no network connection is needed. Simply open the file in your
  * see [[Homepage|http://tiddlywiki.com]], [[Wiki-Markup|http://tiddlywiki.org/wiki/TiddlyWiki_Markup]]
 
+
+
The term &raquo;Time&laquo; spans a variety of vastly different entities. Within a NLE we get to deal with various //flavours of time values.//
+;continuous time
+:without any additional assumptions, ''points in time'' can be specified with arbitrary precision.
+:the time values are just numbers; the point of reference and the meaning is implicit.
+:within Lumiera, time is encoded as integral number of //micro ticks,// practically continuous
+;duration
+:a range of time, a ''distance'' on the time axis, measured with the same arbitrary precision as time points.
+:distances and durations can be determined by //subtracting// two time points, consequently they are //signed numbers.//
+:a duration always abstracts from the time //when// this duration or distance happens, the relation to any time scale remains implicit
+;offset
+:offsetting a time or a duration is an operation (not an entity): it means changing the denoted time point or duration.
+:the //target// of an offset operation is a time or duration, while it's //argument// is a distance (synonymous to duration).
+:Time values are //immutable,// like numbers. Only a ''time variable'' can be changed. Durations to the contrary can be mutable or  const.
+;time span
+:contrary to a mere duration, a ''time interval'' or time span is actually //anchored// at a specific point in time.
+:it can be seen as a //special kind of duration,// which explicitly states the information //when// this time span takes place.
+
+;internal time
+:While the basic continuous time values don't imply any provision regarding the time scale and origin to be used, actually, within the implementation of the application, the meaning of time values is uniform and free of contradictions. Thus effectively there is an ''implementation time scale'' -- but its scope of validity is //strictly limited to the implementation level of a single application instance.// It is never exposed and never persisted. It might not be reproducible over multiple instantiations of the application. The implementation reserves the right to recalibrate this internal scale. Later, when Lumiera gains the capability to run within a network of render nodes, these instance connections will include a negotiation about the internal time scale, which remains completely opaque to the outer world. This explains, why {{{lumiera::Time}}} instances lack the ability to show their time value beyond debugging purposes. This is to avoid confusion and to stress their opaque nature.
+;wall clock and system time
+:The core property of any external real world time is that it is //running// -- we have to synchronise to an external time source.
+:This implies the presence of a //running synchronisation process,// with the authority to adjust the time base;
+:contrast this to the internal time, which is static and unconnected -- 
+;quantised time
+:The ''act of quantisation'' transforms a continuous property into a ''discrete'' structure. Prominent examples can be found in the domain of micro physics and with digital information processing. In a broader sense, any measurement or //quantification// also encompasses a quantisation. Regarding time and time measurement, quantisation means alignment to a predefined ''time grid''. Quantisation necessarily is an //irreversible process// -- possible additional informations get discarded.
+:Note that quantisation introduces an ''time origin'' and a ''reference scale''
+;frame count
+:within the context of film and media editing, the specification of a ''frame number'' is an especially important instance of quantisation.
+:all the properties of quantisation apply indeed to this special case: it is a time measurement or specification, where the values are aligned to a grid, and there is a reference time point where the counting starts (origin) and a reference scale (frames per second). Handling of quantised time values in Lumiera is defined such as to ensure the presence of all those bits of information. Without such precautions, operating with bare frame numbers leads itself to all kinds of confusions, mismatches, quantisation errors and unnecessary limitations of functionality.
+;timecode
+:Quantisation also is the foundation of all kinds of formalised time specifications
+:actually even a frame count is some kind of (informal) timecode -- other timecodes employ a standardised format.
+://every// presentation of time values and every persistent storage and exchange of such values is based on time codes.
+:but quantisation and time code aren't identical: a given quantised time value typically can be cast into multiple timecode formats.
+
+!Patterns for handling quantised time
+When it comes to actually handling quantised time values, several patterns are conceivable for dealing with the quantisation operation and representing quantised data. As guideline for judging these patterns, the general properties of time quantisation, as detailed above, should be taken into account. Quantising a time value means both //discarding information,// while at the same time //adding information// pertaining the assumptions of the context.
+
+__casual handling__: this is rather an frequently encountered ''anti pattern''. When reading such code, most striking is the sense of general unawareness of the problem, which is then "discovered" on a per case base, which leads to numerous repetitions of the same basic undertakings, but done with individual treatment of each instance (not so much copy-n-paste). Typical code smells:
+* the rounding, modulo and subtract-base operations pertinent with scale handling are seemingly inserted as bugfix
+* local code path forks to circumvent or compensate for otherwise hard wired calculations based on specific ways to invoke a function
+* playing strikingly clever tricks or employing heuristics to "figure out" the missing scale information from accessible context after the fact
+* advertising support for some of the conceivable cases as special feature, or adding it as plugin or extension module with limited scope
+* linking parts of the necessary additional information to completely unrelated other structures, thus causing code tangling and scattering
+* result or behaviour of calculations depends on the way things are set up in a seemingly contingent way, forcing users to stick to very specific procedures and ordered steps.
+[>img[Time and Time Quantisation in Lumiera|uml/fig142725.png]]
+__static typing__: an analysis of the cases to be expected establishes common patterns and some base cases, which are then represented by distinct types with well established conversions. This can be combined with generic programming for the common parts. Close to the data input, a factory establishes these statically typed values.
+
+__tagged values__: quantised values are explicitly created out of continuous values by a quantiser entity. These quantised data values contain a copy of the original data, adjusted to be exactly aligned with respect to the underlying time grid. In addition, they carry a tag or ID to denote the respective scale, grid or timecode system. This tag can be used later on to assess compatibility or to recast values into another timecode system.
+
+__delayed quantisation__: with this approach, the information loss is delayed as long as possible. Quantised time values are rather treated as promise for quantisation, while the actual time data remains unaltered. Additionally, they carry a tag, or even a direct link to the responsible quantiser instance. Effectively, these are specialised time values, instances of a sub-concept, able to stand-in for general time values, but exposing additional accessors to get a quantised value.
+
+!!!discussion
+For Lumiera, the static typing approach is of limited value -- it excels when values belonging to different scales are actually treated differently. There are such cases, but rather on the data handling level, e.g. sound samples are always handled block wise. But regarding time values, the unifying aspect is more important, which leads to prefering a dynamic (run time typed) approach, while //erasing// the special differences most of the time. Yet the dynamic and open nature of the Lumiera high-level model favours the delayed quantisation pattern; the same values may require different quantisation depending on the larger model context an object is encountered in. This solution might be to general and heavy weight at times though. Thus, for important special cases, the accessors should return tagged values, preferably even with differing static type. Time codes can be integrated this way, but most notably the ''frame numbers'' used for addressing throughout the backend, can be implemented as such specifically typed tagged values; the tag here denotes the quantiser and thus the underlying grid -- it should be implemented as hash-ID for smooth integration with code written in plain C.
+
+
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 ({{red{WIP 1/10}}}: not clear if this is an entity or just a conceptual definition) 

From cce72e611ef6e2ae68e122ba3cc21cf39954b4d4 Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Tue, 21 Dec 2010 02:05:13 +0100
Subject: [PATCH 11/30] WIP: new namespace and compliation units for time
 quantisation

namespace lib::time
lumitime.cpp will define the basic time wrapper
quantiser.cpp the grid alitnment and formatting wrapper

header for
- timevalues / ranges
- quantised time valuse
- timecode valuse

"lumitime.hpp" will contain the interface facilities
---
 src/lib/Makefile.am             |  3 +-
 src/lib/{ => time}/lumitime.cpp |  8 ++++--
 src/lib/time/quantiser.cpp      | 39 ++++++++++++++++++++++++++
 src/lib/time/quantiser.hpp      | 49 +++++++++++++++++++++++++++++++++
 src/lib/time/timecode.hpp       | 49 +++++++++++++++++++++++++++++++++
 src/lib/time/timevalue.hpp      | 49 +++++++++++++++++++++++++++++++++
 6 files changed, 193 insertions(+), 4 deletions(-)
 rename src/lib/{ => time}/lumitime.cpp (97%)
 create mode 100644 src/lib/time/quantiser.cpp
 create mode 100644 src/lib/time/quantiser.hpp
 create mode 100644 src/lib/time/timecode.hpp
 create mode 100644 src/lib/time/timevalue.hpp

diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 9837f7da3..a00b4bdc2 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -44,7 +44,6 @@ liblumiera_la_SOURCES =					\
 	$(liblumiera_la_srcdir)/lockerror.c		\
 	$(liblumiera_la_srcdir)/logging.cpp		\
 	$(liblumiera_la_srcdir)/luid.c			\
-	$(liblumiera_la_srcdir)/lumitime.cpp		\
 	$(liblumiera_la_srcdir)/mpool.c			\
 	$(liblumiera_la_srcdir)/mrucache.c		\
 	$(liblumiera_la_srcdir)/mutex.c			\
@@ -61,6 +60,8 @@ liblumiera_la_SOURCES =					\
 	$(liblumiera_la_srcdir)/test/test-helper.cpp	\
 	$(liblumiera_la_srcdir)/test/testoption.cpp	\
 	$(liblumiera_la_srcdir)/time.c			\
+	$(liblumiera_la_srcdir)/time/lumitime.cpp	\
+	$(liblumiera_la_srcdir)/time/quantiser.cpp	\
 	$(liblumiera_la_srcdir)/tmpbuf.c		\
 	$(liblumiera_la_srcdir)/util.cpp
 
diff --git a/src/lib/lumitime.cpp b/src/lib/time/lumitime.cpp
similarity index 97%
rename from src/lib/lumitime.cpp
rename to src/lib/time/lumitime.cpp
index bae855539..6f1a7ac23 100644
--- a/src/lib/lumitime.cpp
+++ b/src/lib/time/lumitime.cpp
@@ -22,6 +22,8 @@
 
 
 #include "lib/lumitime.hpp"
+#include "lib/time/timevalue.hpp"
+
 extern "C" {
 #include "lib/time.h"
 }
@@ -39,7 +41,7 @@ namespace lumiera {
   const Time Time::MIN ( -std::numeric_limits::max() );
   
   
-      
+  
   Time::Time ( long millis
              , uint secs 
              , uint mins
@@ -47,7 +49,7 @@ namespace lumiera {
              )
     : t_(lumiera_build_time (millis,secs,mins,hours))
   { }
-
+  
   int
   Time::getMillis() const
   {
@@ -81,7 +83,7 @@ namespace lumiera {
     // TODO
     return 0;
   }
-
+  
   
   Time::operator string()  const
   {
diff --git a/src/lib/time/quantiser.cpp b/src/lib/time/quantiser.cpp
new file mode 100644
index 000000000..48b24979c
--- /dev/null
+++ b/src/lib/time/quantiser.cpp
@@ -0,0 +1,39 @@
+/*
+  Quantiser  -  aligning time values to a time grid
+
+  Copyright (C)         Lumiera.org
+    2010,               Hermann Vosseler 
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of
+  the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+* *****************************************************/
+
+
+#include "lib/lumitime.hpp"
+#include "lib/time/timevalue.hpp"
+
+using std::string;
+
+
+namespace lib {
+namespace time {
+  
+  
+  /** */
+  
+  
+  
+}} // lib::time
+  
diff --git a/src/lib/time/quantiser.hpp b/src/lib/time/quantiser.hpp
new file mode 100644
index 000000000..b511ed53f
--- /dev/null
+++ b/src/lib/time/quantiser.hpp
@@ -0,0 +1,49 @@
+/*
+  QUANTISER.hpp  -  aligning time values to a time grid
+
+  Copyright (C)         Lumiera.org
+    2010,               Hermann Vosseler 
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of
+  the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+
+#ifndef LIB_TIME_QUANTISER_H
+#define LIB_TIME_QUANTISER_H
+
+//#include 
+#include 
+
+
+namespace lib {
+namespace time {
+  
+  
+  /**
+   * Facility to create grid-aligned time values.
+   * 
+   * @todo WIP-WIP-WIP
+   */
+  class Quantiser
+    {
+      
+    public:
+    };
+  
+  
+  
+}} // lib::time
+#endif
diff --git a/src/lib/time/timecode.hpp b/src/lib/time/timecode.hpp
new file mode 100644
index 000000000..2a8ef6750
--- /dev/null
+++ b/src/lib/time/timecode.hpp
@@ -0,0 +1,49 @@
+/*
+  TIMECODE.hpp  -  grid aligned and fixed format time specifications
+
+  Copyright (C)         Lumiera.org
+    2010,               Hermann Vosseler 
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of
+  the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+
+#ifndef LIB_TIME_TIMECODE_H
+#define LIB_TIME_TIMECODE_H
+
+//#include 
+#include 
+
+
+namespace lib {
+namespace time {
+  
+  
+  /**
+   * fixed format time specification.
+   * 
+   * @todo WIP-WIP-WIP
+   */
+  class TCode
+    {
+      
+    public:
+    };
+  
+  
+  
+}} // lib::time
+#endif
diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp
new file mode 100644
index 000000000..d81c7f283
--- /dev/null
+++ b/src/lib/time/timevalue.hpp
@@ -0,0 +1,49 @@
+/*
+  TIMEVALUE.hpp  -  basic definitions for time values and time intervals
+
+  Copyright (C)         Lumiera.org
+    2010,               Hermann Vosseler 
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of
+  the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+
+#ifndef LIB_TIME_TIMEVALUE_H
+#define LIB_TIME_TIMEVALUE_H
+
+//#include 
+#include 
+
+
+namespace lib {
+namespace time {
+  
+  
+  /**
+   * fixed format time specification.
+   * 
+   * @todo WIP-WIP-WIP
+   */
+  class TimeValue
+    {
+      
+    public:
+    };
+  
+  
+  
+}} // lib::time
+#endif

From a6fd1ec6fd640aa926aa90abf44e492fb9a0b178 Mon Sep 17 00:00:00 2001
From: Stefan Kangas 
Date: Tue, 21 Dec 2010 09:52:27 +0100
Subject: [PATCH 12/30] Give names to the default ClipTracks in the GUI test
 code.

---
 src/gui/model/sequence.cpp | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/gui/model/sequence.cpp b/src/gui/model/sequence.cpp
index 6cb0269a9..318ee4a4f 100644
--- a/src/gui/model/sequence.cpp
+++ b/src/gui/model/sequence.cpp
@@ -46,17 +46,21 @@ Sequence::Sequence()
   {
     group_track->get_child_track_list().push_back(
       clip_track = shared_ptr(new ClipTrack()));
+    clip_track->set_name("Clip Track 1");
     group_track->get_child_track_list().push_back(
       group_track2 = shared_ptr(new GroupTrack()));
     group_track2->set_name("Group Track 2");
     group_track2->get_child_track_list().push_back(
-      shared_ptr(new ClipTrack()));
+      clip_track = shared_ptr(new ClipTrack()));
+    clip_track->set_name("Clip Track 2");
     first = false;
   }
   
-  tracks.push_back(shared_ptr(new GroupTrack()));
+  tracks.push_back(group_track = shared_ptr(new GroupTrack()));
+  group_track->set_name("Group Track 3");
   
-  tracks.push_back(shared_ptr(new ClipTrack()));
+  tracks.push_back(clip_track = shared_ptr(new ClipTrack()));
+  clip_track->set_name("Clip Track 3");
   
   // END TEST CODE
   

From 000486e12685d89c04b9f70badee3410b9fc1506 Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Wed, 22 Dec 2010 04:09:27 +0100
Subject: [PATCH 13/30] WIP create empty unit tests for time
 quantisation/handling

---
 src/lib/lumitime.hpp                          | 26 ++----
 tests/40components.tests                      | 17 +++-
 tests/lib/Makefile.am                         |  5 +-
 ...ime-wrapper-test.cpp => lumitime-test.cpp} |  6 +-
 tests/lib/time/time-formats-test.cpp          | 90 +++++++++++++++++++
 tests/lib/time/time-quantisation-test.cpp     | 90 +++++++++++++++++++
 tests/lib/time/time-value-test.cpp            | 90 +++++++++++++++++++
 7 files changed, 300 insertions(+), 24 deletions(-)
 rename tests/lib/{time-wrapper-test.cpp => lumitime-test.cpp} (96%)
 create mode 100644 tests/lib/time/time-formats-test.cpp
 create mode 100644 tests/lib/time/time-quantisation-test.cpp
 create mode 100644 tests/lib/time/time-value-test.cpp

diff --git a/src/lib/lumitime.hpp b/src/lib/lumitime.hpp
index 5fe942218..88c6a1764 100644
--- a/src/lib/lumitime.hpp
+++ b/src/lib/lumitime.hpp
@@ -36,27 +36,15 @@ namespace lumiera {
 
 
   /**
-   * C++ convenience wrapper representing a time value, which could denote
-   * a temporal position (time point) relative to an (implicit) timeline zero
-   * point, or it could represent a time interval.
+   * Lumiera's internal time data.
+   * Time denotes a time point, specified as opaque value on an 
+   * quasi continuous ("sufficiently precise") internal time scale, relative
+   * to an (implicit) timeline zero point. The actual implementation relies
+   * on gavl_time_t (long) values.
    * 
-   * This wrapper is deliberately kept rather limited as not to be completely
-   * interchangeable with and integral type. The rationale is that time values
-   * should be kept separate and tagged as time values. The following is supported:
-   * - conversions from / to gavl_time_t (which is effectively a int64_t)
-   * - additions and subtractions of time values
-   * - multiplication with an integral factor
-   * - comparisons between time values and gavl_time_t values
+   * @see lib::time::TimeVar for an number-like time value usable for calculations
    * 
-   * @todo consider the possible extensions
-   *       - parsing and pretty printing
-   *       - quantising of floating point values
-   *       - conversion to boost::rational
-   *       - define a Framerate type
-   * 
-   * @note this is currently (10/08) an experimental implementation to ease
-   *       the time handling within C++ code. It is advisable not to use it
-   *       on external interfaces (use gavl_time_t there please).
+   * @todo it is not clear to which degree Time is mutable...
    */
   class Time 
     : boost::additive
@@ -47,7 +47,7 @@ namespace test   {
   /********************************************
    * @test sanity of the C++ time wrapper.
    */
-  class TimeWrapper_test : public Test
+  class LumiTime_test : public Test
     {
       virtual void
       run (Arg arg) 
@@ -166,7 +166,7 @@ namespace test   {
   
   
   /** Register this test class... */
-  LAUNCHER (TimeWrapper_test, "unit common");
+  LAUNCHER (LumiTime_test, "unit common");
   
   
   
diff --git a/tests/lib/time/time-formats-test.cpp b/tests/lib/time/time-formats-test.cpp
new file mode 100644
index 000000000..5a60473ae
--- /dev/null
+++ b/tests/lib/time/time-formats-test.cpp
@@ -0,0 +1,90 @@
+/*
+  TimeFormats(Test)  -  timecode handling and formatting
+
+  Copyright (C)         Lumiera.org
+    2010,               Hermann Vosseler 
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of
+  the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+* *****************************************************/
+
+
+#include "lib/test/run.hpp"
+#include "lib/time/timecode.hpp"
+#include "lib/util.hpp"
+
+//#include 
+//#include 
+//#include 
+
+//using boost::lexical_cast;
+//using util::isnil;
+//using std::rand;
+//using std::cout;
+//using std::endl;
+
+
+namespace lib {
+namespace time{
+namespace test{
+  
+  
+  /********************************************************
+   * @test verify handling of grid aligned timecode values.
+   *       - creating timecode values
+   *       - some conversions
+   *       - formatting
+   */
+  class TimeFormats_test : public Test
+    {
+      virtual void
+      run (Arg arg) 
+        {
+          long refval= isnil(arg)?  1 : lexical_cast (arg[1]);
+          
+          Time ref (refval);
+          
+          checkBasics (ref);
+          checkComparisons (ref);
+          checkComponentAccess();
+        } 
+      
+      
+      void
+      checkBasics (Time const& ref)
+        {
+        }
+      
+      
+      void
+      checkComparisons (Time const& ref)
+        {
+        }
+      
+      
+      void
+      checkComponentAccess()
+        {
+        }
+      
+    };
+  
+  
+  /** Register this test class... */
+  LAUNCHER (TimeFormats_test, "unit common");
+  
+  
+  
+}}} // namespace lib::time::test
diff --git a/tests/lib/time/time-quantisation-test.cpp b/tests/lib/time/time-quantisation-test.cpp
new file mode 100644
index 000000000..5e6660e2d
--- /dev/null
+++ b/tests/lib/time/time-quantisation-test.cpp
@@ -0,0 +1,90 @@
+/*
+  TimeQuantisation(Test)  -  handling of virtually grid aligned time values
+
+  Copyright (C)         Lumiera.org
+    2010,               Hermann Vosseler 
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of
+  the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+* *****************************************************/
+
+
+#include "lib/test/run.hpp"
+#include "lib/time/quantiser.hpp"
+#include "lib/util.hpp"
+
+//#include 
+//#include 
+//#include 
+
+//using boost::lexical_cast;
+//using util::isnil;
+//using std::rand;
+//using std::cout;
+//using std::endl;
+
+
+namespace lib {
+namespace time{
+namespace test{
+  
+  
+  /********************************************************
+   * @test verify handling of time values, time intervals.
+   *       - creating times and time intervals
+   *       - comparisons
+   *       - time arithmetics
+   */
+  class TimeQuantisation_test : public Test
+    {
+      virtual void
+      run (Arg arg) 
+        {
+          long refval= isnil(arg)?  1 : lexical_cast (arg[1]);
+          
+          Time ref (refval);
+          
+          checkBasics (ref);
+          checkComparisons (ref);
+          checkComponentAccess();
+        } 
+      
+      
+      void
+      checkBasics (Time const& ref)
+        {
+        }
+      
+      
+      void
+      checkComparisons (Time const& ref)
+        {
+        }
+      
+      
+      void
+      checkComponentAccess()
+        {
+        }
+      
+    };
+  
+  
+  /** Register this test class... */
+  LAUNCHER (TimeQuantisation_test, "unit common");
+  
+  
+  
+}}} // namespace lib::time::test
diff --git a/tests/lib/time/time-value-test.cpp b/tests/lib/time/time-value-test.cpp
new file mode 100644
index 000000000..b40ca5189
--- /dev/null
+++ b/tests/lib/time/time-value-test.cpp
@@ -0,0 +1,90 @@
+/*
+  TimeValue(Test)  -  working with time values and time intervals in C++...
+
+  Copyright (C)         Lumiera.org
+    2010,               Hermann Vosseler 
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of
+  the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+* *****************************************************/
+
+
+#include "lib/test/run.hpp"
+#include "lib/time/timevalue.hpp"
+#include "lib/util.hpp"
+
+//#include 
+//#include 
+//#include 
+
+//using boost::lexical_cast;
+//using util::isnil;
+//using std::rand;
+//using std::cout;
+//using std::endl;
+
+
+namespace lib {
+namespace time{
+namespace test{
+  
+  
+  /********************************************************
+   * @test verify handling of time values, time intervals.
+   *       - creating times and time intervals
+   *       - comparisons
+   *       - time arithmetics
+   */
+  class TimeValue_test : public Test
+    {
+      virtual void
+      run (Arg arg) 
+        {
+          long refval= isnil(arg)?  1 : lexical_cast (arg[1]);
+          
+          Time ref (refval);
+          
+          checkBasics (ref);
+          checkComparisons (ref);
+          checkComponentAccess();
+        } 
+      
+      
+      void
+      checkBasics (Time const& ref)
+        {
+        }
+      
+      
+      void
+      checkComparisons (Time const& ref)
+        {
+        }
+      
+      
+      void
+      checkComponentAccess()
+        {
+        }
+      
+    };
+  
+  
+  /** Register this test class... */
+  LAUNCHER (TimeValue_test, "unit common");
+  
+  
+  
+}}} // namespace lib::time::test

From f18226e8ac3f6aa3272187ae8cb7242b61159ed7 Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Wed, 22 Dec 2010 04:49:57 +0100
Subject: [PATCH 14/30] WIP start drafting simple time values, offsets and
 intervals

questions: what is mutable / immutable?
what is the distinction between TimeValue and Time ?
what conversions make sense?
what mutations / operators to support?
---
 src/lib/time/timevalue.hpp | 113 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 112 insertions(+), 1 deletion(-)

diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp
index d81c7f283..6f4eb0427 100644
--- a/src/lib/time/timevalue.hpp
+++ b/src/lib/time/timevalue.hpp
@@ -24,9 +24,14 @@
 #ifndef LIB_TIME_TIMEVALUE_H
 #define LIB_TIME_TIMEVALUE_H
 
-//#include 
+#include 
 #include 
 
+extern "C" {
+#include 
+#include 
+}
+
 
 namespace lib {
 namespace time {
@@ -38,12 +43,118 @@ namespace time {
    * @todo WIP-WIP-WIP
    */
   class TimeValue
+    : boost::totally_ordered >
     {
+      gavl_time_t t_;
       
     public:
+      static const Time MAX ; 
+      static const Time MIN ;
+      
+      explicit 
+      TimeValue (gavl_time_t val=0)
+        : t_(val)
+        { }
+      
+      // using standard copy operations
+      
+      operator gavl_time_t ()  const { return t_; }
+      
+      // Supporting totally_ordered
+      friend bool operator<  (Time const& t1, Time const& t2)  { return t1.t_ <  t2.t_; }
+      friend bool operator<  (Time const& t1, gavl_time_t t2)  { return t1.t_ <  t2   ; }
+      friend bool operator>  (Time const& t1, gavl_time_t t2)  { return t1.t_ >  t2   ; }
+      friend bool operator== (Time const& t1, Time const& t2)  { return t1.t_ == t2.t_; }
+      friend bool operator== (Time const& t1, gavl_time_t t2)  { return t1.t_ == t2   ; }
     };
   
   
+  class TimeVar
+    : public TimeValue
+    , boost::additive
+    {
+        
+    public:
+      TimeVar (TimeValue time)
+        : TimeValue(time)
+        { }
+      
+      
+      // Supporting additive
+      TimeVar& operator+= (TimeVar const& tx)  { t_ += tx.t_; return *this; }
+      TimeVar& operator-= (TimeVar const& tx)  { t_ -= tx.t_; return *this; }
+      
+      // Supporting multiplication with integral factor
+      TimeVar& operator*= (int64_t fact)       { t_ *= fact;  return *this; }
+       
+      // baseclass TimeValue is already totally_ordered 
+    };
+  
+  
+  class Offset;  
+    
+  /**
+   * Lumiera's internal time value datatype
+   */
+  class Time
+    : public TimeValue
+    {
+    public:
+      explicit 
+      Time (TimeValue val=0)
+        : TimeValue(val)
+        { }
+      
+      Time ( long millis
+           , uint secs 
+           , uint mins =0
+           , uint hours=0
+           );
+    };
+  
+  
+  class Offset
+    : public TimeValue
+    {
+        
+    public:
+      explicit 
+      Offset (TimeValue distance)
+        : TimeValue(distance)
+        { }
+    };
+      
+  inline Offset
+  operator- (Time const& end, Time const& start)
+  {
+    TimeVar distance(end);
+    distance -= start;
+    return Offset(distance);
+  }
+    
+  typedef const Offset TimeDistance;
+  
+  
+  class Duration
+    : public TimeValue
+    {
+      // always positive
+    };
+  
+  
+  class TimeSpan
+    : public Time
+    {
+      Duration dur_;
+      
+    public:
+      TimeSpan(Time start, Duration length)
+        : Time(start)
+        , dur_(length)
+        { }
+    };
+  
   
 }} // lib::time
 #endif

From 966d2227e5622afb4e7e9ad4b026ab4a9d6882ac Mon Sep 17 00:00:00 2001
From: Ichthyostega 
Date: Thu, 23 Dec 2010 22:20:56 +0100
Subject: [PATCH 15/30] analysis of time usage, including quantisation pitfalls

---
 wiki/renderengine.html | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/wiki/renderengine.html b/wiki/renderengine.html
index 06edfffaf..2d12e8229 100644
--- a/wiki/renderengine.html
+++ b/wiki/renderengine.html
@@ -6526,7 +6526,7 @@ Thus no server and no network connection is needed. Simply open the file in your
  * see [[Homepage|http://tiddlywiki.com]], [[Wiki-Markup|http://tiddlywiki.org/wiki/TiddlyWiki_Markup]]
 
-
+
The term &raquo;Time&laquo; spans a variety of vastly different entities. Within a NLE we get to deal with various //flavours of time values.//
 ;continuous time
 :without any additional assumptions, ''points in time'' can be specified with arbitrary precision.
@@ -6581,6 +6581,36 @@ __delayed quantisation__: with this approach, the information loss is delayed as
 
 !!!discussion
 For Lumiera, the static typing approach is of limited value -- it excels when values belonging to different scales are actually treated differently. There are such cases, but rather on the data handling level, e.g. sound samples are always handled block wise. But regarding time values, the unifying aspect is more important, which leads to prefering a dynamic (run time typed) approach, while //erasing// the special differences most of the time. Yet the dynamic and open nature of the Lumiera high-level model favours the delayed quantisation pattern; the same values may require different quantisation depending on the larger model context an object is encountered in. This solution might be to general and heavy weight at times though. Thus, for important special cases, the accessors should return tagged values, preferably even with differing static type. Time codes can be integrated this way, but most notably the ''frame numbers'' used for addressing throughout the backend, can be implemented as such specifically typed tagged values; the tag here denotes the quantiser and thus the underlying grid -- it should be implemented as hash-ID for smooth integration with code written in plain C.
+&rarr; more on [[usage situations|TimeUsage]]
+
+
+
+
the following collection of usage situations helps to shape the details of the time values and time quantisation design. &rarr; see also  [[time quantisation|TimeQuant]]
+
+;time position of an object
+:indeed the term "time position" encompasses two quite different questtions
+:* a time or timing specification within the object
+:* determining the time point in reference to an existing scale
+;time and length of an object
+:basically the same situation, but length could be treated in two ways for quantisation
+:* having a precise specification and then quantise the start and endpoint
+:* quantise the start position and then establish an (independently quantised length)
+;moving and resizing an object
+:this can in itself be done in two different ways, and each of them can be applied in a quantised flavour
+:which sums up to 8 possible combinations, considereing that position and length are 2 degrees of freedom.
+:* a variable can be /changed/ by an offset
+:* a variable can be /defined/ to a new value
+:another (hidden) degree of freedom lies in how to apply an quantised offset to an unquantised value (and reversed)
+:because this operation might be done both in the quantised or non-quantised domain, and also the result might be (un)quantised
+;updating the playback position
+:this can be seen as a practical application of the above; basically we can choose to show the wall clock time or we can advance the playback position in frame increments, thus denoting the frame currently in display. These distinctions may look mood for video, but are relevant for precise audio editing, especially when combined with loop playback (recall that audio is processed block wise, but the individual sample frames and thus the possible loop positions are way finer than the processing block size)
+;displaying time intervals
+:for display, time intervals get //re-quantised// into display array coordinates.
+:While evidently the display coordinates are themselves quantised and we obviously don't want to cancel out the effect of an quantisation of the values or intervals to be displayed (which means, we get two quantisations chained up after each other), there remains the question if the display array coordinates should be aligned to the grid of the //elements to be displayed,// and especially if the allowd zoom factors should be limited. This decision isn't an easy one, as it has an immediate and tangible effect on what can be showed, how reversible and reproducible a view is and (note) on the actual values which can be set and changed through the GUI.
+;time value arithmetic
+:Client code as well as the internal implementation of time handling needs to do arrithmetic operations with time values. Time values are additive and totally ordered. Distance, as calculated by subtraction, can be made into a metric. Another and quite different question is to what extent a quantised variant of this arrithmetics is required.
+;relative placement
+:because of the divergence between quantised and unquantised values, the quesion arises, if placement relative to another object referes to the raw position or the already quantised position. Baiscally all the variations discussed for //time and length of an object// also do apply here.
 
From 9e60a631eb969ae75f8eb83856d8039286e110d5 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 24 Dec 2010 19:21:10 +0100 Subject: [PATCH 16/30] solve or decide the problems turned up by the usage analysis. --- wiki/renderengine.html | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 2d12e8229..0434f3a91 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -6584,11 +6584,11 @@ For Lumiera, the static typing approach is of limited value -- it excels when va &rarr; more on [[usage situations|TimeUsage]]
-
+
the following collection of usage situations helps to shape the details of the time values and time quantisation design. &rarr; see also  [[time quantisation|TimeQuant]]
 
 ;time position of an object
-:indeed the term "time position" encompasses two quite different questtions
+:indeed the term "time position" encompasses two quite different questions
 :* a time or timing specification within the object
 :* determining the time point in reference to an existing scale
 ;time and length of an object
@@ -6597,7 +6597,7 @@ For Lumiera, the static typing approach is of limited value -- it excels when va
 :* quantise the start position and then establish an (independently quantised length)
 ;moving and resizing an object
 :this can in itself be done in two different ways, and each of them can be applied in a quantised flavour
-:which sums up to 8 possible combinations, considereing that position and length are 2 degrees of freedom.
+:which sums up to 8 possible combinations, considering that position and length are 2 degrees of freedom.
 :* a variable can be /changed/ by an offset
 :* a variable can be /defined/ to a new value
 :another (hidden) degree of freedom lies in how to apply an quantised offset to an unquantised value (and reversed)
@@ -6606,11 +6606,24 @@ For Lumiera, the static typing approach is of limited value -- it excels when va
 :this can be seen as a practical application of the above; basically we can choose to show the wall clock time or we can advance the playback position in frame increments, thus denoting the frame currently in display. These distinctions may look mood for video, but are relevant for precise audio editing, especially when combined with loop playback (recall that audio is processed block wise, but the individual sample frames and thus the possible loop positions are way finer than the processing block size)
 ;displaying time intervals
 :for display, time intervals get //re-quantised// into display array coordinates.
-:While evidently the display coordinates are themselves quantised and we obviously don't want to cancel out the effect of an quantisation of the values or intervals to be displayed (which means, we get two quantisations chained up after each other), there remains the question if the display array coordinates should be aligned to the grid of the //elements to be displayed,// and especially if the allowd zoom factors should be limited. This decision isn't an easy one, as it has an immediate and tangible effect on what can be showed, how reversible and reproducible a view is and (note) on the actual values which can be set and changed through the GUI.
+:While evidently the display coordinates are themselves quantised and we obviously don't want to cancel out the effect of an quantisation of the values or intervals to be displayed (which means, we get two quantisations chained up after each other), there remains the question if the display array coordinates should be aligned to the grid of the //elements to be displayed,// and especially if the allowed zoom factors should be limited. This decision isn't an easy one, as it has an immediate and tangible effect on what can be showed, how reversible and reproducible a view is and (note) on the actual values which can be set and changed through the GUI.
 ;time value arithmetic
-:Client code as well as the internal implementation of time handling needs to do arrithmetic operations with time values. Time values are additive and totally ordered. Distance, as calculated by subtraction, can be made into a metric. Another and quite different question is to what extent a quantised variant of this arrithmetics is required.
+:Client code as well as the internal implementation of time handling needs to do arithmetic operations with time values. Time values are additive and totally ordered. Distance, as calculated by subtraction, can be made into a metric. Another and quite different question is to what extent a quantised variant of this arithmetics is required.
 ;relative placement
-:because of the divergence between quantised and unquantised values, the quesion arises, if placement relative to another object referes to the raw position or the already quantised position. Baiscally all the variations discussed for //time and length of an object// also do apply here.
+:because of the divergence between quantised and unquantised values, the question arises, if placement relative to another object refers to the raw position or the already quantised position. Basically all the variations discussed for //time and length of an object// also do apply here.
+
+!notable problems
+''Direct quantisation of length is not possible''. This is due to the non-linear nature of all but the most trivial time grids: Already such a simple addition like a start offset destroys linearity, and this still the more is true within a compound grid where the grid spacing changes at some point. Thus, the length has to be re-established at the target position of an time interval after each change involving quantisation. Regarding the //strategy// to apply when re-establishing the length, it seems more appropriate to treat the object as an entity which is moved, which means to do quantisation in two steps, first the position, then the endpoint (the second option in the description above). But it seems advisable not to hard wire that strategy -- better put it into the quantiser.
+
+''When to materialise a quantisation''. Because of the basic intention to retain information, we delay actually applying the quantisation to the stored values as much as possible. This has the downside of possibly accumulating off-grid values without that being evident. On the other hand, allowing for quantised changes inevitably pulls in all the complexity of mixing quantised and non-quantised values. It seems more appropriate to move these distinctions out of the cope of this design and offload them onto the client (code using these time classes): thus we'd //only accept raw time values for redefining a quantised interval.// But the client code is still free to use a separate quantisation, which might even utilise a different grid. For example, when moving a clip taken from 50fps media, the new position might be quantised to the 50fps grid established by the media, while the target timeline runs with 25fps, allowing for finer adjustments based on the intermediate frames present in the source material.
+
+Taking this approach also nicely removes the problem with the ''impossibility to quantise offsets''. This problem is an immediate consequence of the nonlinearity of most grids (as stated above). By just accepting raw time values for change, and indeed preferring just to re-set to new values, we don't solve that problem, but move it out of scope.
+
+Another closely related problem is ''when to allow mutations'', if at all. We can't completely do away with mutations, simply because we don't have a pure functional language at our disposal. The whole concept of //reference semantics// doesn't play so well with immutable objects. The Lumiera high-level (session) model certainly relies on objects intended to be //manipulated.// Thus we need a re-settable length field in {{{MObject}}} and we need a time variable for position calculations. Yet we could make any //derived objects// into immutable descriptor records, which certainly helps with parallelism.
+
+The ''problem with playback position'' is -- that it's an attempt to conceptualise a non-existing entity. There is no such thing like "the" playback position. Yet most applications I'm aware off employ this concept. Likely they got trapped by the metaphor of the tape head, again. We should do away with that. On playback, we should show a //projection of wall-clock time onto the expected playback range// -- not more, not less. It should be acknowledged that there is //no direct link to the ongoing playback processes,// besides the fact that they're assumed to sync to wall-clock time as well. Recall, typically there are multiple playback processes going on in compound, and each might run on a different update rate. If we really want a //visual out-of-sync indicator,// we should treat that as a separate reporting facility and display it apart of the playback cursor.
+
+Note that the ''display window might be treated as just an independent instance of quantisation''. This is similar to the approach taken above for modifying quantised time span values. We should provide a special kind of time grid, the display coordinates. The origin of these is always defined to the left (lower) side of the interval to be displayed, and they are gauged in screen units (pixels or similar, as used by the GUI toolkit set). The rest is handled by the general quantisation mechanisms. The problem of aligning the display should be transformed into a general facility to align grids, and solved for the general case. Doing so solves the remaining problems with quantised value changes and with ''specifying relative placements'' as well: If we choose to represent them as quantised values, we might (or might not) also choose to apply this //grid-alignment function.//
 
From 74fce587bd1774aa5571cb1dfa0f0c5086e83835 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 24 Dec 2010 02:21:31 +0100 Subject: [PATCH 17/30] Fix several incorrect comments (refering to the wrong file). --- src/gui/model/clip-track.hpp | 2 +- src/gui/model/clip.cpp | 4 ++-- src/gui/model/clip.hpp | 9 ++++++--- src/gui/widgets/timeline/timeline-body.cpp | 5 +++++ src/gui/widgets/timeline/timeline-clip.cpp | 4 ++-- src/gui/widgets/timeline/timeline-view-window.cpp | 4 ++-- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/gui/model/clip-track.hpp b/src/gui/model/clip-track.hpp index 5e8ea354c..1fa86f7f1 100644 --- a/src/gui/model/clip-track.hpp +++ b/src/gui/model/clip-track.hpp @@ -20,7 +20,7 @@ */ /** - * @file widgets/timeline/clip-track.hpp + * @file model/clip-track.hpp * This file contains the definition of timeline track objects which * contain clips. */ diff --git a/src/gui/model/clip.cpp b/src/gui/model/clip.cpp index 2815ea7fe..af53ce7a6 100644 --- a/src/gui/model/clip.cpp +++ b/src/gui/model/clip.cpp @@ -1,6 +1,6 @@ /* - timeline-track.cpp - Implementation of the timeline clip object - + clip.cpp - Implementation of the Clip object + Copyright (C) Lumiera.org 2008, Joel Holdsworth diff --git a/src/gui/model/clip.hpp b/src/gui/model/clip.hpp index df9d67d1c..1c895239f 100644 --- a/src/gui/model/clip.hpp +++ b/src/gui/model/clip.hpp @@ -1,5 +1,5 @@ /* - timeline-clip.hpp - Declaration of the timeline clip object + clip.hpp - Definition of the Clip class Copyright (C) Lumiera.org 2008, Joel Holdsworth @@ -19,8 +19,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/** @file widgets/timeline/timeline-clip.hpp - ** This file contains the definition of timeline clip object +/** @file model/clip.hpp + ** This file contains the definition of the Clip object */ #ifndef CLIP_HPP @@ -32,6 +32,9 @@ namespace model { class Clip { public: + /** + * Constructor + **/ Clip(); }; diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp index eac93ba09..2eb68bf06 100644 --- a/src/gui/widgets/timeline/timeline-body.cpp +++ b/src/gui/widgets/timeline/timeline-body.cpp @@ -1,6 +1,11 @@ /* +<<<<<<< HEAD timeline.cpp - Implementation of the timeline widget +======= + timeline-body.cpp - Implementation of the timeline body widget + +>>>>>>> Fix several incorrect comments (refering to the wrong file). Copyright (C) Lumiera.org 2008, Joel Holdsworth diff --git a/src/gui/widgets/timeline/timeline-clip.cpp b/src/gui/widgets/timeline/timeline-clip.cpp index e4c031e52..47826f077 100644 --- a/src/gui/widgets/timeline/timeline-clip.cpp +++ b/src/gui/widgets/timeline/timeline-clip.cpp @@ -1,6 +1,6 @@ /* - timeline-track.cpp - Implementation of the timeline clip object - + timeline-clip.cpp - Implementation of the timeline clip object + Copyright (C) Lumiera.org 2008, Joel Holdsworth diff --git a/src/gui/widgets/timeline/timeline-view-window.cpp b/src/gui/widgets/timeline/timeline-view-window.cpp index 6ea7ff242..dcaf8845c 100644 --- a/src/gui/widgets/timeline/timeline-view-window.cpp +++ b/src/gui/widgets/timeline/timeline-view-window.cpp @@ -1,6 +1,6 @@ /* - timeline-window.hpp - Implementation of the timeline window object - + timeline-view-window.hpp - Implementation of the timeline window object + Copyright (C) Lumiera.org 2008, Joel Holdsworth From 799a8188de41ca509b8919fb1345535ffa24620e Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 24 Dec 2010 03:22:56 +0100 Subject: [PATCH 18/30] First implementation of track visible in timeline. --- src/gui/model/parent-track.hpp | 2 +- .../widgets/timeline/timeline-clip-track.cpp | 22 +++++++-- .../widgets/timeline/timeline-clip-track.hpp | 6 ++- src/gui/widgets/timeline/timeline-clip.cpp | 45 ++++++++++++++++++- src/gui/widgets/timeline/timeline-clip.hpp | 13 +++++- 5 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/gui/model/parent-track.hpp b/src/gui/model/parent-track.hpp index 6d5b0481a..89967eccc 100644 --- a/src/gui/model/parent-track.hpp +++ b/src/gui/model/parent-track.hpp @@ -89,7 +89,7 @@ public: protected: /** - * The internal list of child tracks of this paremt. + * The internal list of child tracks of this parent. **/ lumiera::observable_list< boost::shared_ptr > tracks; }; diff --git a/src/gui/widgets/timeline/timeline-clip-track.cpp b/src/gui/widgets/timeline/timeline-clip-track.cpp index 2b2bbb875..92a2f4511 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.cpp +++ b/src/gui/widgets/timeline/timeline-clip-track.cpp @@ -20,6 +20,9 @@ * *****************************************************/ +#include + +#include "timeline-clip.hpp" #include "timeline-clip-track.hpp" #include "timeline-view-window.hpp" @@ -28,19 +31,26 @@ using namespace Gtk; namespace gui { namespace widgets { namespace timeline { - + ClipTrack::ClipTrack(TimelineWidget &timeline_widget, boost::shared_ptr track) : Track(timeline_widget, track) { + // TEST CODE: add a clip to the track + boost::shared_ptr model_clip(new model::Clip()); + boost::shared_ptr timeline_clip(new timeline::Clip(model_clip)); + clips.push_back(timeline_clip); + // END TEST CODE } void ClipTrack::draw_track(Cairo::RefPtr cairo, TimelineViewWindow* const window) const { - - + REQUIRE(cairo); + REQUIRE(window); + + // Draw a rectangle to let us know it works? :-) cairo->rectangle(window->time_to_x(0), 1, window->time_to_x(500000) - window->time_to_x(0), get_height() - 2); @@ -50,6 +60,12 @@ ClipTrack::draw_track(Cairo::RefPtr cairo, cairo->set_source_rgb(0.25, 0.25, 0.25); cairo->stroke(); + + // Draw all clips + BOOST_FOREACH(boost::shared_ptr c, clips) + { + c->draw_clip(cairo, window); + } } } // namespace timeline diff --git a/src/gui/widgets/timeline/timeline-clip-track.hpp b/src/gui/widgets/timeline/timeline-clip-track.hpp index f6947fbe8..90f63fc7d 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.hpp +++ b/src/gui/widgets/timeline/timeline-clip-track.hpp @@ -28,6 +28,8 @@ #ifndef TIMELINE_CLIP_TRACK_HPP #define TIMELINE_CLIP_TRACK_HPP +#include + #include "timeline-track.hpp" #include "../../model/clip-track.hpp" @@ -46,7 +48,9 @@ public: void draw_track(Cairo::RefPtr cairo, TimelineViewWindow* const window) const; - + +private: + std::vector > clips; }; } // namespace timeline diff --git a/src/gui/widgets/timeline/timeline-clip.cpp b/src/gui/widgets/timeline/timeline-clip.cpp index 47826f077..dc93ccbb5 100644 --- a/src/gui/widgets/timeline/timeline-clip.cpp +++ b/src/gui/widgets/timeline/timeline-clip.cpp @@ -26,11 +26,52 @@ namespace gui { namespace widgets { namespace timeline { -Clip::Clip() +Clip::Clip(boost::shared_ptr clip) + : model_clip(clip) { - + REQUIRE(model_clip); } +void +Clip::draw_clip(Cairo::RefPtr cr, + TimelineViewWindow* const window) const +{ + REQUIRE(cr); + REQUIRE(window); + + int x = window->time_to_x(1000000); + int width = window->time_to_x(2000000) - window->time_to_x(1000000); + + // Draw a rectangle for the clip + cr->rectangle(x, 1, width, 100-2); + + // TODO: get duration from the model::Clip + // TODO: get height from the Timeline::Track + + cr->set_source_rgb(0.4, 0.4, 0.4); + cr->fill_preserve(); + + cr->set_source_rgb(0.25, 0.25, 0.25); + cr->stroke(); + + // Show the clip name + cr->rectangle(x, 1, width, 100-2); + cr->clip(); + + cr->move_to(x + 3, 15); + cr->set_source_rgb(1.0, 1.0, 1.0); + Cairo::RefPtr font = + Cairo::ToyFontFace::create("Bitstream Charter", + Cairo::FONT_SLANT_NORMAL, + Cairo::FONT_WEIGHT_NORMAL); + cr->set_font_face(font); + cr->set_font_size(11); + cr->show_text("Track"); // TODO: get clip name from model + + // TODO: Show thumbnails for clip +} + + } // namespace timeline } // namespace widgets } // namespace gui diff --git a/src/gui/widgets/timeline/timeline-clip.hpp b/src/gui/widgets/timeline/timeline-clip.hpp index 46cc751be..c08d87c66 100644 --- a/src/gui/widgets/timeline/timeline-clip.hpp +++ b/src/gui/widgets/timeline/timeline-clip.hpp @@ -23,7 +23,11 @@ ** This file contains the definition of timeline clip object */ + +#include "../../gtk-lumiera.hpp" #include "../../model/clip.hpp" +#include "timeline-view-window.hpp" +#include "include/logging.h" #ifndef TIMELINE_CLIP_HPP #define TIMELINE_CLIP_HPP @@ -35,11 +39,16 @@ namespace timeline { class Clip : public model::Clip { public: - Clip(); + Clip(boost::shared_ptr clip); + void draw_clip(Cairo::RefPtr cairo, + TimelineViewWindow* const window) const; + +private: + + boost::shared_ptr model_clip; }; - } // namespace timeline } // namespace widgets } // namespace gui From 51fea246643c3594fd9b7c4c6a56b5ee83d443a0 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 24 Dec 2010 03:51:57 +0100 Subject: [PATCH 19/30] Add GUI/model tests fixtures --- tests/51-gui-model.tests | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/51-gui-model.tests diff --git a/tests/51-gui-model.tests b/tests/51-gui-model.tests new file mode 100644 index 000000000..a73a49606 --- /dev/null +++ b/tests/51-gui-model.tests @@ -0,0 +1,22 @@ +TESTING "Component Test Suite: GUI Model Parts" ./test-components --group=gui + +PLANNED "ModelClipTrack_test" ModelClipTrack_test < Date: Fri, 10 Dec 2010 21:45:48 +0100 Subject: [PATCH 20/30] Use Time instead of gavl_time_t in the timecode widget. --- src/gui/widgets/timecode-widget.cpp | 96 +++++++++++++---------------- src/gui/widgets/timecode-widget.hpp | 36 ++++++----- 2 files changed, 63 insertions(+), 69 deletions(-) diff --git a/src/gui/widgets/timecode-widget.cpp b/src/gui/widgets/timecode-widget.cpp index 964f22c16..a97220555 100644 --- a/src/gui/widgets/timecode-widget.cpp +++ b/src/gui/widgets/timecode-widget.cpp @@ -33,12 +33,6 @@ #include "timecode-widget.hpp" #include "../util/convert.hpp" -#include "../../lib/lumitime.hpp" - -extern "C" { -#include "../../lib/time.h" -} - using namespace sigc; using namespace Gtk; using namespace std; @@ -75,7 +69,7 @@ TimeCode::TimeCode(std::string clock_name, std::string widget_name, bool allow_e colon4(":"), colon5(":") { - last_when = 0; + last_when = Time(0); last_pdelta = 0; last_sdelta = 0; key_entry_state = 0; @@ -380,7 +374,7 @@ TimeCode::on_realize() } void -TimeCode::set(gavl_time_t when, bool force) +TimeCode::set(Time when, bool force) { if (!force && when == last_when) return; @@ -425,7 +419,7 @@ TimeCode::set(gavl_time_t when, bool force) // } void -TimeCode::set_frames(gavl_time_t when, bool force) +TimeCode::set_frames(Time when, bool force) { char buf[32]; snprintf(buf, sizeof(buf), "%u", (unsigned int)when); @@ -433,15 +427,13 @@ TimeCode::set_frames(gavl_time_t when, bool force) } void -TimeCode::set_minsec(gavl_time_t when, bool force) +TimeCode::set_minsec(Time when, bool force) { char buf[32]; - lumiera::Time t(when); - - int hrs = t.getHours(); - int mins = t.getMins(); - float secs = t.getSecs(); + int hrs = when.getHours(); + int mins = when.getMins(); + float secs = when.getSecs(); if (force || hrs != ms_last_hrs) { @@ -466,17 +458,15 @@ TimeCode::set_minsec(gavl_time_t when, bool force) } void -TimeCode::set_smpte(gavl_time_t when, bool force) +TimeCode::set_smpte(Time when, bool force) { char buf[32]; - lumiera::Time t(when); - - int smpte_negative = when < 0; - int smpte_hours = t.getHours(); - int smpte_minutes = t.getMins(); - int smpte_seconds = t.getSecs(); - int smpte_frames = 0; //t.getFrames(framerate); + int smpte_negative = 0; // FIXME: when < 0; + int smpte_hours = when.getHours(); + int smpte_minutes = when.getMins(); + int smpte_seconds = when.getSecs(); + int smpte_frames = 0; //when.getFrames(framerate); // if (is_duration) { // session->smpte_duration(when, smpte); @@ -933,7 +923,7 @@ TimeCode::field_button_press_event(GdkEventButton *ev, Field field) return false; // if (session == 0) return false; - // gavl_time_t frames = 0; + // Time frames = 0; switch (ev->button) { case 1: @@ -981,7 +971,7 @@ TimeCode::field_button_scroll_event (GdkEventScroll *ev, Field field) // return false; // } - // gavl_time_t frames = 0; + // Time frames = 0; switch (ev->direction) { @@ -1050,21 +1040,21 @@ TimeCode::field_motion_notify_event (GdkEventMotion *ev, Field field) if (trunc(drag_accum) != 0) { - gavl_time_t frames; - gavl_time_t pos ; + int frames; + Time pos; int dir; dir = (drag_accum < 0 ? 1:-1); pos = current_time(); frames = get_frames(field,pos,dir); - if (frames != 0 && frames * drag_accum < current_time()) + if (frames != 0 && frames * drag_accum < ((gavl_time_t)current_time())) { // minus because up is negative in computer-land - set ((gavl_time_t) floor (pos - drag_accum * frames), false); + set ((Time) floor (pos - drag_accum * frames), false); } else { - set (0 , false); + set (Time(0) , false); } drag_accum = 0; @@ -1074,23 +1064,23 @@ TimeCode::field_motion_notify_event (GdkEventMotion *ev, Field field) return true; } -gavl_time_t -TimeCode::get_frames(Field field, gavl_time_t pos, int dir) +int +TimeCode::get_frames(Field field, Time pos, int dir) { - gavl_time_t frames = 0; + int frames = 0; // switch (field) // { // case SMPTE_Hours: - // frames = (gavl_time_t) floor (3600.0 * session->frame_rate()); + // frames = (Time) floor (3600.0 * session->frame_rate()); // break; // case SMPTE_Minutes: - // frames = (gavl_time_t) floor (60.0 * session->frame_rate()); + // frames = (Time) floor (60.0 * session->frame_rate()); // break; // case SMPTE_Seconds: // frames = session->frame_rate(); // break; // case SMPTE_Frames: - // frames = (gavl_time_t) floor (session->frame_rate() / session->smpte_frames_per_second()); + // frames = (Time) floor (session->frame_rate() / session->smpte_frames_per_second()); // break; // case VFrames: @@ -1098,10 +1088,10 @@ TimeCode::get_frames(Field field, gavl_time_t pos, int dir) // break; // case MS_Hours: - // frames = (gavl_time_t) floor (3600.0 * session->frame_rate()); + // frames = (Time) floor (3600.0 * session->frame_rate()); // break; // case MS_Minutes: - // frames = (gavl_time_t) floor (60.0 * session->frame_rate()); + // frames = (Time) floor (60.0 * session->frame_rate()); // break; // case MS_Seconds: // frames = session->frame_rate(); @@ -1111,10 +1101,10 @@ TimeCode::get_frames(Field field, gavl_time_t pos, int dir) return frames; } -gavl_time_t -TimeCode::current_time(gavl_time_t pos) const +Time +TimeCode::current_time(Time pos) const { - gavl_time_t ret = 0; + Time ret = Time(0); switch (_mode) { @@ -1137,10 +1127,10 @@ TimeCode::current_time(gavl_time_t pos) const return ret; } -gavl_time_t -TimeCode::current_duration(gavl_time_t pos) const +Time +TimeCode::current_duration(Time pos) const { - gavl_time_t ret = 0; + Time ret = Time(0); switch (_mode) { @@ -1193,13 +1183,13 @@ TimeCode::smpte_sanitize_display() // } } -gavl_time_t +Time TimeCode::smpte_time_from_display() const { // TODO // SMPTE::Time smpte; - // gavl_time_t sample; + // Time sample; // smpte.hours = atoi (hours_label.get_text()); // smpte.minutes = atoi (minutes_label.get_text()); @@ -1210,10 +1200,10 @@ TimeCode::smpte_time_from_display() const // session->smpte_to_sample(smpte, sample, false /* use_offset */, false /* use_subframes */ ); - return 0; + return Time(0); } -gavl_time_t +Time TimeCode::minsec_time_from_display () const { // TODO @@ -1222,17 +1212,17 @@ TimeCode::minsec_time_from_display () const // int mins = atoi (ms_minutes_label.get_text()); // float secs = atof (ms_seconds_label.get_text()); - // gavl_time_t sr = session->frame_rate(); + // Time sr = session->frame_rate(); - // return (gavl_time_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr)); + // return (Time) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr)); - return 0; + return Time(0); } -gavl_time_t +Time TimeCode::audio_time_from_display () const { - return (gavl_time_t) atoi (audio_frames_label.get_text()); + return Time((gavl_time_t) atoi (audio_frames_label.get_text())); } void diff --git a/src/gui/widgets/timecode-widget.hpp b/src/gui/widgets/timecode-widget.hpp index cb63060ed..3a280a589 100644 --- a/src/gui/widgets/timecode-widget.hpp +++ b/src/gui/widgets/timecode-widget.hpp @@ -33,6 +33,10 @@ #include #include +#include "lib/lumitime.hpp" + +using lumiera::Time; + namespace gui { namespace widgets { @@ -52,15 +56,15 @@ public: void focus(); - void set(gavl_time_t, bool force = false); + void set(Time when, bool force = false); void set_mode(Mode); void set_widget_name(std::string); std::string name() const { return _name; } - gavl_time_t current_time(gavl_time_t position = 0) const; - gavl_time_t current_duration(gavl_time_t position = 0) const; + Time current_time(Time position = Time(0)) const; + Time current_duration(Time position = Time(0)) const; sigc::signal ValueChanged; sigc::signal ChangeAborted; @@ -127,7 +131,7 @@ private: Gtk::EventBox clock_base; Gtk::Frame clock_frame; - gavl_time_t last_when; + Time last_when; bool last_pdelta; bool last_sdelta; @@ -152,22 +156,22 @@ private: bool field_button_press_event(GdkEventButton *ev, Field); bool field_button_release_event(GdkEventButton *ev, Field); bool field_button_scroll_event(GdkEventScroll *ev, Field); - bool field_key_press_event(GdkEventKey *, Field); - bool field_key_release_event(GdkEventKey *, Field); - bool field_focus_in_event(GdkEventFocus *, Field); - bool field_focus_out_event(GdkEventFocus *, Field); - bool drop_focus_handler(GdkEventFocus*); + bool field_key_press_event(GdkEventKey *ev, Field); + bool field_key_release_event(GdkEventKey *ev, Field); + bool field_focus_in_event(GdkEventFocus *ev, Field); + bool field_focus_out_event(GdkEventFocus *ev, Field); + bool drop_focus_handler(GdkEventFocus *ev); - void set_smpte(gavl_time_t, bool); - void set_minsec(gavl_time_t, bool); - void set_frames(gavl_time_t, bool); + void set_smpte(Time, bool); + void set_minsec(Time, bool); + void set_frames(Time, bool); - gavl_time_t get_frames(Field, gavl_time_t pos = 0, int dir=1); + int get_frames(Field, Time pos = Time(0), int dir=1); void smpte_sanitize_display(); - gavl_time_t smpte_time_from_display() const; - gavl_time_t minsec_time_from_display() const; - gavl_time_t audio_time_from_display() const; + Time smpte_time_from_display() const; + Time minsec_time_from_display() const; + Time audio_time_from_display() const; void build_ops_menu(); void setup_events(); From 0594ea26adc3ae633802508dc76888accafb1026 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 24 Dec 2010 22:46:22 +0100 Subject: [PATCH 21/30] Make Timeline Arrow Tool use the standard left cursor. --- src/gui/widgets/timeline/timeline-arrow-tool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/widgets/timeline/timeline-arrow-tool.cpp b/src/gui/widgets/timeline/timeline-arrow-tool.cpp index d985cf7bf..67765288f 100644 --- a/src/gui/widgets/timeline/timeline-arrow-tool.cpp +++ b/src/gui/widgets/timeline/timeline-arrow-tool.cpp @@ -41,7 +41,7 @@ ArrowTool::get_type() const Gdk::Cursor ArrowTool::get_cursor() const { - return Gdk::Cursor(Gdk::ARROW); + return Gdk::Cursor(Gdk::LEFT_PTR); } void From e0da4c2378ec74f8ea7a901afe418240835b97ac Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 24 Dec 2010 23:10:00 +0100 Subject: [PATCH 22/30] Make Timeline default to Arrow Tool instead of Ibeamer Tool. --- src/gui/panels/timeline-panel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/panels/timeline-panel.cpp b/src/gui/panels/timeline-panel.cpp index 325cda76b..26bbdfd6b 100644 --- a/src/gui/panels/timeline-panel.cpp +++ b/src/gui/panels/timeline-panel.cpp @@ -61,7 +61,7 @@ TimelinePanel::TimelinePanel(workspace::PanelManager &panel_manager, zoomIn(Stock::ZOOM_IN), zoomOut(Stock::ZOOM_OUT), updatingToolbar(false), - currentTool(timeline::IBeam) + currentTool(timeline::Arrow) { // Hook up notifications get_project().get_sequences().signal_changed().connect(mem_fun(this, From 87ad80f17e2fff74a93e86e1b35ffa8471b549dc Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 24 Dec 2010 23:17:28 +0100 Subject: [PATCH 23/30] Fix typos. --- src/gui/panels/timeline-panel.cpp | 4 ++-- src/gui/panels/timeline-panel.hpp | 4 ++-- src/gui/widgets/timeline/timeline-clip.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/panels/timeline-panel.cpp b/src/gui/panels/timeline-panel.cpp index 26bbdfd6b..5f564dd90 100644 --- a/src/gui/panels/timeline-panel.cpp +++ b/src/gui/panels/timeline-panel.cpp @@ -92,14 +92,14 @@ TimelinePanel::TimelinePanel(workspace::PanelManager &panel_manager, toolbar.append(forwardButton); toolbar.append(nextButton); - toolbar.append(seperator1); + toolbar.append(separator1); toolbar.append(arrowTool, mem_fun(this, &TimelinePanel::on_arrow_tool)); toolbar.append(iBeamTool, mem_fun(this, &TimelinePanel::on_ibeam_tool)); - toolbar.append(seperator2); + toolbar.append(separator2); toolbar.append(zoomIn, mem_fun(this, &TimelinePanel::on_zoom_in)); toolbar.append(zoomOut, mem_fun(this, &TimelinePanel::on_zoom_out)); diff --git a/src/gui/panels/timeline-panel.hpp b/src/gui/panels/timeline-panel.hpp index 8b209b3ff..75df50cd5 100644 --- a/src/gui/panels/timeline-panel.hpp +++ b/src/gui/panels/timeline-panel.hpp @@ -181,12 +181,12 @@ private: MiniToggleButton arrowTool; MiniToggleButton iBeamTool; - Gtk::SeparatorToolItem seperator1; + Gtk::SeparatorToolItem separator1; MiniButton zoomIn; MiniButton zoomOut; - Gtk::SeparatorToolItem seperator2; + Gtk::SeparatorToolItem separator2; // Internals bool updatingToolbar; diff --git a/src/gui/widgets/timeline/timeline-clip.cpp b/src/gui/widgets/timeline/timeline-clip.cpp index dc93ccbb5..d41a473ca 100644 --- a/src/gui/widgets/timeline/timeline-clip.cpp +++ b/src/gui/widgets/timeline/timeline-clip.cpp @@ -66,7 +66,7 @@ Clip::draw_clip(Cairo::RefPtr cr, Cairo::FONT_WEIGHT_NORMAL); cr->set_font_face(font); cr->set_font_size(11); - cr->show_text("Track"); // TODO: get clip name from model + cr->show_text("Clip Name"); // TODO: get clip name from model // TODO: Show thumbnails for clip } From 063e5887b4e3360ae0f7e16ef10b90e2a690ad97 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sat, 25 Dec 2010 04:39:30 +0100 Subject: [PATCH 24/30] Fix Ardour Timecode widget: compilation problems on the buildserver. (Ticket #735) --- src/gui/widgets/timecode-widget.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/gui/widgets/timecode-widget.cpp b/src/gui/widgets/timecode-widget.cpp index a97220555..b43c9087f 100644 --- a/src/gui/widgets/timecode-widget.cpp +++ b/src/gui/widgets/timecode-widget.cpp @@ -187,7 +187,8 @@ TimeCode::set_widget_name(string name) void TimeCode::setup_events() { - clock_base.set_can_focus(true); + // FIXME: change to set_can_focus(true) once Debian squeeze is released + clock_base.set_flags(CAN_FOCUS); const Gdk::EventMask eventMask = Gdk::BUTTON_PRESS_MASK| @@ -207,14 +208,15 @@ TimeCode::setup_events() ms_seconds_ebox.add_events(eventMask); audio_frames_ebox.add_events(eventMask); - hours_ebox.set_can_focus(true); - minutes_ebox.set_can_focus(true); - seconds_ebox.set_can_focus(true); - frames_ebox.set_can_focus(true); - audio_frames_ebox.set_can_focus(true); - ms_hours_ebox.set_can_focus(true); - ms_minutes_ebox.set_can_focus(true); - ms_seconds_ebox.set_can_focus(true); + // FIXME: change to set_can_focus(true) once Debian squeeze is released + hours_ebox.set_flags(CAN_FOCUS); + minutes_ebox.set_flags(CAN_FOCUS); + seconds_ebox.set_flags(CAN_FOCUS); + frames_ebox.set_flags(CAN_FOCUS); + audio_frames_ebox.set_flags(CAN_FOCUS); + ms_hours_ebox.set_flags(CAN_FOCUS); + ms_minutes_ebox.set_flags(CAN_FOCUS); + ms_seconds_ebox.set_flags(CAN_FOCUS); hours_ebox.signal_motion_notify_event().connect(bind(mem_fun( *this, &TimeCode::field_motion_notify_event), SMPTE_Hours)); From 60ccdda018a83ae64f6800eabae6c905e9a2ce90 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sat, 25 Dec 2010 21:29:53 +0100 Subject: [PATCH 25/30] Replace several uses of GdkColor with Cairo::SolidPattern. --- src/gui/Makefile.am | 2 ++ src/gui/widgets/timeline/timeline-body.cpp | 22 +++++------- src/gui/widgets/timeline/timeline-body.hpp | 6 ++-- src/gui/widgets/timeline/timeline-ruler.cpp | 19 ++++------- src/gui/widgets/timeline/timeline-ruler.hpp | 4 +-- src/gui/window-manager.cpp | 38 +++++++++++++-------- src/gui/window-manager.hpp | 8 +++-- src/gui/workspace/actions.cpp | 6 ++-- 8 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 55218452e..f47509758 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -95,6 +95,8 @@ gtk_gui_la_SOURCES = \ $(lumigui_srcdir)/panels/timeline-panel.hpp \ $(lumigui_srcdir)/panels/viewer-panel.cpp \ $(lumigui_srcdir)/panels/viewer-panel.hpp \ + $(lumigui_srcdir)/util/cairo-util.cpp \ + $(lumigui_srcdir)/util/cairo-util.hpp \ $(lumigui_srcdir)/util/convert.cpp \ $(lumigui_srcdir)/util/convert.hpp \ $(lumigui_srcdir)/util/rectangle.cpp \ diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp index 2eb68bf06..0143ea627 100644 --- a/src/gui/widgets/timeline/timeline-body.cpp +++ b/src/gui/widgets/timeline/timeline-body.cpp @@ -1,11 +1,6 @@ /* -<<<<<<< HEAD - timeline.cpp - Implementation of the timeline widget - -======= timeline-body.cpp - Implementation of the timeline body widget ->>>>>>> Fix several incorrect comments (refering to the wrong file). Copyright (C) Lumiera.org 2008, Joel Holdsworth @@ -31,6 +26,7 @@ #include "timeline-body.hpp" #include "../timeline-widget.hpp" #include "../../window-manager.hpp" +#include "../../util/cairo-util.hpp" #include "timeline-arrow-tool.hpp" #include "timeline-ibeam-tool.hpp" @@ -41,6 +37,8 @@ using namespace std; using namespace boost; using namespace lumiera; +using gui::util::CairoUtil; + namespace gui { namespace widgets { namespace timeline { @@ -362,8 +360,8 @@ TimelineBody::draw_track(Cairo::RefPtr cr, // Draw the track background cr->rectangle(0, 0, view_width, height); - GdkColor colour = backgroundColour; // Needed to preserve const qualifier - gdk_cairo_set_source_color(cr->cobj(), &colour); + Cairo::RefPtr bg_col = backgroundColour; // Needed to preserve const qualifier + cr->set_source(bg_col); cr->fill(); // Render the track @@ -391,17 +389,13 @@ TimelineBody::draw_selection(Cairo::RefPtr cr) // Draw the cover if(end_x > 0 && start_x < allocation.get_width()) { - cr->set_source_rgba( - (float)selectionColour.red / 0xFFFF, - (float)selectionColour.green / 0xFFFF, - (float)selectionColour.blue / 0xFFFF, - selectionAlpha); + cr->set_source (CairoUtil::pattern_set_alpha (selectionColour, selectionAlpha)); cr->rectangle(start_x + 0.5, 0, end_x - start_x, allocation.get_height()); cr->fill(); } - gdk_cairo_set_source_color(cr->cobj(), &selectionColour); + cr->set_source(selectionColour); cr->set_line_width(1); // Draw the start @@ -440,7 +434,7 @@ TimelineBody::draw_playback_point(Cairo::RefPtr cr) const int x = view_window().time_to_x(point); // Set source - gdk_cairo_set_source_color(cr->cobj(), &playbackPointColour); + cr->set_source(playbackPointColour); cr->set_line_width(1); // Draw diff --git a/src/gui/widgets/timeline/timeline-body.hpp b/src/gui/widgets/timeline/timeline-body.hpp index 46dfb2303..71e22520b 100644 --- a/src/gui/widgets/timeline/timeline-body.hpp +++ b/src/gui/widgets/timeline/timeline-body.hpp @@ -183,10 +183,10 @@ private: int beginShiftVerticalOffset; // Style properties - GdkColor backgroundColour; - GdkColor selectionColour; + Cairo::RefPtr backgroundColour; + Cairo::RefPtr selectionColour; float selectionAlpha; - GdkColor playbackPointColour; + Cairo::RefPtr playbackPointColour; gui::widgets::TimelineWidget &timelineWidget; diff --git a/src/gui/widgets/timeline/timeline-ruler.cpp b/src/gui/widgets/timeline/timeline-ruler.cpp index cd5c9cdd3..f67f929bc 100644 --- a/src/gui/widgets/timeline/timeline-ruler.cpp +++ b/src/gui/widgets/timeline/timeline-ruler.cpp @@ -25,6 +25,7 @@ #include "timeline-ruler.hpp" #include "../timeline-widget.hpp" #include "../../window-manager.hpp" +#include "../../util/cairo-util.hpp" extern "C" { #include "../../../lib/time.h" @@ -39,6 +40,8 @@ using namespace gui::widgets; using namespace gui::widgets::timeline; using namespace lumiera; +using gui::util::CairoUtil; + namespace gui { namespace widgets { namespace timeline { @@ -445,15 +448,11 @@ TimelineRuler::draw_playback_period(Cairo::RefPtr cr, } // Fill - cr->set_source_rgba( - (float)playbackPeriodArrowColour.red / 0xFFFF, - (float)playbackPeriodArrowColour.green / 0xFFFF, - (float)playbackPeriodArrowColour.blue / 0xFFFF, - playbackPeriodArrowAlpha); + cr->set_source (CairoUtil::pattern_set_alpha (playbackPeriodArrowColour, playbackPeriodArrowAlpha)); cr->fill_preserve(); // Stroke - gdk_cairo_set_source_color(cr->cobj(), &playbackPeriodArrowColour); + cr->set_source(playbackPeriodArrowColour); cr->set_line_width(1); cr->stroke(); } @@ -481,15 +480,11 @@ TimelineRuler::draw_playback_point(Cairo::RefPtr cr, cr->close_path(); // Fill - cr->set_source_rgba( - (float)playbackPointColour.red / 0xFFFF, - (float)playbackPointColour.green / 0xFFFF, - (float)playbackPointColour.blue / 0xFFFF, - playbackPointAlpha); + cr->set_source (CairoUtil::pattern_set_alpha (playbackPeriodArrowColour, playbackPeriodArrowAlpha)); cr->fill_preserve(); // Stroke - gdk_cairo_set_source_color(cr->cobj(), &playbackPointColour); + cr->set_source(playbackPointColour); cr->set_line_width(1); cr->stroke(); } diff --git a/src/gui/widgets/timeline/timeline-ruler.hpp b/src/gui/widgets/timeline/timeline-ruler.hpp index 4e8bf2083..bdeb08f63 100644 --- a/src/gui/widgets/timeline/timeline-ruler.hpp +++ b/src/gui/widgets/timeline/timeline-ruler.hpp @@ -218,11 +218,11 @@ private: int mouseChevronSize; int selectionChevronSize; - GdkColor playbackPointColour; + Cairo::RefPtr playbackPointColour; float playbackPointAlpha; int playbackPointSize; - GdkColor playbackPeriodArrowColour; + Cairo::RefPtr playbackPeriodArrowColour; float playbackPeriodArrowAlpha; int playbackPeriodArrowSize; int playbackPeriodArrowStemSize; diff --git a/src/gui/window-manager.cpp b/src/gui/window-manager.cpp index cd108bf71..52d466286 100644 --- a/src/gui/window-manager.cpp +++ b/src/gui/window-manager.cpp @@ -91,7 +91,7 @@ WindowManager::on_window_closed(GdkEventAny* event) shared_ptr workspace_window(*iterator); REQUIRE(workspace_window); - RefPtr window = workspace_window->get_window(); + Glib::RefPtr window = workspace_window->get_window(); REQUIRE(window); if(window->gobj() == event->window) { @@ -134,25 +134,33 @@ WindowManager::update_close_window_in_menus() } } -GdkColor -WindowManager::read_style_colour_property( +Cairo::RefPtr +WindowManager::read_style_colour_property ( Gtk::Widget &widget, const gchar *property_name, guint16 red, guint16 green, guint16 blue) { - GdkColor *colour; + REQUIRE (property_name); - gtk_widget_style_get(widget.gobj(), property_name, &colour, NULL); + // TODO: Can we get rid of the GdkColor completely here? + GdkColor *color; + gtk_widget_style_get(widget.gobj(), property_name, &color, NULL); + Cairo::RefPtr pattern; // Did the color load successfully? - if(colour != NULL) - return *colour; + if (color != NULL) + { + pattern = Cairo::SolidPattern::create_rgb ( (double)color->red / 0xFFFF, + (double)color->green / 0xFFFF, + (double)color->blue / 0xFFFF); + } else - { - WARN(gui, "%s style value failed to load", property_name); - - const GdkColor default_colour = {0, red, green, blue}; - return default_colour; - } + { + WARN(gui, "%s style value failed to load", property_name); + + pattern = Cairo::SolidPattern::create_rgb ( red, green, blue ); + } + + return pattern; } void @@ -167,7 +175,7 @@ WindowManager::register_app_icon_sizes() void WindowManager::register_stock_items() { - RefPtr factory = IconFactory::create(); + Glib::RefPtr factory = IconFactory::create(); add_stock_icon_set(factory, "panel-resources", "panel_resources", _("_Resources")); add_stock_icon_set(factory, "panel-timeline", "panel_timeline", _("_Timeline")); @@ -256,7 +264,7 @@ WindowManager::add_theme_icon_source(Gtk::IconSet &icon_set, REQUIRE(width > 0); // Try to load the icon - RefPtr theme = Gtk::IconTheme::get_default(); + Glib::RefPtr theme = Gtk::IconTheme::get_default(); REQUIRE(theme); TODO ("find out how IconInfo could be made const. For example, GTKmm 2.10.10 is missing the const on operator bool() in iconinfo.h"); diff --git a/src/gui/window-manager.hpp b/src/gui/window-manager.hpp index 987bde10a..29ead7005 100644 --- a/src/gui/window-manager.hpp +++ b/src/gui/window-manager.hpp @@ -25,6 +25,8 @@ ** @see gtk-lumiera.hpp */ +#include + #include "gtk-lumiera.hpp" //#include "workspace/workspace-window.hpp" @@ -81,9 +83,9 @@ public: * @param blue The fallback blue intensity. * @return The loaded colour. **/ - static GdkColor read_style_colour_property( - Gtk::Widget &widget, const gchar *property_name, - guint16 red, guint16 green, guint16 blue); + static Cairo::RefPtr + read_style_colour_property (Gtk::Widget &widget, const gchar *property_name, + guint16 red, guint16 green, guint16 blue); private: diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index 0472e7b59..c52ca36ec 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -49,7 +49,7 @@ Actions::Actions(WorkspaceWindow &workspace_window) : } void -Actions::populate_main_actions(RefPtr uiManager) +Actions::populate_main_actions(Glib::RefPtr uiManager) { REQUIRE(uiManager); @@ -208,11 +208,11 @@ Actions::populate_main_actions(RefPtr uiManager) } void -Actions::populate_show_panel_actions(RefPtr uiManager) +Actions::populate_show_panel_actions(Glib::RefPtr uiManager) { const int count = PanelManager::get_panel_description_count(); - RefPtr actionGroup = ActionGroup::create(); + Glib::RefPtr actionGroup = ActionGroup::create(); for(int i = 0; i < count; i++) { const gchar *stock_id = PanelManager::get_panel_stock_id(i); From b5f32522b1c771a1ac5554e8f109283ef658d625 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 26 Dec 2010 03:36:27 +0100 Subject: [PATCH 26/30] still chewing on the remaining problems with time quantisation --- wiki/renderengine.html | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 0434f3a91..28b45fef5 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -6584,7 +6584,7 @@ For Lumiera, the static typing approach is of limited value -- it excels when va &rarr; more on [[usage situations|TimeUsage]]
-
+
the following collection of usage situations helps to shape the details of the time values and time quantisation design. &rarr; see also  [[time quantisation|TimeQuant]]
 
 ;time position of an object
@@ -6612,18 +6612,40 @@ For Lumiera, the static typing approach is of limited value -- it excels when va
 ;relative placement
 :because of the divergence between quantised and unquantised values, the question arises, if placement relative to another object refers to the raw position or the already quantised position. Basically all the variations discussed for //time and length of an object// also do apply here.
 
-!notable problems
+!notable issues
 ''Direct quantisation of length is not possible''. This is due to the non-linear nature of all but the most trivial time grids: Already such a simple addition like a start offset destroys linearity, and this still the more is true within a compound grid where the grid spacing changes at some point. Thus, the length has to be re-established at the target position of an time interval after each change involving quantisation. Regarding the //strategy// to apply when re-establishing the length, it seems more appropriate to treat the object as an entity which is moved, which means to do quantisation in two steps, first the position, then the endpoint (the second option in the description above). But it seems advisable not to hard wire that strategy -- better put it into the quantiser.
 
-''When to materialise a quantisation''. Because of the basic intention to retain information, we delay actually applying the quantisation to the stored values as much as possible. This has the downside of possibly accumulating off-grid values without that being evident. On the other hand, allowing for quantised changes inevitably pulls in all the complexity of mixing quantised and non-quantised values. It seems more appropriate to move these distinctions out of the cope of this design and offload them onto the client (code using these time classes): thus we'd //only accept raw time values for redefining a quantised interval.// But the client code is still free to use a separate quantisation, which might even utilise a different grid. For example, when moving a clip taken from 50fps media, the new position might be quantised to the 50fps grid established by the media, while the target timeline runs with 25fps, allowing for finer adjustments based on the intermediate frames present in the source material.
+We should note, that the problems regarding quantised durations also carry over to //offsets:// it is difficult to ''define the semantics of a quantised offset''. Seemingly the only viable approach is to have a //intended offset,// and then to apply a re-quantisation to the target after applying the (raw) offset.
 
-Taking this approach also nicely removes the problem with the ''impossibility to quantise offsets''. This problem is an immediate consequence of the nonlinearity of most grids (as stated above). By just accepting raw time values for change, and indeed preferring just to re-set to new values, we don't solve that problem, but move it out of scope.
+''When to materialise a quantisation''. Because of the basic intention to retain information, we delay actually applying the quantisation to the stored values as much as possible. But not materialising immediately at quantisation has the downside of possibly accumulating off-grid values without that being evident. Most notably, if we apply the raw offsets produced by GUI interactions, the object's positions and lengthes are bound to accumulate spurious information never intended by the user.
+
+Thus, an especially important instance of that problem is ''how to deal with updates in a quantised environment''. If we handle quantisation stictly as a view employed on output, we run into the problems with accumulating spurious information. On the other hand, allowing for quantised changes inevitably pulls in all the complexity of mixing quantised and non-quantised values. It would be desirable somehow to move these distinctions out of the scope of this design and offload them onto the client (code using these time classes).
 
 Another closely related problem is ''when to allow mutations'', if at all. We can't completely do away with mutations, simply because we don't have a pure functional language at our disposal. The whole concept of //reference semantics// doesn't play so well with immutable objects. The Lumiera high-level (session) model certainly relies on objects intended to be //manipulated.// Thus we need a re-settable length field in {{{MObject}}} and we need a time variable for position calculations. Yet we could make any //derived objects// into immutable descriptor records, which certainly helps with parallelism.
 
 The ''problem with playback position'' is -- that it's an attempt to conceptualise a non-existing entity. There is no such thing like "the" playback position. Yet most applications I'm aware off employ this concept. Likely they got trapped by the metaphor of the tape head, again. We should do away with that. On playback, we should show a //projection of wall-clock time onto the expected playback range// -- not more, not less. It should be acknowledged that there is //no direct link to the ongoing playback processes,// besides the fact that they're assumed to sync to wall-clock time as well. Recall, typically there are multiple playback processes going on in compound, and each might run on a different update rate. If we really want a //visual out-of-sync indicator,// we should treat that as a separate reporting facility and display it apart of the playback cursor.
 
 Note that the ''display window might be treated as just an independent instance of quantisation''. This is similar to the approach taken above for modifying quantised time span values. We should provide a special kind of time grid, the display coordinates. The origin of these is always defined to the left (lower) side of the interval to be displayed, and they are gauged in screen units (pixels or similar, as used by the GUI toolkit set). The rest is handled by the general quantisation mechanisms. The problem of aligning the display should be transformed into a general facility to align grids, and solved for the general case. Doing so solves the remaining problems with quantised value changes and with ''specifying relative placements'' as well: If we choose to represent them as quantised values, we might (or might not) also choose to apply this //grid-alignment function.//
+
+!substantial problems to be solved
+* how to align multiple grids
+* how to integrate modifications of quantised values.
+
+The problem with modification of quantised values highlights an inner contratiction or conflicting goals
+* the whole system should fit in naturally and just feel like using raw time values
+* quantisation should be added //late// -- like a view
+* there should be a guidance towards the intended proper use
+
+!!! possible solutions{{red{WIP 12/10}}}
+* only allow to assign a completely new setting
+* only accept raw time values for redefining a quantised interval
+* only accept an abstract //modification object.//
+
+!!!usage considerations
+Question is: how fine grained and configurable needs this to be?
+* for example, when moving a clip taken from 50fps media, the new position might be quantised to the 50fps grid established by the media, while the target timeline runs with 25fps, allowing for finer adjustments based on the intermediate frames present in the source material.
+* likely we need a "nudge by unit(s)"
+
 
From fffb1b89da570cfa91aeb9729548d5789e315925 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Dec 2010 09:55:34 +0100 Subject: [PATCH 27/30] Fix compilation problems on the buildserver, cont. (Ticket #735) --- src/gui/widgets/timeline/timeline-clip.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-clip.cpp b/src/gui/widgets/timeline/timeline-clip.cpp index d41a473ca..fa8903fc9 100644 --- a/src/gui/widgets/timeline/timeline-clip.cpp +++ b/src/gui/widgets/timeline/timeline-clip.cpp @@ -58,15 +58,11 @@ Clip::draw_clip(Cairo::RefPtr cr, cr->rectangle(x, 1, width, 100-2); cr->clip(); - cr->move_to(x + 3, 15); - cr->set_source_rgb(1.0, 1.0, 1.0); - Cairo::RefPtr font = - Cairo::ToyFontFace::create("Bitstream Charter", - Cairo::FONT_SLANT_NORMAL, - Cairo::FONT_WEIGHT_NORMAL); - cr->set_font_face(font); - cr->set_font_size(11); - cr->show_text("Clip Name"); // TODO: get clip name from model + cr->move_to (x + 3, 12); + cr->set_source_rgb (1.0, 1.0, 1.0); + + cr->set_font_size (9); + cr->show_text ("Clip Name"); // TODO: get clip name from model // TODO: Show thumbnails for clip } From 86c7003d6dca3dbea013bcc3b68c6d6189888d41 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Dec 2010 22:19:09 +0100 Subject: [PATCH 28/30] Commit CairoUtil class forgotten in commit 60ccdd. --- src/gui/util/cairo-util.cpp | 81 +++++++++++++++++++++++++++++++++++++ src/gui/util/cairo-util.hpp | 73 +++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 src/gui/util/cairo-util.cpp create mode 100644 src/gui/util/cairo-util.hpp diff --git a/src/gui/util/cairo-util.cpp b/src/gui/util/cairo-util.cpp new file mode 100644 index 000000000..d9559cd82 --- /dev/null +++ b/src/gui/util/cairo-util.cpp @@ -0,0 +1,81 @@ +/* + cairo-util.cpp - Defines utility functions for Cairo + + Copyright (C) Lumiera.org + 2010, Stefan Kangas + + 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 "cairo-util.hpp" + +namespace gui { +namespace util { + + RefPtr + CairoUtil::pattern_set_red (const RefPtr color, double red) + { + double old_red; + double blue; + double green; + double alpha; + + color->get_rgba (old_red, blue, green, alpha); + + return Cairo::SolidPattern::create_rgba (red, blue, green, alpha); + } + + RefPtr + CairoUtil::pattern_set_green (const RefPtr color, double blue) + { + double red; + double old_blue; + double green; + double alpha; + + color->get_rgba (red, old_blue, green, alpha); + + return Cairo::SolidPattern::create_rgba (red, blue, green, alpha); + } + + RefPtr + CairoUtil::pattern_set_blue (const RefPtr color, double green) + { + double red; + double blue; + double old_green; + double alpha; + + color->get_rgba (red, blue, old_green, alpha); + + return Cairo::SolidPattern::create_rgba (red, blue, green, alpha); + } + + RefPtr + CairoUtil::pattern_set_alpha (const RefPtr color, double alpha) + { + double red; + double blue; + double green; + double old_alpha; + + color->get_rgba (red, blue, green, old_alpha); + + return Cairo::SolidPattern::create_rgba (red, blue, green, alpha); + } + +} // namespace util +} // namespace gui diff --git a/src/gui/util/cairo-util.hpp b/src/gui/util/cairo-util.hpp new file mode 100644 index 000000000..999e728ea --- /dev/null +++ b/src/gui/util/cairo-util.hpp @@ -0,0 +1,73 @@ +/* + cairo-util.hpp - Declares utility functions for Cairo + + Copyright (C) Lumiera.org + 2010, Stefan Kangas + + 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 + +#ifndef UTIL_CAIRO_HPP +#define UTIL_CAIRO_HPP + +using Cairo::RefPtr; +using Cairo::SolidPattern; + +namespace gui { +namespace util { + + class CairoUtil + { + public: + /** + * Make a new SolidPattern from an old one, changing the red component of the color. + * @param The new value for the red component of the color. + * @return The new pattern. + */ + static RefPtr + pattern_set_red (const RefPtr color, double red); + + /** + * Make a new SolidPattern from an old one, changing the green component of the color. + * @param The new value for the green component of the color. + * @return The new pattern. + */ + static RefPtr + pattern_set_green (const RefPtr, double green); + + /** + * Make a new SolidPattern from an old one, changing the blue component of the color. + * @param The new value for the blue component of the color. + * @return The new pattern. + */ + static RefPtr + pattern_set_blue (const RefPtr, double blue); + + /** + * Make a new SolidPattern from an old one, changing the alpha component of the color. + * @param The new value for the alpha component of the color. + * @return The new pattern. + */ + static RefPtr + pattern_set_alpha (const RefPtr, double alpha); + }; + +} // namespace util +} // namespace gui + +#endif From bdb9832f29b34efcb0dd3704aa78f859a35f9547 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 6 Dec 2010 14:18:53 +0100 Subject: [PATCH 29/30] Rename "Resources" to "Assets" --- .../outerSpace/lumiera_from_outer_space.txt | 2 -- icons/Makefile.am | 14 +++++++------- .../{panel-resources.png => panel-assets.png} | Bin .../{panel-resources.png => panel-assets.png} | Bin .../{panel-resources.png => panel-assets.png} | Bin src/gui/Makefile.am | 4 ++-- .../{resources-panel.cpp => assets-panel.cpp} | 12 ++++++------ .../{resources-panel.hpp => assets-panel.hpp} | 4 ++-- src/gui/window-manager.cpp | 2 +- src/gui/workspace/actions.cpp | 16 ++++++++-------- src/gui/workspace/actions.hpp | 2 +- src/gui/workspace/panel-manager.cpp | 10 +++++----- src/gui/workspace/workspace-window.hpp | 2 +- 13 files changed, 33 insertions(+), 35 deletions(-) rename icons/prerendered/16x16/{panel-resources.png => panel-assets.png} (100%) rename icons/prerendered/22x22/{panel-resources.png => panel-assets.png} (100%) rename icons/prerendered/32x32/{panel-resources.png => panel-assets.png} (100%) rename src/gui/panels/{resources-panel.cpp => assets-panel.cpp} (86%) rename src/gui/panels/{resources-panel.hpp => assets-panel.hpp} (95%) diff --git a/doc/user/outerSpace/lumiera_from_outer_space.txt b/doc/user/outerSpace/lumiera_from_outer_space.txt index 26d0bce67..397647a7d 100644 --- a/doc/user/outerSpace/lumiera_from_outer_space.txt +++ b/doc/user/outerSpace/lumiera_from_outer_space.txt @@ -248,8 +248,6 @@ Timeline View Asset View ~~~~~~~~~~ -// currently named 'resources' should be renamed to 'assets' - // Manages all assets available in one project. // * source media/footage/soundfiles // * prepared clips, known subprojects diff --git a/icons/Makefile.am b/icons/Makefile.am index 8bffefd44..0f34d924b 100644 --- a/icons/Makefile.am +++ b/icons/Makefile.am @@ -40,7 +40,7 @@ icons = \ $(16x16)/track-enabled.png \ $(16x16)/track-locked.png \ $(16x16)/track-unlocked.png \ - $(16x16)/panel-resources.png $(22x22)/panel-resources.png $(32x32)/panel-resources.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 @@ -79,12 +79,12 @@ $(16x16)/track-unlocked.png : $(svgdir)/track-unlocked.svg $(top_builddir)/rsvg- # Panels -$(16x16)/panel-resources.png: $(16x16pre)/panel-resources.png - cp $(16x16pre)/panel-resources.png $(16x16) -$(22x22)/panel-resources.png: $(22x22pre)/panel-resources.png - cp $(22x22pre)/panel-resources.png $(22x22) -$(32x32)/panel-resources.png: $(32x32pre)/panel-resources.png - cp $(32x32pre)/panel-resources.png $(32x32) +$(16x16)/panel-assets.png: $(16x16pre)/panel-assets.png + cp $(16x16pre)/panel-assets.png $(16x16) +$(22x22)/panel-assets.png: $(22x22pre)/panel-assets.png + cp $(22x22pre)/panel-assets.png $(22x22) +$(32x32)/panel-assets.png: $(32x32pre)/panel-assets.png + cp $(32x32pre)/panel-assets.png $(32x32) $(16x16)/panel-timeline.png: $(16x16pre)/panel-timeline.png cp $(16x16pre)/panel-timeline.png $(16x16) diff --git a/icons/prerendered/16x16/panel-resources.png b/icons/prerendered/16x16/panel-assets.png similarity index 100% rename from icons/prerendered/16x16/panel-resources.png rename to icons/prerendered/16x16/panel-assets.png diff --git a/icons/prerendered/22x22/panel-resources.png b/icons/prerendered/22x22/panel-assets.png similarity index 100% rename from icons/prerendered/22x22/panel-resources.png rename to icons/prerendered/22x22/panel-assets.png diff --git a/icons/prerendered/32x32/panel-resources.png b/icons/prerendered/32x32/panel-assets.png similarity index 100% rename from icons/prerendered/32x32/panel-resources.png rename to icons/prerendered/32x32/panel-assets.png diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index f47509758..a63f5d1db 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -89,8 +89,8 @@ gtk_gui_la_SOURCES = \ $(lumigui_srcdir)/output/xvdisplayer.hpp \ $(lumigui_srcdir)/panels/panel.cpp \ $(lumigui_srcdir)/panels/panel.hpp \ - $(lumigui_srcdir)/panels/resources-panel.cpp \ - $(lumigui_srcdir)/panels/resources-panel.hpp \ + $(lumigui_srcdir)/panels/assets-panel.cpp \ + $(lumigui_srcdir)/panels/assets-panel.hpp \ $(lumigui_srcdir)/panels/timeline-panel.cpp \ $(lumigui_srcdir)/panels/timeline-panel.hpp \ $(lumigui_srcdir)/panels/viewer-panel.cpp \ diff --git a/src/gui/panels/resources-panel.cpp b/src/gui/panels/assets-panel.cpp similarity index 86% rename from src/gui/panels/resources-panel.cpp rename to src/gui/panels/assets-panel.cpp index bd37cf195..45d4887ee 100644 --- a/src/gui/panels/resources-panel.cpp +++ b/src/gui/panels/assets-panel.cpp @@ -21,12 +21,12 @@ * *****************************************************/ #include "../gtk-lumiera.hpp" -#include "resources-panel.hpp" +#include "assets-panel.hpp" namespace gui { namespace panels { -ResourcesPanel::ResourcesPanel(workspace::PanelManager &panel_manager, +AssetsPanel::AssetsPanel(workspace::PanelManager &panel_manager, GdlDockItem *dock_item) : Panel(panel_manager, dock_item, get_title(), get_stock_id()) { @@ -39,15 +39,15 @@ ResourcesPanel::ResourcesPanel(workspace::PanelManager &panel_manager, } const char* -ResourcesPanel::get_title() +AssetsPanel::get_title() { - return _("Resources"); + return _("Assets"); } const gchar* -ResourcesPanel::get_stock_id() +AssetsPanel::get_stock_id() { - return "panel_resources"; + return "panel_assets"; } } // namespace panels diff --git a/src/gui/panels/resources-panel.hpp b/src/gui/panels/assets-panel.hpp similarity index 95% rename from src/gui/panels/resources-panel.hpp rename to src/gui/panels/assets-panel.hpp index 20021a920..e293c1f36 100644 --- a/src/gui/panels/resources-panel.hpp +++ b/src/gui/panels/assets-panel.hpp @@ -31,7 +31,7 @@ namespace gui { namespace panels { -class ResourcesPanel : public Panel +class AssetsPanel : public Panel { public: /** @@ -39,7 +39,7 @@ public: * @param panel_manager The owner panel manager widget. * @param dock_item The GdlDockItem that will host this panel. **/ - ResourcesPanel(workspace::PanelManager &panel_manager, + AssetsPanel(workspace::PanelManager &panel_manager, GdlDockItem *dock_item); /** diff --git a/src/gui/window-manager.cpp b/src/gui/window-manager.cpp index 52d466286..44c550215 100644 --- a/src/gui/window-manager.cpp +++ b/src/gui/window-manager.cpp @@ -177,7 +177,7 @@ WindowManager::register_stock_items() { Glib::RefPtr factory = IconFactory::create(); - add_stock_icon_set(factory, "panel-resources", "panel_resources", _("_Resources")); + add_stock_icon_set(factory, "panel-assets", "panel_assets", _("_Assets")); add_stock_icon_set(factory, "panel-timeline", "panel_timeline", _("_Timeline")); add_stock_icon_set(factory, "panel-viewer", "panel_viewer", _("_Viewer")); diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index c52ca36ec..2c8e205da 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -90,10 +90,10 @@ Actions::populate_main_actions(Glib::RefPtr uiManager) // View Menu actionGroup->add(Action::create("ViewMenu", _("_View"))); - assetsPanelAction = ToggleAction::create("ViewResources", - StockID("panel_resources")); + assetsPanelAction = ToggleAction::create("ViewAssets", + StockID("panel_assets")); assetsPanelAction->signal_toggled().connect( - mem_fun(*this, &Actions::on_menu_view_resources)); + mem_fun(*this, &Actions::on_menu_view_assets)); actionGroup->add(assetsPanelAction); timelinePanelAction = ToggleAction::create("ViewTimeline", @@ -160,7 +160,7 @@ Actions::populate_main_actions(Glib::RefPtr uiManager) " " "
" " " - " " + " " " " " " " " @@ -234,13 +234,13 @@ Actions::populate_show_panel_actions(Glib::RefPtr uiManager) void Actions::update_action_state() { - /*REQUIRE(workspaceWindow.resourcesPanel != NULL); + /*REQUIRE(workspaceWindow.assetsPanel != NULL); REQUIRE(workspaceWindow.timelinePanel != NULL); REQUIRE(workspaceWindow.viewerPanel != NULL); is_updating_action_state = true; assetsPanelAction->set_active( - workspaceWindow.resourcesPanel->is_shown()); + workspaceWindow.assetsPanel->is_shown()); timelinePanelAction->set_active( workspaceWindow.timelinePanel->is_shown()); viewerPanelAction->set_active( @@ -289,10 +289,10 @@ Actions::on_menu_edit_preferences() /* ===== View Menu Event Handlers ===== */ void -Actions::on_menu_view_resources() +Actions::on_menu_view_assets() { //if(!is_updating_action_state) - // workspaceWindow.resourcesPanel->show( + // workspaceWindow.assetsPanel->show( // assetsPanelAction->get_active()); } diff --git a/src/gui/workspace/actions.hpp b/src/gui/workspace/actions.hpp index f4f72c1ec..e60557b3f 100644 --- a/src/gui/workspace/actions.hpp +++ b/src/gui/workspace/actions.hpp @@ -84,7 +84,7 @@ private: void on_menu_edit_preferences(); - void on_menu_view_resources(); + void on_menu_view_assets(); void on_menu_view_timeline(); void on_menu_view_viewer(); diff --git a/src/gui/workspace/panel-manager.cpp b/src/gui/workspace/panel-manager.cpp index 3cabe8f45..4df663ba2 100644 --- a/src/gui/workspace/panel-manager.cpp +++ b/src/gui/workspace/panel-manager.cpp @@ -22,7 +22,7 @@ #include "panel-manager.hpp" -#include "../panels/resources-panel.hpp" +#include "../panels/assets-panel.hpp" #include "../panels/viewer-panel.hpp" #include "../panels/timeline-panel.hpp" @@ -39,7 +39,7 @@ const PanelManager::PanelDescription PanelManager::panelDescriptionList[] = { PanelManager::Panel(), PanelManager::Panel(), - PanelManager::Panel() + PanelManager::Panel() }; unsigned short PanelManager::panelID = 0; @@ -219,15 +219,15 @@ PanelManager::get_panel_title(int index) void PanelManager::create_panels() { - panels::Panel* resourcesPanel = - create_panel_by_name("ResourcesPanel"); + panels::Panel* assetsPanel = + create_panel_by_name("AssetsPanel"); panels::Panel* viewerPanel = create_panel_by_name("ViewerPanel"); panels::Panel* timelinePanel = create_panel_by_name("TimelinePanel"); gdl_dock_add_item(dock, - resourcesPanel->get_dock_item(), GDL_DOCK_LEFT); + assetsPanel->get_dock_item(), GDL_DOCK_LEFT); gdl_dock_add_item(dock, timelinePanel->get_dock_item(), GDL_DOCK_BOTTOM); gdl_dock_add_item(dock, diff --git a/src/gui/workspace/workspace-window.hpp b/src/gui/workspace/workspace-window.hpp index 6836882bf..38ddab9f9 100644 --- a/src/gui/workspace/workspace-window.hpp +++ b/src/gui/workspace/workspace-window.hpp @@ -34,7 +34,7 @@ #include "actions.hpp" #include "panel-manager.hpp" -#include "../panels/resources-panel.hpp" +#include "../panels/assets-panel.hpp" #include "../panels/viewer-panel.hpp" #include "../panels/timeline-panel.hpp" From 784b094fa7c415d062b0667e48e8f8f89e92bdda Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 26 Dec 2010 23:00:34 +0100 Subject: [PATCH 30/30] fix compilation problems with draft code --- src/lib/time/timevalue.hpp | 49 ++++++++++++----------- tests/lib/time/time-formats-test.cpp | 8 ++-- tests/lib/time/time-quantisation-test.cpp | 8 ++-- tests/lib/time/time-value-test.cpp | 6 +-- 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp index 6f4eb0427..58095f85e 100644 --- a/src/lib/time/timevalue.hpp +++ b/src/lib/time/timevalue.hpp @@ -36,6 +36,8 @@ extern "C" { namespace lib { namespace time { + using lumiera::Time; + /** * fixed format time specification. @@ -46,6 +48,7 @@ namespace time { : boost::totally_ordered > { + protected: gavl_time_t t_; public: @@ -62,11 +65,11 @@ namespace time { operator gavl_time_t () const { return t_; } // Supporting totally_ordered - friend bool operator< (Time const& t1, Time const& t2) { return t1.t_ < t2.t_; } - friend bool operator< (Time const& t1, gavl_time_t t2) { return t1.t_ < t2 ; } - friend bool operator> (Time const& t1, gavl_time_t t2) { return t1.t_ > t2 ; } - friend bool operator== (Time const& t1, Time const& t2) { return t1.t_ == t2.t_; } - friend bool operator== (Time const& t1, gavl_time_t t2) { return t1.t_ == t2 ; } + friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; } + friend bool operator< (TimeValue const& t1, gavl_time_t t2) { return t1.t_ < t2 ; } + friend bool operator> (TimeValue const& t1, gavl_time_t t2) { return t1.t_ > t2 ; } + friend bool operator== (TimeValue const& t1, TimeValue const& t2) { return t1.t_ == t2.t_; } + friend bool operator== (TimeValue const& t1, gavl_time_t t2) { return t1.t_ == t2 ; } }; @@ -97,21 +100,21 @@ namespace time { /** * Lumiera's internal time value datatype */ - class Time - : public TimeValue - { - public: - explicit - Time (TimeValue val=0) - : TimeValue(val) - { } - - Time ( long millis - , uint secs - , uint mins =0 - , uint hours=0 - ); - }; +//class Time +// : public TimeValue +// { +// public: +// explicit +// Time (TimeValue val=0) +// : TimeValue(val) +// { } +// +// Time ( long millis +// , uint secs +// , uint mins =0 +// , uint hours=0 +// ); +// }; class Offset @@ -128,9 +131,9 @@ namespace time { inline Offset operator- (Time const& end, Time const& start) { - TimeVar distance(end); - distance -= start; - return Offset(distance); +// TimeVar distance(end); +// distance -= start; +// return Offset(distance); } typedef const Offset TimeDistance; diff --git a/tests/lib/time/time-formats-test.cpp b/tests/lib/time/time-formats-test.cpp index 5a60473ae..ac9a52c5d 100644 --- a/tests/lib/time/time-formats-test.cpp +++ b/tests/lib/time/time-formats-test.cpp @@ -25,12 +25,12 @@ #include "lib/time/timecode.hpp" #include "lib/util.hpp" -//#include +#include //#include //#include -//using boost::lexical_cast; -//using util::isnil; +using boost::lexical_cast; +using util::isnil; //using std::rand; //using std::cout; //using std::endl; @@ -40,6 +40,8 @@ namespace lib { namespace time{ namespace test{ + using lumiera::Time; + /******************************************************** * @test verify handling of grid aligned timecode values. diff --git a/tests/lib/time/time-quantisation-test.cpp b/tests/lib/time/time-quantisation-test.cpp index 5e6660e2d..ac3dd9393 100644 --- a/tests/lib/time/time-quantisation-test.cpp +++ b/tests/lib/time/time-quantisation-test.cpp @@ -25,12 +25,12 @@ #include "lib/time/quantiser.hpp" #include "lib/util.hpp" -//#include +#include //#include //#include -//using boost::lexical_cast; -//using util::isnil; +using boost::lexical_cast; +using util::isnil; //using std::rand; //using std::cout; //using std::endl; @@ -40,6 +40,8 @@ namespace lib { namespace time{ namespace test{ + using lumiera::Time; + /******************************************************** * @test verify handling of time values, time intervals. diff --git a/tests/lib/time/time-value-test.cpp b/tests/lib/time/time-value-test.cpp index b40ca5189..e9e602d17 100644 --- a/tests/lib/time/time-value-test.cpp +++ b/tests/lib/time/time-value-test.cpp @@ -25,12 +25,12 @@ #include "lib/time/timevalue.hpp" #include "lib/util.hpp" -//#include +#include //#include //#include -//using boost::lexical_cast; -//using util::isnil; +using boost::lexical_cast; +using util::isnil; //using std::rand; //using std::cout; //using std::endl;