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 @@
+
+
+
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