diff --git a/doc/devel/draw/FramePositions.svg b/doc/devel/draw/FramePositions.svg new file mode 100644 index 000000000..01cc14ca1 --- /dev/null +++ b/doc/devel/draw/FramePositions.svg @@ -0,0 +1,1269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + style="overflow:visible"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + t + + + + + + + + + + + + + + + + + + + + + + + t + + + + + + + + + + + + + + + + + + + + + + + + + t + + diff --git a/icons/svg/tool-arrow.svg b/icons/svg/tool-arrow.svg index 026b6633f..3f0b72102 100644 --- a/icons/svg/tool-arrow.svg +++ b/icons/svg/tool-arrow.svg @@ -510,6 +510,89 @@ y1="-129.52815" x2="252.00447" y2="-135.47408" /> + + + + + + + + - - - - - + + + - - - - - - + + + + - - - - - - - + + + + + @@ -655,7 +655,7 @@ sodipodi:nodetypes="cssccccssscccsssccccssscccs" id="path7977" d="M 130.5,77.5 C 129.99037,77.5 129.5,78 129.5,78.5 C 129.5,79 130,79.5 130.5,79.5 L 130.5,79.5 C 131,79.5 131.5,80 131.5,80.5 L 131.5,87.5 C 131.5,88 131,88.5 130.5,88.5 L 130.5,88.5 C 130,88.5 129.5,89 129.5,89.5 C 129.5,90 130,90.5 130.5,90.5 L 131.5,90.5 C 132,90.5 132.5,90 132.5,89.5 C 132.5,90 133,90.5 133.5,90.5 L 134.5,90.5 C 135,90.5 135.5,90 135.5,89.5 C 135.5,89 135,88.5 134.5,88.5 L 134.5,88.5 C 134,88.5 133.5,88 133.5,87.5 L 133.5,80.5 C 133.5,80 134,79.5 134.5,79.5 L 134.5,79.5 C 135,79.5 135.5,79 135.5,78.5 C 135.5,78 135,77.5 134.5,77.5 L 133.5,77.5 C 133,77.5 132.5,78 132.5,78.5 C 132.5,78 132,77.5 131.5,77.5 L 130.5,77.5 z" - style="fill:#eeeeec;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:#eeeeec;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:#eeeeec;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:#eeeeec;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> diff --git a/src/gui/lumiera_ui.rc b/src/gui/lumiera_ui.rc index 02f6d90fc..a13ba209d 100644 --- a/src/gui/lumiera_ui.rc +++ b/src/gui/lumiera_ui.rc @@ -126,6 +126,7 @@ style "timeline_body" gtkmm__CustomObject_TimelineBody::background = "#7E838B" gtkmm__CustomObject_TimelineBody::selection = "#2D2D90" gtkmm__CustomObject_TimelineBody::selection_alpha = 0.5 + gtkmm__CustomObject_TimelineBody::playback_point = "#006000" } style "timeline_ruler" = "default_base" @@ -140,10 +141,15 @@ style "timeline_ruler" = "default_base" gtkmm__CustomObject_TimelineRuler::min_division_width = 100 gtkmm__CustomObject_TimelineRuler::mouse_chevron_size = 5 gtkmm__CustomObject_TimelineRuler::selection_chevron_size = 5 - gtkmm__CustomObject_TimelineRuler::playback_arrow_colour = "#2D2D90" - gtkmm__CustomObject_TimelineRuler::playback_arrow_alpha = 0.5 - gtkmm__CustomObject_TimelineRuler::playback_arrow_size = 10 - gtkmm__CustomObject_TimelineRuler::playback_arrow_stem_size = 3 + + gtkmm__CustomObject_TimelineRuler::playback_point_colour = "#006000" + gtkmm__CustomObject_TimelineRuler::playback_point_alpha = 0.5 + gtkmm__CustomObject_TimelineRuler::playback_point_size = 12 + + gtkmm__CustomObject_TimelineRuler::playback_period_arrow_colour = "#2D2D90" + gtkmm__CustomObject_TimelineRuler::playback_period_arrow_alpha = 0.5 + gtkmm__CustomObject_TimelineRuler::playback_period_arrow_size = 10 + gtkmm__CustomObject_TimelineRuler::playback_period_arrow_stem_size = 3 } style "timeline_header_base" = "default_base" diff --git a/src/gui/panels/timeline-panel.cpp b/src/gui/panels/timeline-panel.cpp index 65e9ae6b7..709323bad 100644 --- a/src/gui/panels/timeline-panel.cpp +++ b/src/gui/panels/timeline-panel.cpp @@ -39,6 +39,12 @@ const int TimelinePanel::ZoomToolSteps = 2; // 2 seems comfortable TimelinePanel::TimelinePanel() : Panel("timeline", _("Timeline"), "panel_timeline"), + previousButton(Stock::MEDIA_PREVIOUS), + rewindButton(Stock::MEDIA_REWIND), + playPauseButton(Stock::MEDIA_PLAY), + stopButton(Stock::MEDIA_STOP), + forwardButton(Stock::MEDIA_FORWARD), + nextButton(Stock::MEDIA_NEXT), arrowTool(Gtk::StockID("tool_arrow")), iBeamTool(Gtk::StockID("tool_i_beam")), zoomIn(Stock::ZOOM_IN), @@ -49,18 +55,32 @@ TimelinePanel::TimelinePanel() : // Setup the widget timelineWidget.mouse_hover_signal().connect( mem_fun(this, &TimelinePanel::on_mouse_hover)); + timelineWidget.playback_period_drag_released_signal().connect( + mem_fun(this, &TimelinePanel::on_playback_period_drag_released)); // Setup the toolbar timeIndicatorButton.set_label_widget(timeIndicator); + toolbar.append(timeIndicatorButton); + toolbar.append(previousButton); + toolbar.append(rewindButton); + toolbar.append(playPauseButton, + mem_fun(this, &TimelinePanel::on_play_pause)); + toolbar.append(stopButton, + mem_fun(this, &TimelinePanel::on_stop)); + toolbar.append(forwardButton); + toolbar.append(nextButton); + toolbar.append(seperator1); - toolbar.append(arrowTool, mem_fun(this, - &TimelinePanel::on_arrow_tool)); - toolbar.append(iBeamTool, mem_fun(this, - &TimelinePanel::on_ibeam_tool)); + toolbar.append(arrowTool, + mem_fun(this, &TimelinePanel::on_arrow_tool)); + toolbar.append(iBeamTool, + mem_fun(this, &TimelinePanel::on_ibeam_tool)); + toolbar.append(seperator2); + toolbar.append(zoomIn, mem_fun(this, &TimelinePanel::on_zoom_in)); toolbar.append(zoomOut, mem_fun(this, &TimelinePanel::on_zoom_out)); @@ -78,6 +98,33 @@ TimelinePanel::TimelinePanel() : show_time(0); } +void +TimelinePanel::on_play_pause() +{ + // TEST CODE! + if(!is_playing()) + { + play(); + } + else + { + frameEvent.disconnect(); + } + + update_playback_buttons(); +} + +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(); +} + void TimelinePanel::on_arrow_tool() { @@ -112,7 +159,26 @@ TimelinePanel::on_zoom_out() void TimelinePanel::on_mouse_hover(gavl_time_t time) { - show_time(time); + +} + +void +TimelinePanel::on_playback_period_drag_released() +{ + //----- TEST CODE - this needs to set the playback point via the + // real backend + timelineWidget.set_playback_point( + timelineWidget.get_playback_period_start()); + //----- END TEST CODE + + play(); +} + +void +TimelinePanel::update_playback_buttons() +{ + playPauseButton.set_stock_id(is_playing() ? + Stock::MEDIA_PAUSE : Stock::MEDIA_PLAY); } void @@ -136,12 +202,49 @@ TimelinePanel::update_zoom_buttons() TimelineWidget::MaxScale); } +void +TimelinePanel::play() +{ + 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); +} + +bool +TimelinePanel::is_playing() const +{ + // TEST CODE! - this should be hooked up to the real playback control + return frameEvent.connected(); +} + void TimelinePanel::show_time(gavl_time_t time) { timeIndicator.set_text(lumiera_tmpbuf_print_time(time)); } +bool +TimelinePanel::on_frame() +{ + // TEST CODE! + const gavl_time_t point = timelineWidget.get_playback_point() + + GAVL_TIME_SCALE / 25; + if(point < timelineWidget.get_playback_period_end()) + { + show_time(point); + timelineWidget.set_playback_point(point); + + + } + else + on_stop(); + + return true; +} + } // namespace panels } // namespace gui } // namespace lumiera diff --git a/src/gui/panels/timeline-panel.hpp b/src/gui/panels/timeline-panel.hpp index b46218e87..e12a827f6 100644 --- a/src/gui/panels/timeline-panel.hpp +++ b/src/gui/panels/timeline-panel.hpp @@ -49,6 +49,10 @@ public: private: //----- Event Handlers -----// + + void on_play_pause(); + void on_stop(); + void on_arrow_tool(); void on_ibeam_tool(); @@ -58,11 +62,16 @@ private: void on_time_pressed(); void on_mouse_hover(gavl_time_t time); + void on_playback_period_drag_released(); private: + void update_playback_buttons(); void update_tool_buttons(); void update_zoom_buttons(); + void play(); + bool is_playing() const; + void show_time(gavl_time_t time); private: @@ -75,6 +84,17 @@ private: TimelineWidget timelineWidget; // Toolbar Widgets + + Gtk::Label timeIndicator; + Gtk::ToolButton timeIndicatorButton; + + Gtk::ToolButton previousButton; + Gtk::ToolButton rewindButton; + Gtk::ToolButton playPauseButton; + Gtk::ToolButton stopButton; + Gtk::ToolButton forwardButton; + Gtk::ToolButton nextButton; + Gtk::ToggleToolButton arrowTool; Gtk::ToggleToolButton iBeamTool; @@ -84,14 +104,17 @@ private: Gtk::ToolButton zoomOut; Gtk::SeparatorToolItem seperator2; - - Gtk::Label timeIndicator; - Gtk::ToolButton timeIndicatorButton; - + // Internals bool updatingToolbar; +private: + // TEST CODE + bool on_frame(); + sigc::connection frameEvent; + //----- Constants -----// +private: static const int ZoomToolSteps; }; diff --git a/src/gui/panels/viewer-panel.cpp b/src/gui/panels/viewer-panel.cpp index 323859b9a..ee129a606 100644 --- a/src/gui/panels/viewer-panel.cpp +++ b/src/gui/panels/viewer-panel.cpp @@ -31,20 +31,11 @@ namespace gui { namespace panels { ViewerPanel::ViewerPanel() : - Panel("viewer", _("Viewer"), "panel_viewer"), - previousButton(Stock::MEDIA_PREVIOUS), - rewindButton(Stock::MEDIA_REWIND), - playPauseButton(Stock::MEDIA_PLAY), - forwardButton(Stock::MEDIA_FORWARD), - nextButton(Stock::MEDIA_NEXT) + Panel("viewer", _("Viewer"), "panel_viewer") { //----- Set up the Tool Bar -----// // Add the commands - toolBar.append(previousButton); - toolBar.append(rewindButton); - toolBar.append(playPauseButton); - toolBar.append(forwardButton); - toolBar.append(nextButton); + // Configure the toolbar toolBar.set_toolbar_style(TOOLBAR_ICONS); diff --git a/src/gui/panels/viewer-panel.hpp b/src/gui/panels/viewer-panel.hpp index 9f92b4f63..5400aee41 100644 --- a/src/gui/panels/viewer-panel.hpp +++ b/src/gui/panels/viewer-panel.hpp @@ -31,9 +31,6 @@ #include "panel.hpp" #include "../widgets/video-display-widget.hpp" -using namespace lumiera::gui::widgets; -using namespace Gtk; - namespace lumiera { namespace gui { namespace panels { @@ -45,14 +42,8 @@ namespace panels { protected: - ToolButton previousButton; - ToolButton rewindButton; - ToolButton playPauseButton; - ToolButton forwardButton; - ToolButton nextButton; - - VideoDisplayWidget display; - Toolbar toolBar; + lumiera::gui::widgets::VideoDisplayWidget display; + Gtk::Toolbar toolBar; }; } // namespace panels diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index c7463768b..2bf6285f9 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -48,6 +48,7 @@ TimelineWidget::TimelineWidget() : selectionEnd(0), playbackPeriodStart(0), playbackPeriodEnd(0), + playbackPoint(GAVL_TIME_UNDEFINED), horizontalScroll(horizontalAdjustment), verticalScroll(verticalAdjustment) { @@ -248,6 +249,20 @@ TimelineWidget::set_playback_period(gavl_time_t start, gavl_time_t end) body->queue_draw(); } +void +TimelineWidget::set_playback_point(gavl_time_t point) +{ + playbackPoint = point; + ruler->queue_draw(); + body->queue_draw(); +} + +gavl_time_t +TimelineWidget::get_playback_point() const +{ + return playbackPoint; +} + ToolType TimelineWidget::get_tool() const { @@ -274,6 +289,12 @@ TimelineWidget::mouse_hover_signal() const return mouseHoverSignal; } +sigc::signal +TimelineWidget::playback_period_drag_released_signal() const +{ + return playbackPeriodDragReleasedSignal; +} + void TimelineWidget::on_scroll() { @@ -372,6 +393,12 @@ TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event) return true; } +void +TimelineWidget::on_playback_period_drag_released() +{ + playbackPeriodDragReleasedSignal.emit(); +} + } // namespace widgets } // namespace gui } // namespace lumiera diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index ef13ef556..4e307bd19 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -52,8 +52,14 @@ namespace timeline {} class TimelineWidget : public Gtk::Table { public: + /** + * Constructor + */ TimelineWidget(); + /** + * Destructor + */ ~TimelineWidget(); /* ===== Data Access ===== */ @@ -145,6 +151,20 @@ public: */ void set_playback_period(gavl_time_t start, gavl_time_t end); + /** + * Sets the time which is currenty being played back. + * @param point The time index being played. This value may be + * GAVL_TIME_UNDEFINED, if there is no playback point. + */ + void set_playback_point(gavl_time_t point); + + /** + * Gets the current playback point. + * @return The time index of the playback point. This value may be + * GAVL_TIME_UNDEFINED, if there is no playback point. + */ + gavl_time_t get_playback_point() const; + /** * Gets the type of the tool currently active. */ @@ -160,6 +180,8 @@ public: sigc::signal view_changed_signal() const; sigc::signal mouse_hover_signal() const; + + sigc::signal playback_period_drag_released_signal() const; /* ===== Events ===== */ protected: @@ -183,6 +205,8 @@ private: int get_y_scroll_offset() const; bool on_motion_in_body_notify_event(GdkEventMotion *event); + + void on_playback_period_drag_released(); protected: @@ -195,6 +219,7 @@ protected: gavl_time_t selectionEnd; gavl_time_t playbackPeriodStart; gavl_time_t playbackPeriodEnd; + gavl_time_t playbackPoint; int totalHeight; @@ -202,6 +227,7 @@ protected: timeline::Track video2; std::vector tracks; + // Child Widgets timeline::HeaderContainer *headerContainer; timeline::TimelineBody *body; timeline::TimelineRuler *ruler; @@ -213,6 +239,8 @@ protected: // Signals sigc::signal viewChangedSignal; sigc::signal mouseHoverSignal; + sigc::signal + playbackPeriodDragReleasedSignal; /* ===== Constants ===== */ public: diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp index a3602572a..0d620ef07 100644 --- a/src/gui/widgets/timeline/timeline-body.cpp +++ b/src/gui/widgets/timeline/timeline-body.cpp @@ -132,8 +132,6 @@ TimelineBody::on_realize() bool TimelineBody::on_expose_event(GdkEventExpose* event) { - Cairo::Matrix view_matrix; - REQUIRE(event != NULL); REQUIRE(timelineWidget != NULL); @@ -146,78 +144,18 @@ TimelineBody::on_expose_event(GdkEventExpose* event) read_styles(); // Prepare to render via cairo - Glib::RefPtr