From 0b5fb555b6a3878926bac0844fd8b3db1b1e99c7 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Thu, 15 Jan 2009 18:54:13 +0000 Subject: [PATCH 01/11] Added dragging of whole branches --- .../timeline/timeline-layout-helper.cpp | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-layout-helper.cpp b/src/gui/widgets/timeline/timeline-layout-helper.cpp index 4efb2cf2a..2d5f1d22b 100644 --- a/src/gui/widgets/timeline/timeline-layout-helper.cpp +++ b/src/gui/widgets/timeline/timeline-layout-helper.cpp @@ -243,24 +243,28 @@ TimelineLayoutHelper::layout_headers_recursive( REQUIRE(depth >= 0); int child_offset = 0; - + TrackTree::sibling_iterator iterator; for(iterator = layoutTree.begin(parent_iterator); iterator != layoutTree.end(parent_iterator); iterator++) { Gdk::Rectangle rect; + int track_height = 0; + const shared_ptr &model_track = *iterator; REQUIRE(model_track); - shared_ptr timeline_track = lookup_timeline_track(model_track); + + const bool being_dragged = (timeline_track == draggingTrack); // Is the track going to be shown? if(parent_expanded) { // Calculate and store the box of the header - const int track_height = timeline_track->get_height(); + track_height = timeline_track->get_height() + + TimelineWidget::TrackPadding; const int indent = depth * indent_width; rect = Gdk::Rectangle( @@ -270,19 +274,15 @@ TimelineLayoutHelper::layout_headers_recursive( track_height); // height // Offset for the next header - child_offset += track_height + TimelineWidget::TrackPadding; + child_offset += track_height; // Is this header being dragged? - if(timeline_track == draggingTrack) - { - rect.set_y(dragPoint.get_y() - dragStartOffset.get_y()); - } + if(being_dragged) + rect.set_y(dragPoint.get_y() - dragStartOffset.get_y()); headerBoxes[timeline_track] = rect; } - - // Is the track animating? const bool is_track_animating = timeline_track->is_expand_animating(); @@ -292,10 +292,11 @@ TimelineLayoutHelper::layout_headers_recursive( const bool expand_child = (animating || timeline_track->get_expanded()) && parent_expanded; - + int child_branch_height = layout_headers_recursive( - iterator, branch_offset + child_offset, - header_width, indent_width, depth + 1, expand_child); + iterator, rect.get_y() + track_height, + header_width, indent_width, depth + 1, + expand_child); // Do collapse animation as necessary if(is_track_animating) From c9d269872e6e1fbaa946cae7efb99c6a23f0cc30 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Thu, 15 Jan 2009 18:57:58 +0000 Subject: [PATCH 02/11] Fixed a bug with dragging when the timeline is scrolled down --- src/gui/widgets/timeline/timeline-layout-helper.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-layout-helper.cpp b/src/gui/widgets/timeline/timeline-layout-helper.cpp index 2d5f1d22b..a47097854 100644 --- a/src/gui/widgets/timeline/timeline-layout-helper.cpp +++ b/src/gui/widgets/timeline/timeline-layout-helper.cpp @@ -139,7 +139,8 @@ TimelineLayoutHelper::begin_dragging_track( const Gdk::Rectangle &rect = headerBoxes[draggingTrack]; dragStartOffset = Gdk::Point( mouse_point.get_x() - rect.get_x(), - mouse_point.get_y() - rect.get_y()); + mouse_point.get_y() - rect.get_y() + + timelineWidget.get_y_scroll_offset()); // Find the track in the tree const shared_ptr model_track = @@ -187,7 +188,7 @@ TimelineLayoutHelper::drag_to_point(const Gdk::Point &point) const weak_ptr track = lookup_timeline_track(*iterator); - if(util::pt_in_rect(point, headerBoxes[track])) + if(util::pt_in_rect(dragPoint, headerBoxes[track])) { // Relocate the header draggingTrackIter = layoutTree.move_after( From 7a939e5d872244000da5dde5899de01c9b71a437 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 17 Jan 2009 11:09:44 +0000 Subject: [PATCH 03/11] Added header dragging scroll slide animation --- src/gui/widgets/timeline-widget.cpp | 6 +++ src/gui/widgets/timeline-widget.hpp | 2 + .../timeline/timeline-header-container.cpp | 53 +++++++++++++++++++ .../timeline/timeline-header-container.hpp | 48 +++++++++++++++++ 4 files changed, 109 insertions(+) diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 9859a3def..0e589bba0 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -484,6 +484,12 @@ TimelineWidget::get_y_scroll_offset() const return (int)verticalAdjustment.get_value(); } +void +TimelineWidget::set_y_scroll_offset(const int offset) +{ + verticalAdjustment.set_value(offset); +} + bool TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event) { diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index b95073230..7113d100f 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -226,6 +226,8 @@ private: int get_y_scroll_offset() const; + void set_y_scroll_offset(const int offset); + // ----- Event Handlers -----// /** diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index 172c130d6..1c552182b 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -36,6 +36,13 @@ using namespace util; namespace gui { namespace widgets { namespace timeline { + +// ===== Constants ===== // + +const int TimelineHeaderContainer::ScrollSlideRateDivisor = 4; +const int TimelineHeaderContainer::ScrollSlideEventInterval = 40; + +// ===== Implementation ===== // TimelineHeaderContainer::TimelineHeaderContainer( gui::widgets::TimelineWidget &timeline_widget) : @@ -208,7 +215,19 @@ bool TimelineHeaderContainer::on_motion_notify_event ( // Are we currently dragging? if(layout.get_dragging_track()) { + // Forward the message to the layout manager layout.drag_to_point(mousePoint); + + // Is the mouse out of bounds? if so we must begin scrolling + const int height = get_allocation().get_height(); + const int y = mousePoint.get_y(); + + if(y < 0) + begin_scroll_slide(y / ScrollSlideRateDivisor); + else if(y > height) + begin_scroll_slide((y - height) / ScrollSlideRateDivisor); + else end_scroll_slide(); + return result; } @@ -304,6 +323,22 @@ TimelineHeaderContainer::on_hovering_track_changed( } + +bool +TimelineHeaderContainer::on_scroll_slide_timer() +{ + // Shift the view + const int view_height = get_allocation().get_height(); + timelineWidget.set_y_scroll_offset( + timelineWidget.get_y_scroll_offset() + + scrollSlideRate * view_height / 256); + + // Keep the layout manager updated + timelineWidget.layoutHelper.drag_to_point(mousePoint); + + // Return true to keep the timer going + return true; +} void TimelineHeaderContainer::layout_headers() @@ -365,6 +400,24 @@ TimelineHeaderContainer::lookup_timeline_track( return timeline_track; } +void +TimelineHeaderContainer::begin_scroll_slide(int scroll_slide_rate) +{ + scrollSlideRate = scroll_slide_rate; + if(!scrollSlideEvent.connected()) + scrollSlideEvent = Glib::signal_timeout().connect(sigc::mem_fun( + this, &TimelineHeaderContainer::on_scroll_slide_timer), + ScrollSlideEventInterval); +} + +void +TimelineHeaderContainer::end_scroll_slide() +{ + scrollSlideRate = 0; + if(scrollSlideEvent.connected()) + scrollSlideEvent.disconnect(); +} + } // namespace timeline } // namespace widgets } // namespace gui diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index 6526244c3..9caefecee 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -139,6 +139,15 @@ private: void on_hovering_track_changed( boost::shared_ptr hovering_track); +private: + /* ===== Internal Event Handlers ===== */ + + /** + * An internal event handler, which is called when the scroll slide + * timer calls it. + */ + bool on_scroll_slide_timer(); + /* ===== Internals ===== */ private: @@ -172,6 +181,18 @@ private: **/ boost::shared_ptr lookup_timeline_track( boost::shared_ptr model_track); + + /** + * Begins, or continues a scroll slide at a given rate + * @param scroll_slide_rate The distance to slide every timer event + * in units of 1/256th of the view height. + */ + void begin_scroll_slide(int scroll_slide_rate); + + /** + * Ends a scroll slide, and disconnects the slide timer + */ + void end_scroll_slide(); private: @@ -195,11 +216,38 @@ private: * click is not processed by track headers. **/ Gtk::Menu contextMenu; + + /** + * This connection is used to represent the timer which causes scroll + * sliding to occur. + * @remarks Scroll sliding is an animated scroll which occurs when + * the user drags a header outside the area of the timeline body. + */ + sigc::connection scrollSlideEvent; + + /** + * Specifies the rate at which scroll sliding is currently taking + * place. + */ + int scrollSlideRate; //----- User Interaction State -----// boost::shared_ptr hoveringTrack; Gdk::Point mousePoint; + + /* ===== Constants ===== */ + /** + * The amount to divide the mouse overshoot by to produce the slide + * scroll rate. + * @remarks Smaller values cause faster scrolling. + */ + static const int ScrollSlideRateDivisor; + + /** + * The interval between scroll slide events in ms. + */ + static const int ScrollSlideEventInterval; friend class gui::widgets::TimelineWidget; friend class timeline::Track; From 47296381a834561e526738be3bee78aeabb92d51 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 17 Jan 2009 15:05:19 +0000 Subject: [PATCH 04/11] WIP: Added keep-above code --- .../timeline/timeline-header-container.cpp | 64 ++++++++++++++++++- .../timeline/timeline-header-container.hpp | 10 +++ .../timeline/timeline-layout-helper.cpp | 32 ++++++---- .../timeline/timeline-layout-helper.hpp | 13 +++- 4 files changed, 104 insertions(+), 15 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index 1c552182b..4041ab554 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -183,7 +183,7 @@ bool TimelineHeaderContainer::on_button_release_event ( // Has the user been dragging? if(layout.get_dragging_track()) - layout.end_dragging_track(); + end_drag(); return Container::on_button_release_event(event); } @@ -208,7 +208,7 @@ bool TimelineHeaderContainer::on_motion_notify_event ( if((event->state & GDK_BUTTON1_MASK) && hoveringTrack && !layout.get_dragging_track()) { - layout.begin_dragging_track(mousePoint); + begin_drag(); return result; } @@ -400,6 +400,66 @@ TimelineHeaderContainer::lookup_timeline_track( return timeline_track; } +void +TimelineHeaderContainer::begin_drag() +{ + TimelineLayoutHelper &layout = timelineWidget.layoutHelper; + + shared_ptr dragging_track = + layout.begin_dragging_track(mousePoint); + ENSURE(dragging_track); // Something strange has happened if we + // were somehow not hovering on a track + + const TimelineLayoutHelper::TrackTree::pre_order_iterator node = + layout.iterator_from_track(dragging_track->get_model_track()); + set_keep_above_recursive(node, true); +} + +void +TimelineHeaderContainer::end_drag() +{ + TimelineLayoutHelper &layout = timelineWidget.layoutHelper; + + shared_ptr dragging_track = + layout.get_dragging_track(); + ENSURE(dragging_track); // Something strange has happened if we + // were somehow not dragging on a track + + const TimelineLayoutHelper::TrackTree::pre_order_iterator node = + layout.iterator_from_track(dragging_track->get_model_track()); + set_keep_above_recursive(node, false); + + layout.end_dragging_track(); +} + +void +TimelineHeaderContainer::set_keep_above_recursive( + TimelineLayoutHelper::TrackTree::iterator_base node, + const bool keep_above) +{ + TimelineLayoutHelper::TrackTree::pre_order_iterator iter; + + const TimelineLayoutHelper::TrackTree &layout_tree = + timelineWidget.layoutHelper.get_layout_tree(); + + shared_ptr timeline_track = + lookup_timeline_track(*node); + REQUIRE(timeline_track); + + Glib::RefPtr window = + timeline_track->get_header_widget().get_window(); + ENSURE(window); // Something strange has happened if there was no + // window + window->set_keep_above(keep_above); + + for(iter = layout_tree.begin(node); + iter != layout_tree.end(node); + iter++) + { + set_keep_above_recursive(iter, keep_above); + } +} + void TimelineHeaderContainer::begin_scroll_slide(int scroll_slide_rate) { diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index 9caefecee..4b2883d47 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -29,6 +29,7 @@ #define HEADER_CONTAINER_HPP #include "../../gtk-lumiera.hpp" +#include "timeline-layout-helper.hpp" namespace gui { @@ -182,6 +183,15 @@ private: boost::shared_ptr lookup_timeline_track( boost::shared_ptr model_track); + void begin_drag(); + + + void end_drag(); + + void set_keep_above_recursive( + TimelineLayoutHelper::TrackTree::iterator_base node, + const bool keep_above); + /** * Begins, or continues a scroll slide at a given rate * @param scroll_slide_rate The distance to slide every timer event diff --git a/src/gui/widgets/timeline/timeline-layout-helper.cpp b/src/gui/widgets/timeline/timeline-layout-helper.cpp index a47097854..dccd9d143 100644 --- a/src/gui/widgets/timeline/timeline-layout-helper.cpp +++ b/src/gui/widgets/timeline/timeline-layout-helper.cpp @@ -128,13 +128,13 @@ TimelineLayoutHelper::track_from_y(int y) return shared_ptr(); } -bool +shared_ptr TimelineLayoutHelper::begin_dragging_track( const Gdk::Point &mouse_point) { draggingTrack = header_from_point(mouse_point); if(!draggingTrack) - return false; + return shared_ptr(); const Gdk::Rectangle &rect = headerBoxes[draggingTrack]; dragStartOffset = Gdk::Point( @@ -142,19 +142,11 @@ TimelineLayoutHelper::begin_dragging_track( mouse_point.get_y() - rect.get_y() + timelineWidget.get_y_scroll_offset()); - // Find the track in the tree const shared_ptr model_track = draggingTrack->get_model_track(); - REQUIRE(model_track); - for(draggingTrackIter = layoutTree.begin(); - draggingTrackIter != layoutTree.end(); - draggingTrackIter++) - { - if(*draggingTrackIter == model_track) - break; - } + draggingTrackIter = iterator_from_track(model_track); - return true; + return draggingTrack; } void @@ -212,6 +204,22 @@ TimelineLayoutHelper::is_animating() const return animating; } +TimelineLayoutHelper::TrackTree::pre_order_iterator +TimelineLayoutHelper::iterator_from_track( + boost::shared_ptr model_track) +{ + REQUIRE(model_track); + + TrackTree::pre_order_iterator iter; + for(iter = layoutTree.begin(); iter != layoutTree.end(); iter++) + { + if(*iter == model_track) + break; + } + + return iter; +} + void TimelineLayoutHelper::update_layout() { diff --git a/src/gui/widgets/timeline/timeline-layout-helper.hpp b/src/gui/widgets/timeline/timeline-layout-helper.hpp index a93f88fa4..68f44939a 100644 --- a/src/gui/widgets/timeline/timeline-layout-helper.hpp +++ b/src/gui/widgets/timeline/timeline-layout-helper.hpp @@ -127,7 +127,8 @@ public: **/ boost::shared_ptr track_from_y(int y); - bool begin_dragging_track(const Gdk::Point &mouse_point); + boost::shared_ptr + begin_dragging_track(const Gdk::Point &mouse_point); void end_dragging_track(); @@ -144,6 +145,16 @@ public: int get_total_height() const; bool is_animating() const; + + /** + * A utility function which finds the iterator of a track in the + * layout tree. + * @param model_track The model track to look for. + * @return Returns the model iterator of layoutTree.end() if no + * iterator was found. + **/ + TrackTree::pre_order_iterator iterator_from_track( + boost::shared_ptr model_track); protected: From ebb552e32329395f7bc02b559e3397c4e85692bb Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 17 Jan 2009 15:38:39 +0000 Subject: [PATCH 05/11] Transitioned to references of project instead of pointers --- src/gui/gtk-lumiera.cpp | 2 +- src/gui/panels/assets-panel.cpp | 2 +- src/gui/panels/assets-panel.hpp | 2 +- src/gui/panels/panel.cpp | 6 ++---- src/gui/panels/panel.hpp | 6 +++--- src/gui/panels/timeline-panel.cpp | 6 +++--- src/gui/panels/timeline-panel.hpp | 2 +- src/gui/panels/viewer-panel.cpp | 2 +- src/gui/panels/viewer-panel.hpp | 2 +- src/gui/workspace/actions.cpp | 2 +- src/gui/workspace/workspace-window.cpp | 10 ++++------ src/gui/workspace/workspace-window.hpp | 6 +++--- 12 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index 9fd41b94e..feb73ea5b 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -65,7 +65,7 @@ GtkLumiera::main(int argc, char *argv[]) window_manager.set_theme("lumiera_ui.rc"); - WorkspaceWindow main_window(&project); + WorkspaceWindow main_window(project); kit.run(main_window); diff --git a/src/gui/panels/assets-panel.cpp b/src/gui/panels/assets-panel.cpp index 316ebf256..5ed878be8 100644 --- a/src/gui/panels/assets-panel.cpp +++ b/src/gui/panels/assets-panel.cpp @@ -26,7 +26,7 @@ namespace gui { namespace panels { -AssetsPanel::AssetsPanel(model::Project *const owner_project) : +AssetsPanel::AssetsPanel(model::Project &owner_project) : Panel(owner_project, "assets", _("Assets"), "panel_assets"), placeholder("Assets/Media") { diff --git a/src/gui/panels/assets-panel.hpp b/src/gui/panels/assets-panel.hpp index 05c473dca..4f815a78d 100644 --- a/src/gui/panels/assets-panel.hpp +++ b/src/gui/panels/assets-panel.hpp @@ -38,7 +38,7 @@ public: * Constructor * @param owner_project The project associated with this panel. **/ - AssetsPanel(model::Project *const owner_project); + AssetsPanel(model::Project &owner_project); protected: Gtk::Label placeholder; diff --git a/src/gui/panels/panel.cpp b/src/gui/panels/panel.cpp index 05fb096b1..49eb6cd47 100644 --- a/src/gui/panels/panel.cpp +++ b/src/gui/panels/panel.cpp @@ -26,12 +26,11 @@ namespace gui { namespace panels { -Panel::Panel(model::Project *const owner_project, +Panel::Panel(model::Project &owner_project, const gchar *name, const gchar *long_name, GdlDockItemBehavior behavior) : project(owner_project) { - REQUIRE(owner_project != NULL); REQUIRE(name != NULL); REQUIRE(long_name != NULL); @@ -42,12 +41,11 @@ Panel::Panel(model::Project *const owner_project, ENSURE(dock_item != NULL); } -Panel::Panel(model::Project *const owner_project, +Panel::Panel(model::Project &owner_project, const gchar *name, const gchar *long_name, const gchar *stock_id, GdlDockItemBehavior behavior) : project(owner_project) { - REQUIRE(owner_project != NULL); REQUIRE(name != NULL); REQUIRE(long_name != NULL); REQUIRE(stock_id != NULL); diff --git a/src/gui/panels/panel.hpp b/src/gui/panels/panel.hpp index 669a7a4f1..adc4f34ab 100644 --- a/src/gui/panels/panel.hpp +++ b/src/gui/panels/panel.hpp @@ -51,7 +51,7 @@ protected: * @param long_name The name to display on the caption * @param behavior The GDL behaviour of this item */ - Panel(model::Project *const owner_project, + Panel(model::Project &owner_project, const gchar *name, const gchar *long_name, GdlDockItemBehavior behavior = GDL_DOCK_ITEM_BEH_NORMAL); @@ -63,7 +63,7 @@ protected: * @param stock_id The id of the stock item to display on the caption * @param behavior The GDL behaviour of this item */ - Panel(model::Project *const owner_project, + Panel(model::Project &owner_project, const gchar *name, const gchar *long_name, const gchar *stock_id, GdlDockItemBehavior behavior = GDL_DOCK_ITEM_BEH_NORMAL); @@ -99,7 +99,7 @@ private: protected: - model::Project *const project; + model::Project &project; GdlDockItem* dock_item; }; diff --git a/src/gui/panels/timeline-panel.cpp b/src/gui/panels/timeline-panel.cpp index f1ca132d2..7b9e5fe06 100644 --- a/src/gui/panels/timeline-panel.cpp +++ b/src/gui/panels/timeline-panel.cpp @@ -43,7 +43,7 @@ namespace panels { const int TimelinePanel::ZoomToolSteps = 2; // 2 seems comfortable -TimelinePanel::TimelinePanel(model::Project *const owner_project) : +TimelinePanel::TimelinePanel(model::Project &owner_project) : Panel(owner_project, "timeline", _("Timeline"), "panel_timeline"), timeIndicator(), previousButton(Stock::MEDIA_PREVIOUS), @@ -65,7 +65,7 @@ TimelinePanel::TimelinePanel(model::Project *const owner_project) : // mem_fun(this, &TimelinePanel::on_playback_period_drag_released)); // Hook up notifications - project->get_sequences().signal_changed().connect( + project.get_sequences().signal_changed().connect( mem_fun(this, &TimelinePanel::on_sequence_list_changed)); // Setup the notebook @@ -223,7 +223,7 @@ TimelinePanel::update_notebook() old_pages.swap(notebook_pages); BOOST_FOREACH( shared_ptr< model::Sequence > sequence, - project->get_sequences() ) + project.get_sequences() ) { std::map >:: iterator iterator = old_pages.find(sequence.get()); diff --git a/src/gui/panels/timeline-panel.hpp b/src/gui/panels/timeline-panel.hpp index 846d675fe..48b00d551 100644 --- a/src/gui/panels/timeline-panel.hpp +++ b/src/gui/panels/timeline-panel.hpp @@ -50,7 +50,7 @@ public: * Constructor * @param owner_project The project associated with this panel. */ - TimelinePanel(model::Project *const owner_project); + TimelinePanel(model::Project &owner_project); /** diff --git a/src/gui/panels/viewer-panel.cpp b/src/gui/panels/viewer-panel.cpp index 070dd2d29..2e8de0e9b 100644 --- a/src/gui/panels/viewer-panel.cpp +++ b/src/gui/panels/viewer-panel.cpp @@ -29,7 +29,7 @@ using namespace Gtk; namespace gui { namespace panels { -ViewerPanel::ViewerPanel(model::Project *const owner_project) : +ViewerPanel::ViewerPanel(model::Project &owner_project) : Panel(owner_project, "viewer", _("Viewer"), "panel_viewer") { //----- Pack in the Widgets -----// diff --git a/src/gui/panels/viewer-panel.hpp b/src/gui/panels/viewer-panel.hpp index 027ab1fc2..30f37f284 100644 --- a/src/gui/panels/viewer-panel.hpp +++ b/src/gui/panels/viewer-panel.hpp @@ -44,7 +44,7 @@ public: * Contructor. @param owner_project The project associated with this panel. **/ - ViewerPanel(model::Project *const owner_project); + ViewerPanel(model::Project &owner_project); protected: diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index ed5a43002..2ac749528 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -188,7 +188,7 @@ Actions::on_menu_sequence_add() dialogs::NameChooser dialog(workspaceWindow, _("Add Sequence"), _("New Sequence")); if(dialog.run() == RESPONSE_OK) - workspaceWindow.get_project()->add_new_sequence(dialog.get_name()); + workspaceWindow.get_project().add_new_sequence(dialog.get_name()); } /* ===== Track Menu Event Handlers ===== */ diff --git a/src/gui/workspace/workspace-window.cpp b/src/gui/workspace/workspace-window.cpp index ee315e026..8b673a27a 100644 --- a/src/gui/workspace/workspace-window.cpp +++ b/src/gui/workspace/workspace-window.cpp @@ -41,12 +41,10 @@ using namespace gui::model; namespace gui { namespace workspace { -WorkspaceWindow::WorkspaceWindow(Project *source_project) : +WorkspaceWindow::WorkspaceWindow(Project &source_project) : project(source_project), actions(*this) -{ - REQUIRE(source_project != NULL); - +{ layout = NULL; assetsPanel = NULL; viewerPanel = NULL; @@ -68,8 +66,8 @@ WorkspaceWindow::~WorkspaceWindow() timelinePanel->unreference(); } -Project* -WorkspaceWindow::get_project() const +Project& +WorkspaceWindow::get_project() { return project; } diff --git a/src/gui/workspace/workspace-window.hpp b/src/gui/workspace/workspace-window.hpp index 91c16d642..69951a4b9 100644 --- a/src/gui/workspace/workspace-window.hpp +++ b/src/gui/workspace/workspace-window.hpp @@ -54,18 +54,18 @@ namespace workspace { class WorkspaceWindow : public Gtk::Window { public: - WorkspaceWindow(gui::model::Project *source_project); + WorkspaceWindow(gui::model::Project &source_project); ~WorkspaceWindow(); - gui::model::Project* get_project() const; + gui::model::Project& get_project(); private: void create_ui(); /* ===== Model ===== */ private: - gui::model::Project *project; + gui::model::Project &project; /* ===== UI ===== */ private: From d16623892202c0e6596ee8cff01e8b1fd7b98566 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 17 Jan 2009 16:12:11 +0000 Subject: [PATCH 06/11] Added the new controller classes --- src/gui/Makefile.am | 4 ++ src/gui/controller/controller.cpp | 41 ++++++++++++++++ src/gui/controller/controller.hpp | 56 ++++++++++++++++++++++ src/gui/controller/playback-controller.cpp | 39 +++++++++++++++ src/gui/controller/playback-controller.hpp | 46 ++++++++++++++++++ src/gui/gtk-lumiera.cpp | 5 +- src/gui/panels/assets-panel.cpp | 4 +- src/gui/panels/assets-panel.hpp | 7 +-- src/gui/panels/panel.cpp | 8 ++-- src/gui/panels/panel.hpp | 14 +++--- src/gui/panels/timeline-panel.cpp | 15 ++++-- src/gui/panels/timeline-panel.hpp | 5 +- src/gui/panels/viewer-panel.cpp | 4 +- src/gui/panels/viewer-panel.hpp | 4 +- src/gui/workspace/workspace-window.cpp | 17 +++++-- src/gui/workspace/workspace-window.hpp | 15 +++++- 16 files changed, 249 insertions(+), 35 deletions(-) create mode 100644 src/gui/controller/controller.cpp create mode 100644 src/gui/controller/controller.hpp create mode 100644 src/gui/controller/playback-controller.cpp create mode 100644 src/gui/controller/playback-controller.hpp diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index e46c1e78d..44a77c0c3 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -163,6 +163,10 @@ libgui_la_SOURCES = \ $(lumigui_srcdir)/model/sequence.hpp \ $(lumigui_srcdir)/model/clip.cpp \ $(lumigui_srcdir)/model/clip.hpp \ + $(lumigui_srcdir)/controller/controller.cpp \ + $(lumigui_srcdir)/controller/controller.hpp \ + $(lumigui_srcdir)/controller/playback-controller.cpp \ + $(lumigui_srcdir)/controller/playback-controller.hpp \ $(lumigui_srcdir)/output/displayer.cpp \ $(lumigui_srcdir)/output/displayer.hpp \ $(lumigui_srcdir)/output/gdkdisplayer.cpp \ diff --git a/src/gui/controller/controller.cpp b/src/gui/controller/controller.cpp new file mode 100644 index 000000000..2d7deefc9 --- /dev/null +++ b/src/gui/controller/controller.cpp @@ -0,0 +1,41 @@ +/* + controllerk.cpp - Implementation of the timeline track object + + Copyright (C) Lumiera.org + 2008, Joel Holdsworth + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + +#include "controller.hpp" + +namespace gui { +namespace controller { + +Controller::Controller(model::Project &model_project) : + project(model_project) +{ + +} + +PlaybackController& Controller::get_playback_controller() +{ + return playback; +} + +} // namespace controller +} // namespace gui + diff --git a/src/gui/controller/controller.hpp b/src/gui/controller/controller.hpp new file mode 100644 index 000000000..27f185e97 --- /dev/null +++ b/src/gui/controller/controller.hpp @@ -0,0 +1,56 @@ +/* + controller.hpp - Declaration of the controller object + + Copyright (C) Lumiera.org + 2009, Joel Holdsworth + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/** @file controller/controller.hpp + ** This file contains the definition of the controller object + */ + +#include "playback-controller.hpp" + +#ifndef CONTROLLER_HPP +#define CONTROLLER_HPP + +namespace gui { + +namespace model { +class Project; +} // namespace model + +namespace controller { + +class Controller +{ +public: + Controller(model::Project &model_project); + + PlaybackController& get_playback_controller(); + +private: + model::Project &project; + + PlaybackController playback; +}; + +} // namespace controller +} // namespace gui + +#endif // CONTROLLER_HPP + diff --git a/src/gui/controller/playback-controller.cpp b/src/gui/controller/playback-controller.cpp new file mode 100644 index 000000000..19f490f47 --- /dev/null +++ b/src/gui/controller/playback-controller.cpp @@ -0,0 +1,39 @@ +/* + timeline-track.cpp - Implementation of the timeline track object + + Copyright (C) Lumiera.org + 2008, Joel Holdsworth + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + +// !!! This header must soon be removed when we drop Etch compatibility +#include + +#include "playback-controller.hpp" + +namespace gui { +namespace controller { + +void +PlaybackController::play() +{ + g_message("Play"); +} + +} // namespace controller +} // namespace gui + diff --git a/src/gui/controller/playback-controller.hpp b/src/gui/controller/playback-controller.hpp new file mode 100644 index 000000000..61833206c --- /dev/null +++ b/src/gui/controller/playback-controller.hpp @@ -0,0 +1,46 @@ +/* + playback-controller.hpp - Declaration of the playback controller object + + Copyright (C) Lumiera.org + 2009, Joel Holdsworth + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/** @file controller/playback-controller.hpp + ** This file contains the definition of the playback controller object + */ + +#ifndef PLAYBACK_CONTROLLER_HPP +#define PLAYBACK_CONTROLLER_HPP + +namespace gui { +namespace controller { + +class PlaybackController +{ +public: + + void play(); + +private: + void pull_frame(); +}; + +} // namespace controller +} // namespace gui + +#endif // PLAYBACK_CONTROLLER_HPP + diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index feb73ea5b..a2147b72d 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -31,6 +31,7 @@ #include "window-manager.hpp" #include "workspace/workspace-window.hpp" #include "model/project.hpp" +#include "controller/controller.hpp" extern "C" { #include "common/interface.h" @@ -43,6 +44,7 @@ using namespace Glib; using namespace gui; using namespace gui::workspace; using namespace gui::model; +using namespace gui::controller; GtkLumiera the_application; @@ -61,11 +63,12 @@ GtkLumiera::main(int argc, char *argv[]) Glib::set_application_name(AppTitle); Project project; + Controller controller(project); WindowManager window_manager; window_manager.set_theme("lumiera_ui.rc"); - WorkspaceWindow main_window(project); + WorkspaceWindow main_window(project, controller); kit.run(main_window); diff --git a/src/gui/panels/assets-panel.cpp b/src/gui/panels/assets-panel.cpp index 5ed878be8..1e189c0fc 100644 --- a/src/gui/panels/assets-panel.cpp +++ b/src/gui/panels/assets-panel.cpp @@ -26,8 +26,8 @@ namespace gui { namespace panels { -AssetsPanel::AssetsPanel(model::Project &owner_project) : - Panel(owner_project, "assets", _("Assets"), "panel_assets"), +AssetsPanel::AssetsPanel(workspace::WorkspaceWindow &workspace_window) : + Panel(workspace_window, "assets", _("Assets"), "panel_assets"), placeholder("Assets/Media") { pack_start(placeholder); diff --git a/src/gui/panels/assets-panel.hpp b/src/gui/panels/assets-panel.hpp index 4f815a78d..33513243a 100644 --- a/src/gui/panels/assets-panel.hpp +++ b/src/gui/panels/assets-panel.hpp @@ -34,11 +34,12 @@ namespace panels { class AssetsPanel : public Panel { public: + /** - * Constructor - * @param owner_project The project associated with this panel. + * Contructor. + * @param workspace_window The window that owns this panel. **/ - AssetsPanel(model::Project &owner_project); + AssetsPanel(workspace::WorkspaceWindow &workspace_window); protected: Gtk::Label placeholder; diff --git a/src/gui/panels/panel.cpp b/src/gui/panels/panel.cpp index 49eb6cd47..aa600cafd 100644 --- a/src/gui/panels/panel.cpp +++ b/src/gui/panels/panel.cpp @@ -26,10 +26,10 @@ namespace gui { namespace panels { -Panel::Panel(model::Project &owner_project, +Panel::Panel(workspace::WorkspaceWindow &workspace_window, const gchar *name, const gchar *long_name, GdlDockItemBehavior behavior) : - project(owner_project) + workspace(workspace_window) { REQUIRE(name != NULL); REQUIRE(long_name != NULL); @@ -41,10 +41,10 @@ Panel::Panel(model::Project &owner_project, ENSURE(dock_item != NULL); } -Panel::Panel(model::Project &owner_project, +Panel::Panel(workspace::WorkspaceWindow &workspace_window, const gchar *name, const gchar *long_name, const gchar *stock_id, GdlDockItemBehavior behavior) : - project(owner_project) + workspace(workspace_window) { REQUIRE(name != NULL); REQUIRE(long_name != NULL); diff --git a/src/gui/panels/panel.hpp b/src/gui/panels/panel.hpp index adc4f34ab..941afa0b8 100644 --- a/src/gui/panels/panel.hpp +++ b/src/gui/panels/panel.hpp @@ -32,8 +32,8 @@ namespace gui { -namespace model { -class Project; +namespace workspace { +class WorkspaceWindow; } namespace panels { @@ -46,24 +46,24 @@ class Panel : public Gtk::VBox protected: /** * Constructs a panel object - * @param owner_project The project associated with this panel. + * @param workspace_window The window that owns this panel. * @param name The internal name of this panel * @param long_name The name to display on the caption * @param behavior The GDL behaviour of this item */ - Panel(model::Project &owner_project, + Panel(workspace::WorkspaceWindow &workspace_window, const gchar *name, const gchar *long_name, GdlDockItemBehavior behavior = GDL_DOCK_ITEM_BEH_NORMAL); /** * Constructs a panel object with a stock item for a caption - * @param owner_project The project associated with this panel. + * @param owner_window The window that owns this panel. * @param name The internal name of this panel * @param long_name The name to display on the caption * @param stock_id The id of the stock item to display on the caption * @param behavior The GDL behaviour of this item */ - Panel(model::Project &owner_project, + Panel(workspace::WorkspaceWindow &owner_window, const gchar *name, const gchar *long_name, const gchar *stock_id, GdlDockItemBehavior behavior = GDL_DOCK_ITEM_BEH_NORMAL); @@ -99,7 +99,7 @@ private: protected: - model::Project &project; + workspace::WorkspaceWindow &workspace; GdlDockItem* dock_item; }; diff --git a/src/gui/panels/timeline-panel.cpp b/src/gui/panels/timeline-panel.cpp index 7b9e5fe06..ea8215aaf 100644 --- a/src/gui/panels/timeline-panel.cpp +++ b/src/gui/panels/timeline-panel.cpp @@ -25,7 +25,9 @@ #include "../gtk-lumiera.hpp" #include "timeline-panel.hpp" +#include "../workspace/workspace-window.hpp" #include "../model/project.hpp" +#include "../controller/controller.hpp" extern "C" { #include "../../lib/time.h" @@ -43,8 +45,9 @@ namespace panels { const int TimelinePanel::ZoomToolSteps = 2; // 2 seems comfortable -TimelinePanel::TimelinePanel(model::Project &owner_project) : - Panel(owner_project, "timeline", _("Timeline"), "panel_timeline"), +TimelinePanel::TimelinePanel(workspace::WorkspaceWindow + &workspace_window) : + Panel(workspace_window, "timeline", _("Timeline"), "panel_timeline"), timeIndicator(), previousButton(Stock::MEDIA_PREVIOUS), rewindButton(Stock::MEDIA_REWIND), @@ -65,7 +68,7 @@ TimelinePanel::TimelinePanel(model::Project &owner_project) : // mem_fun(this, &TimelinePanel::on_playback_period_drag_released)); // Hook up notifications - project.get_sequences().signal_changed().connect( + workspace.get_project().get_sequences().signal_changed().connect( mem_fun(this, &TimelinePanel::on_sequence_list_changed)); // Setup the notebook @@ -119,7 +122,9 @@ TimelinePanel::~TimelinePanel() void TimelinePanel::on_play_pause() -{ +{ + workspace.get_controller().get_playback_controller().play(); + // TEST CODE! if(!is_playing()) { @@ -223,7 +228,7 @@ TimelinePanel::update_notebook() old_pages.swap(notebook_pages); BOOST_FOREACH( shared_ptr< model::Sequence > sequence, - project.get_sequences() ) + workspace.get_project().get_sequences() ) { std::map >:: iterator iterator = old_pages.find(sequence.get()); diff --git a/src/gui/panels/timeline-panel.hpp b/src/gui/panels/timeline-panel.hpp index 48b00d551..463130f5c 100644 --- a/src/gui/panels/timeline-panel.hpp +++ b/src/gui/panels/timeline-panel.hpp @@ -48,10 +48,9 @@ class TimelinePanel : public Panel public: /** * Constructor - * @param owner_project The project associated with this panel. + * @param workspace_window The window that owns this panel. */ - TimelinePanel(model::Project &owner_project); - + TimelinePanel(workspace::WorkspaceWindow &workspace_window); /** * Destructor diff --git a/src/gui/panels/viewer-panel.cpp b/src/gui/panels/viewer-panel.cpp index 2e8de0e9b..7f68b39f3 100644 --- a/src/gui/panels/viewer-panel.cpp +++ b/src/gui/panels/viewer-panel.cpp @@ -29,8 +29,8 @@ using namespace Gtk; namespace gui { namespace panels { -ViewerPanel::ViewerPanel(model::Project &owner_project) : - Panel(owner_project, "viewer", _("Viewer"), "panel_viewer") +ViewerPanel::ViewerPanel(workspace::WorkspaceWindow &workspace_window) : + Panel(workspace_window, "viewer", _("Viewer"), "panel_viewer") { //----- Pack in the Widgets -----// pack_start(display, PACK_EXPAND_WIDGET); diff --git a/src/gui/panels/viewer-panel.hpp b/src/gui/panels/viewer-panel.hpp index 30f37f284..a991014e9 100644 --- a/src/gui/panels/viewer-panel.hpp +++ b/src/gui/panels/viewer-panel.hpp @@ -42,9 +42,9 @@ class ViewerPanel : public Panel public: /** * Contructor. - @param owner_project The project associated with this panel. + * @param workspace_window The window that owns this panel. **/ - ViewerPanel(model::Project &owner_project); + ViewerPanel(workspace::WorkspaceWindow &owner_window); protected: diff --git a/src/gui/workspace/workspace-window.cpp b/src/gui/workspace/workspace-window.cpp index 8b673a27a..24557053d 100644 --- a/src/gui/workspace/workspace-window.cpp +++ b/src/gui/workspace/workspace-window.cpp @@ -37,12 +37,15 @@ using namespace Gtk; using namespace gui::model; +using namespace gui::controller; namespace gui { namespace workspace { -WorkspaceWindow::WorkspaceWindow(Project &source_project) : +WorkspaceWindow::WorkspaceWindow(Project &source_project, + gui::controller::Controller &source_controller) : project(source_project), + controller(source_controller), actions(*this) { layout = NULL; @@ -72,6 +75,12 @@ WorkspaceWindow::get_project() return project; } +Controller& +WorkspaceWindow::get_controller() +{ + return controller; +} + void WorkspaceWindow::create_ui() { @@ -150,11 +159,11 @@ WorkspaceWindow::create_ui() baseContainer.pack_start(*toolbar, Gtk::PACK_SHRINK); //----- Create the Panels -----// - assetsPanel = new AssetsPanel(project); + assetsPanel = new AssetsPanel(*this); ENSURE(assetsPanel != NULL); - viewerPanel = new ViewerPanel(project); + viewerPanel = new ViewerPanel(*this); ENSURE(viewerPanel != NULL); - timelinePanel = new TimelinePanel(project); + timelinePanel = new TimelinePanel(*this); ENSURE(timelinePanel != NULL); //----- Create the Dock -----// diff --git a/src/gui/workspace/workspace-window.hpp b/src/gui/workspace/workspace-window.hpp index 69951a4b9..fb0254d2d 100644 --- a/src/gui/workspace/workspace-window.hpp +++ b/src/gui/workspace/workspace-window.hpp @@ -46,6 +46,10 @@ namespace model { class Project; } // model +namespace controller { + class Controller; +} // model + namespace workspace { /** @@ -54,19 +58,26 @@ namespace workspace { class WorkspaceWindow : public Gtk::Window { public: - WorkspaceWindow(gui::model::Project &source_project); + WorkspaceWindow(gui::model::Project &source_project, + gui::controller::Controller &source_controller); ~WorkspaceWindow(); gui::model::Project& get_project(); + + gui::controller::Controller& get_controller(); private: void create_ui(); - + /* ===== Model ===== */ private: gui::model::Project &project; + /* ===== Controller ===== */ +private: + gui::controller::Controller &controller; + /* ===== UI ===== */ private: Glib::RefPtr uiManager; From d3f94730b5b07eab7ee0accd55ae024a06cd36a9 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 17 Jan 2009 16:17:42 +0000 Subject: [PATCH 07/11] Removed a spurious include --- src/gui/controller/playback-controller.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/gui/controller/playback-controller.cpp b/src/gui/controller/playback-controller.cpp index 19f490f47..8312be602 100644 --- a/src/gui/controller/playback-controller.cpp +++ b/src/gui/controller/playback-controller.cpp @@ -20,9 +20,6 @@ * *****************************************************/ -// !!! This header must soon be removed when we drop Etch compatibility -#include - #include "playback-controller.hpp" namespace gui { From ebe91793c5ff0974a9393bf4a9d1ddf674977de4 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 17 Jan 2009 16:53:01 +0000 Subject: [PATCH 08/11] WIP: Corrected some compile problems --- src/gui/controller/playback-controller.cpp | 11 +++++++++++ src/gui/controller/playback-controller.hpp | 3 +++ src/gui/gtk-lumiera.hpp | 1 + 3 files changed, 15 insertions(+) diff --git a/src/gui/controller/playback-controller.cpp b/src/gui/controller/playback-controller.cpp index 8312be602..a89036075 100644 --- a/src/gui/controller/playback-controller.cpp +++ b/src/gui/controller/playback-controller.cpp @@ -21,6 +21,7 @@ * *****************************************************/ #include "playback-controller.hpp" +#include "../gtk-lumiera.hpp" namespace gui { namespace controller { @@ -31,6 +32,16 @@ PlaybackController::play() g_message("Play"); } +void PlaybackController::playback_thread() +{ + pull_frame(); +} + +void PlaybackController::pull_frame() +{ + +} + } // namespace controller } // namespace gui diff --git a/src/gui/controller/playback-controller.hpp b/src/gui/controller/playback-controller.hpp index 61833206c..ea0f8dc96 100644 --- a/src/gui/controller/playback-controller.hpp +++ b/src/gui/controller/playback-controller.hpp @@ -36,6 +36,9 @@ public: void play(); private: + + void playback_thread(); + void pull_frame(); }; diff --git a/src/gui/gtk-lumiera.hpp b/src/gui/gtk-lumiera.hpp index a01bc5dc4..7f5a8cacd 100644 --- a/src/gui/gtk-lumiera.hpp +++ b/src/gui/gtk-lumiera.hpp @@ -37,6 +37,7 @@ #include #include #include "lib/util.hpp" +#include "backend/thread-wrapper.hpp" extern "C" { #include From 9197aa2ddf1d3f1e2463ef66a391d151522c384a Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 17 Jan 2009 17:37:06 +0000 Subject: [PATCH 09/11] WIP: PlaybackController can now push frames to the Viewer --- src/gui/controller/playback-controller.cpp | 13 ++++++++++++- src/gui/controller/playback-controller.hpp | 7 +++++++ src/gui/gtk-lumiera.hpp | 1 - src/gui/panels/viewer-panel.cpp | 21 ++++++++++++++++++++- src/gui/panels/viewer-panel.hpp | 4 ++++ src/gui/widgets/video-display-widget.cpp | 6 ++++++ src/gui/widgets/video-display-widget.hpp | 2 ++ 7 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/gui/controller/playback-controller.cpp b/src/gui/controller/playback-controller.cpp index a89036075..d69d3f7ce 100644 --- a/src/gui/controller/playback-controller.cpp +++ b/src/gui/controller/playback-controller.cpp @@ -29,7 +29,13 @@ namespace controller { void PlaybackController::play() { - g_message("Play"); + pull_frame(); +} + +void +PlaybackController::attach_viewer(const sigc::slot& on_frame) +{ + frame_signal.connect(on_frame); } void PlaybackController::playback_thread() @@ -39,7 +45,12 @@ void PlaybackController::playback_thread() void PlaybackController::pull_frame() { + unsigned char buffer[320 * 240 * 4]; + + for(int i = 0; i < 320*240*4; i++) + buffer[i] = rand(); + frame_signal.emit(buffer); } } // namespace controller diff --git a/src/gui/controller/playback-controller.hpp b/src/gui/controller/playback-controller.hpp index ea0f8dc96..601fb9d2b 100644 --- a/src/gui/controller/playback-controller.hpp +++ b/src/gui/controller/playback-controller.hpp @@ -23,6 +23,8 @@ ** This file contains the definition of the playback controller object */ +#include + #ifndef PLAYBACK_CONTROLLER_HPP #define PLAYBACK_CONTROLLER_HPP @@ -34,12 +36,17 @@ class PlaybackController public: void play(); + + void attach_viewer(const sigc::slot& on_frame); private: void playback_thread(); void pull_frame(); + +private: + sigc::signal frame_signal; }; } // namespace controller diff --git a/src/gui/gtk-lumiera.hpp b/src/gui/gtk-lumiera.hpp index 7f5a8cacd..a01bc5dc4 100644 --- a/src/gui/gtk-lumiera.hpp +++ b/src/gui/gtk-lumiera.hpp @@ -37,7 +37,6 @@ #include #include #include "lib/util.hpp" -#include "backend/thread-wrapper.hpp" extern "C" { #include diff --git a/src/gui/panels/viewer-panel.cpp b/src/gui/panels/viewer-panel.cpp index 7f68b39f3..f012a406e 100644 --- a/src/gui/panels/viewer-panel.cpp +++ b/src/gui/panels/viewer-panel.cpp @@ -23,8 +23,13 @@ #include "../gtk-lumiera.hpp" #include "viewer-panel.hpp" -using namespace gui::widgets; +#include "../workspace/workspace-window.hpp" +#include "../controller/controller.hpp" +#include "../controller/playback-controller.hpp" + using namespace Gtk; +using namespace gui::widgets; +using namespace gui::controller; namespace gui { namespace panels { @@ -34,6 +39,20 @@ ViewerPanel::ViewerPanel(workspace::WorkspaceWindow &workspace_window) : { //----- Pack in the Widgets -----// pack_start(display, PACK_EXPAND_WIDGET); + + PlaybackController &playback = + workspace_window.get_controller().get_playback_controller(); + + playback.attach_viewer(sigc::mem_fun(this, &ViewerPanel::on_frame)); +} + +void +ViewerPanel::on_frame(void *buffer) +{ + Displayer *displayer = display.get_displayer(); + REQUIRE(displayer); + + displayer->put(buffer); } } // namespace panels diff --git a/src/gui/panels/viewer-panel.hpp b/src/gui/panels/viewer-panel.hpp index a991014e9..b56fb3701 100644 --- a/src/gui/panels/viewer-panel.hpp +++ b/src/gui/panels/viewer-panel.hpp @@ -45,6 +45,10 @@ public: * @param workspace_window The window that owns this panel. **/ ViewerPanel(workspace::WorkspaceWindow &owner_window); + +protected: + + void on_frame(void *buffer); protected: diff --git a/src/gui/widgets/video-display-widget.cpp b/src/gui/widgets/video-display-widget.cpp index 0c396ed4d..1f9dca844 100644 --- a/src/gui/widgets/video-display-widget.cpp +++ b/src/gui/widgets/video-display-widget.cpp @@ -45,6 +45,12 @@ VideoDisplayWidget::~VideoDisplayWidget() delete displayer; } +Displayer* +VideoDisplayWidget::get_displayer() const +{ + return displayer; +} + void VideoDisplayWidget::on_realize() { diff --git a/src/gui/widgets/video-display-widget.hpp b/src/gui/widgets/video-display-widget.hpp index 6bf829f7a..5ea827d81 100644 --- a/src/gui/widgets/video-display-widget.hpp +++ b/src/gui/widgets/video-display-widget.hpp @@ -41,6 +41,8 @@ public: VideoDisplayWidget(); ~VideoDisplayWidget(); + + Displayer* get_displayer() const; /* ===== Overrides ===== */ private: From b0db84ec148b3c6671f3efd03f34cb4148db6878 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sun, 18 Jan 2009 16:17:39 +0000 Subject: [PATCH 10/11] Implemented intial playback controller thread --- configure.ac | 6 +- src/gui/controller/playback-controller.cpp | 86 +++++++++++++++++++--- src/gui/controller/playback-controller.hpp | 28 +++++++ src/gui/gtk-lumiera.cpp | 1 + src/gui/panels/timeline-panel.cpp | 30 +++----- src/gui/panels/timeline-panel.hpp | 4 +- src/gui/widgets/video-display-widget.cpp | 15 ---- src/gui/widgets/video-display-widget.hpp | 3 - 8 files changed, 122 insertions(+), 51 deletions(-) diff --git a/configure.ac b/configure.ac index 717fe6f4b..1b2ec96dc 100644 --- a/configure.ac +++ b/configure.ac @@ -141,9 +141,9 @@ PKG_CHECK_MODULES(LUMIERA_COMMON_LIBS, [sigc++-2.0 >= 2.0.17]) # gtk+-2.0 >= 2.12 gtkmm-2.4 >= 2.12 for Debian Lenny compatibility PKG_CHECK_MODULES(LUMIERA_GUI, [ - gtk+-2.0 >= 2.8 gtkmm-2.4 >= 2.8 - gdl-1.0 >= 0.6.1 cairomm-1.0 >= 0.6.0 - gavl >= 0.2.5 librsvg-2.0 >= 2.18.1]) + gtk+-2.0 >= 2.8 gtkmm-2.4 >= 2.8 gdl-1.0 >= 0.6.1 + cairomm-1.0 >= 0.6.0 gavl >= 0.2.5 librsvg-2.0 >= 2.18.1 + gthread-2.0 >= 2.12.4]) # END Gtk Dependancies diff --git a/src/gui/controller/playback-controller.cpp b/src/gui/controller/playback-controller.cpp index d69d3f7ce..44251278a 100644 --- a/src/gui/controller/playback-controller.cpp +++ b/src/gui/controller/playback-controller.cpp @@ -26,30 +26,94 @@ namespace gui { namespace controller { -void -PlaybackController::play() +PlaybackController::PlaybackController() : + finish_playback_thread(false), + playing(false) { - pull_frame(); + start_playback_thread(); +} + +PlaybackController::~PlaybackController() +{ + mutex.lock(); + finish_playback_thread = true; + mutex.unlock(); + thread->join(); } void -PlaybackController::attach_viewer(const sigc::slot& on_frame) +PlaybackController::play() +{ + Glib::Mutex::Lock lock(mutex); + playing = true; +} + +void +PlaybackController::pause() +{ + Glib::Mutex::Lock lock(mutex); + playing = false; +} + +void +PlaybackController::stop() +{ + Glib::Mutex::Lock lock(mutex); + playing = false; +} + +bool +PlaybackController::is_playing() +{ + Glib::Mutex::Lock lock(mutex); + return playing; +} + +void +PlaybackController::start_playback_thread() +{ + dispatcher.connect(sigc::mem_fun(this, &PlaybackController::on_frame)); + thread = Glib::Thread::create (sigc::mem_fun( + this, &PlaybackController::playback_thread), true); +} + +void +PlaybackController::attach_viewer( + const sigc::slot& on_frame) { frame_signal.connect(on_frame); } -void PlaybackController::playback_thread() -{ - pull_frame(); +void +PlaybackController::playback_thread() +{ + for(;;) + { + { + Glib::Mutex::Lock lock(mutex); + if(finish_playback_thread) + return; + } + + if(is_playing()) + pull_frame(); + + Glib::Thread::yield(); + } } -void PlaybackController::pull_frame() +void +PlaybackController::pull_frame() { - unsigned char buffer[320 * 240 * 4]; - for(int i = 0; i < 320*240*4; i++) buffer[i] = rand(); - + + dispatcher.emit(); +} + +void +PlaybackController::on_frame() +{ frame_signal.emit(buffer); } diff --git a/src/gui/controller/playback-controller.hpp b/src/gui/controller/playback-controller.hpp index 601fb9d2b..9333fcbc2 100644 --- a/src/gui/controller/playback-controller.hpp +++ b/src/gui/controller/playback-controller.hpp @@ -24,6 +24,7 @@ */ #include +#include #ifndef PLAYBACK_CONTROLLER_HPP #define PLAYBACK_CONTROLLER_HPP @@ -35,17 +36,44 @@ class PlaybackController { public: + PlaybackController(); + + ~PlaybackController(); + void play(); + + void pause(); + + void stop(); + + bool is_playing(); void attach_viewer(const sigc::slot& on_frame); private: + void start_playback_thread(); + void playback_thread(); void pull_frame(); + void on_frame(); + private: + + Glib::Thread *thread; + + Glib::StaticMutex mutex; + + Glib::Dispatcher dispatcher; + + volatile bool finish_playback_thread; + + volatile bool playing; + + unsigned char buffer[320 * 240 * 4]; + sigc::signal frame_signal; }; diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index a2147b72d..eb8fbe023 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -57,6 +57,7 @@ namespace gui { void GtkLumiera::main(int argc, char *argv[]) { + Glib::thread_init(); Main kit(argc, argv); diff --git a/src/gui/panels/timeline-panel.cpp b/src/gui/panels/timeline-panel.cpp index ea8215aaf..0c7a566cb 100644 --- a/src/gui/panels/timeline-panel.cpp +++ b/src/gui/panels/timeline-panel.cpp @@ -123,16 +123,13 @@ TimelinePanel::~TimelinePanel() void TimelinePanel::on_play_pause() { - workspace.get_controller().get_playback_controller().play(); - - // TEST CODE! if(!is_playing()) { play(); } else { - frameEvent.disconnect(); + pause(); } update_playback_buttons(); @@ -141,12 +138,8 @@ TimelinePanel::on_play_pause() void TimelinePanel::on_stop() { - // TEST CODE! - /*timelineWidget.set_playback_point(GAVL_TIME_UNDEFINED); - frameEvent.disconnect(); - show_time(timelineWidget.get_playback_period_start()); - - update_playback_buttons();*/ + workspace.get_controller().get_playback_controller().stop(); + update_playback_buttons(); } void @@ -288,20 +281,21 @@ TimelinePanel::update_zoom_buttons() void TimelinePanel::play() +{ + workspace.get_controller().get_playback_controller().play(); +} + +void +TimelinePanel::pause() { - /*if(timelineWidget.get_playback_point() == GAVL_TIME_UNDEFINED) - timelineWidget.set_playback_point( - timelineWidget.get_playback_period_start()); - frameEvent = Glib::signal_timeout().connect( - sigc::mem_fun(this, &TimelinePanel::on_frame), - 1000 / 25);*/ + workspace.get_controller().get_playback_controller().pause(); } bool TimelinePanel::is_playing() const { - // TEST CODE! - this should be hooked up to the real playback control - return frameEvent.connected(); + return workspace.get_controller().get_playback_controller(). + is_playing(); } void diff --git a/src/gui/panels/timeline-panel.hpp b/src/gui/panels/timeline-panel.hpp index 463130f5c..9c860b05a 100644 --- a/src/gui/panels/timeline-panel.hpp +++ b/src/gui/panels/timeline-panel.hpp @@ -87,6 +87,9 @@ private: void update_zoom_buttons(); void play(); + + void pause(); + bool is_playing() const; void set_tool(gui::widgets::timeline::ToolType tool); @@ -137,7 +140,6 @@ private: private: // TEST CODE bool on_frame(); - sigc::connection frameEvent; //----- Constants -----// private: diff --git a/src/gui/widgets/video-display-widget.cpp b/src/gui/widgets/video-display-widget.cpp index 1f9dca844..4a31af101 100644 --- a/src/gui/widgets/video-display-widget.cpp +++ b/src/gui/widgets/video-display-widget.cpp @@ -67,21 +67,6 @@ VideoDisplayWidget::on_realize() add_events(Gdk::ALL_EVENTS_MASK); } -bool -VideoDisplayWidget::on_button_press_event (GdkEventButton* event) -{ - (void)event; - - unsigned char buffer[320 * 240 * 4]; - - for(int i = 0; i < 320*240*4; i++) - buffer[i] = rand(); - - displayer->put((void*)buffer); - - return true; -} - Displayer* VideoDisplayWidget::createDisplayer( Gtk::Widget *drawingArea, int width, int height ) { diff --git a/src/gui/widgets/video-display-widget.hpp b/src/gui/widgets/video-display-widget.hpp index 5ea827d81..6587362cf 100644 --- a/src/gui/widgets/video-display-widget.hpp +++ b/src/gui/widgets/video-display-widget.hpp @@ -47,9 +47,6 @@ public: /* ===== Overrides ===== */ private: virtual void on_realize(); - - // TEST CODE!!!! - virtual bool on_button_press_event (GdkEventButton* event); /* ===== Internals ===== */ private: From 20b2cb1ee536f3bd7f6c725828350d01f4b3cded Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sun, 18 Jan 2009 17:41:55 +0000 Subject: [PATCH 11/11] Implemented a funky test card generator --- src/gui/controller/playback-controller.cpp | 89 +++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/src/gui/controller/playback-controller.cpp b/src/gui/controller/playback-controller.cpp index 44251278a..07a1fbd6d 100644 --- a/src/gui/controller/playback-controller.cpp +++ b/src/gui/controller/playback-controller.cpp @@ -102,11 +102,96 @@ PlaybackController::playback_thread() } } +typedef unsigned char byte; + +inline int +clamp(const int &val, const int &maxval, const int &minval) +{ + if(val > maxval) return maxval; + if(val < minval) return minval; + return val; +} + +inline void +rgb_to_yuv(int r, int g, int b, byte &y, byte &u, byte &v) +{ + // This code isn't great, but it does the job + y = (byte)clamp((299 * r + 587 * g + 114 * b) / 1000, 235, 16); + v = (byte)clamp((500 * r - 419 * g - 81 * b) / 1000 + 127, 255, 0); + u = (byte)clamp((-169 * r - 331 * g + 500 * b) / 1000 + 127, 255, 0); +} + +void rgb_buffer_to_yuy2(unsigned char *in, unsigned char *out) +{ + for(int i = 0; i < 320*240*2; i+=4) + { + byte y0, u0, v0; + const byte r0 = *(in++); + const byte g0 = *(in++); + const byte b0 = *(in++); + rgb_to_yuv(r0, g0, b0, y0, u0, v0); + + byte y1, u1, v1; + const byte r1 = *(in++); + const byte g1 = *(in++); + const byte b1 = *(in++); + rgb_to_yuv(r1, g1, b1, y1, u1, v1); + + out[i] = y0; + out[i + 1] = (byte)(((int)u0 + (int)u1) / 2); + out[i + 2] = y1; + out[i + 3] = (byte)(((int)v0 + (int)v1) / 2); + } +} + void PlaybackController::pull_frame() { - for(int i = 0; i < 320*240*4; i++) - buffer[i] = rand(); + static int frame = 0; + unsigned char in[320 * 240 * 3]; + + frame--; + + if(frame <= 0) + frame = 200; + + if(frame > 150) + { + for(int i = 0; i < 320*240*3; i+=3) + { + byte value = (byte)rand(); + in[i] = value; + in[i+1] = value; + in[i+2] = value; + } + } + else + { + unsigned char row[320 * 3]; + + + for(int x = 0; x < 320; x++) + { + byte &r = row[x*3]; + byte &g = row[x*3+1]; + byte &b = row[x*3+2]; + + if(x < 1*320/7) r = 0xC0, g = 0xC0, b = 0xC0; + else if(x < 2*320/7) r = 0xC0, g = 0xC0, b = 0x00; + else if(x < 3*320/7) r = 0x00, g = 0xC0, b = 0xC0; + else if(x < 4*320/7) r = 0x00, g = 0xC0, b = 0x00; + else if(x < 5*320/7) r = 0xC0, g = 0x00, b = 0xC0; + else if(x < 6*320/7) r = 0xC0, g = 0x00, b = 0x00; + else r = 0x00, g = 0x00, b = 0xC0; + } + + for(int y = 0; y < 240; y++) + { + memcpy(in + y*320*3, row, sizeof(row)); + } + } + + rgb_buffer_to_yuy2(in, buffer); dispatcher.emit(); }