lumiera_/src/gui/panels/timeline-panel.cpp

419 lines
9.9 KiB
C++
Raw Normal View History

/*
2008-04-19 21:31:27 +02:00
timeline-panel.cpp - Implementation of the timeline panel
Copyright (C) Lumiera.org
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
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 <boost/foreach.hpp>
2008-05-17 19:12:07 +02:00
#include "../gtk-lumiera.hpp"
2008-04-19 21:31:27 +02:00
#include "timeline-panel.hpp"
2009-01-17 17:12:11 +01:00
#include "../workspace/workspace-window.hpp"
#include "../model/project.hpp"
2009-01-17 17:12:11 +01:00
#include "../controller/controller.hpp"
2008-08-16 23:06:46 +02:00
extern "C" {
#include "../../lib/time.h"
}
2008-05-22 20:19:04 +02:00
using namespace Gtk;
using namespace sigc;
2008-11-22 20:08:12 +01:00
using namespace std;
using namespace boost;
2009-03-27 15:26:08 +01:00
using namespace util;
using namespace gui::widgets;
using namespace gui::model;
2008-05-22 20:19:04 +02:00
namespace gui {
namespace panels {
const int TimelinePanel::ZoomToolSteps = 2; // 2 seems comfortable
2009-04-13 17:11:50 +02:00
TimelinePanel::TimelinePanel(workspace::PanelManager &panel_manager,
GdlDockItem *dock_item) :
Panel(panel_manager, dock_item, get_title(), get_stock_id()),
2008-12-30 13:35:58 +01:00
timeIndicator(),
2009-03-14 16:24:41 +01:00
timeIndicatorButton(),
2008-09-12 21:55:54 +02:00
previousButton(Stock::MEDIA_PREVIOUS),
rewindButton(Stock::MEDIA_REWIND),
playPauseButton(Stock::MEDIA_PLAY),
2008-10-07 22:17:29 +02:00
stopButton(Stock::MEDIA_STOP),
2008-09-12 21:55:54 +02:00
forwardButton(Stock::MEDIA_FORWARD),
nextButton(Stock::MEDIA_NEXT),
arrowTool(Gtk::StockID("tool_arrow")),
iBeamTool(Gtk::StockID("tool_i_beam")),
zoomIn(Stock::ZOOM_IN),
zoomOut(Stock::ZOOM_OUT),
updatingToolbar(false),
currentTool(timeline::IBeam)
2009-03-27 15:26:08 +01:00
{
2008-11-22 20:08:12 +01:00
// Hook up notifications
2009-04-13 17:11:50 +02:00
get_project().get_sequences().signal_changed().connect(mem_fun(this,
&TimelinePanel::on_sequence_list_changed));
2008-11-22 20:08:12 +01:00
2009-03-27 15:26:08 +01:00
// Setup the sequence chooser
sequenceChooserModel = Gtk::ListStore::create(sequenceChooserColumns);
ENSURE(sequenceChooserModel);
2009-03-21 17:57:56 +01:00
2009-03-27 15:26:08 +01:00
sequenceChooser.set_model(sequenceChooserModel);
sequenceChooser.pack_start(sequenceChooserColumns.nameColumn);
2009-03-21 17:57:56 +01:00
sequenceChooser.show_all();
2009-03-27 15:26:08 +01:00
sequenceChooserChangedConnection = sequenceChooser.signal_changed().
connect( sigc::mem_fun(*this, &TimelinePanel::on_sequence_chosen) );
panelBar.pack_start(sequenceChooser, PACK_SHRINK);
// Setup the toolbar
2009-03-14 16:24:41 +01:00
timeIndicatorButton.add(timeIndicator);
timeIndicatorButton.set_relief(Gtk::RELIEF_NONE);
timeIndicatorButton.set_focus_on_click(false);
2008-09-12 21:55:54 +02:00
2009-03-14 16:24:41 +01:00
toolbar.append(timeIndicatorButton);
2008-10-07 22:17:29 +02:00
2008-09-12 21:55:54 +02:00
toolbar.append(previousButton);
toolbar.append(rewindButton);
2008-10-07 22:17:29 +02:00
toolbar.append(playPauseButton,
mem_fun(this, &TimelinePanel::on_play_pause));
toolbar.append(stopButton,
mem_fun(this, &TimelinePanel::on_stop));
2008-09-12 21:55:54 +02:00
toolbar.append(forwardButton);
toolbar.append(nextButton);
2008-08-30 15:00:47 +02:00
toolbar.append(seperator1);
2008-10-07 22:17:29 +02:00
toolbar.append(arrowTool,
mem_fun(this, &TimelinePanel::on_arrow_tool));
toolbar.append(iBeamTool,
mem_fun(this, &TimelinePanel::on_ibeam_tool));
2008-09-12 21:55:54 +02:00
2008-08-30 15:00:47 +02:00
toolbar.append(seperator2);
2008-09-12 21:55:54 +02:00
toolbar.append(zoomIn, mem_fun(this, &TimelinePanel::on_zoom_in));
toolbar.append(zoomOut, mem_fun(this, &TimelinePanel::on_zoom_out));
2009-03-21 17:57:56 +01:00
2009-03-09 21:45:50 +01:00
toolbar.show_all();
2009-03-21 17:57:56 +01:00
panelBar.pack_start(toolbar, PACK_SHRINK);
2010-07-07 04:07:15 +02:00
// 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"));
playPauseButton .set_tooltip_text(_("Start playback"));
stopButton .set_tooltip_text(_("Stop playback"));
forwardButton .set_tooltip_text(_("Forward"));
nextButton .set_tooltip_text(_("To end"));
arrowTool .set_tooltip_text(_("Selection tool"));
iBeamTool .set_tooltip_text(_("Marker tool"));
zoomIn .set_tooltip_text(_("Zoom in"));
zoomOut .set_tooltip_text(_("Zoom out"));
2009-03-27 15:26:08 +01:00
// Setup the timeline widget
shared_ptr<Sequence> sequence
2009-04-13 17:11:50 +02:00
= *get_project().get_sequences().begin();
2009-03-27 15:26:08 +01:00
timelineWidget.reset(new TimelineWidget(load_state(sequence)));
pack_start(*timelineWidget, PACK_EXPAND_WIDGET);
2008-08-30 15:00:47 +02:00
// Set the initial UI state
2009-03-21 17:57:56 +01:00
update_sequence_chooser();
update_tool_buttons();
update_zoom_buttons();
2008-08-30 15:00:47 +02:00
show_time(0);
}
TimelinePanel::~TimelinePanel()
{
}
const char*
TimelinePanel::get_title()
{
return _("Timeline");
}
2009-04-04 19:53:09 +02:00
const gchar*
TimelinePanel::get_stock_id()
{
return "panel_timeline";
}
2008-10-07 22:17:29 +02:00
void
TimelinePanel::on_play_pause()
2009-01-17 17:12:11 +01:00
{
2008-10-07 22:17:29 +02:00
if(!is_playing())
{
play();
}
else
{
pause();
2008-10-07 22:17:29 +02:00
}
update_playback_buttons();
}
void
TimelinePanel::on_stop()
{
2009-04-13 17:11:50 +02:00
get_controller().get_playback_controller().stop();
update_playback_buttons();
2008-10-07 22:17:29 +02:00
}
void
TimelinePanel::on_arrow_tool()
{
set_tool(timeline::Arrow);
}
void
TimelinePanel::on_ibeam_tool()
{
set_tool(timeline::IBeam);
}
void
TimelinePanel::on_zoom_in()
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
timelineWidget->zoom_view(ZoomToolSteps);
update_zoom_buttons();
}
void
TimelinePanel::on_zoom_out()
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
timelineWidget->zoom_view(-ZoomToolSteps);
update_zoom_buttons();
}
2008-08-16 23:06:46 +02:00
void
TimelinePanel::on_mouse_hover(gavl_time_t time)
{
2008-12-30 13:35:58 +01:00
(void)time;
2008-10-07 22:17:29 +02:00
}
void
TimelinePanel::on_playback_period_drag_released()
{
//----- TEST CODE - this needs to set the playback point via the
// real backend
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
2009-03-27 15:26:08 +01:00
timelineWidget->get_state()->set_playback_point(
timelineWidget->get_state()->get_playback_period_start());
2008-10-07 22:17:29 +02:00
//----- END TEST CODE
play();
}
2008-11-22 20:08:12 +01:00
void
TimelinePanel::on_sequence_list_changed()
{
2009-03-21 17:57:56 +01:00
update_sequence_chooser();
}
void
2009-03-27 15:26:08 +01:00
TimelinePanel::on_sequence_chosen()
2009-03-21 17:57:56 +01:00
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
2009-03-21 17:57:56 +01:00
2009-03-27 15:26:08 +01:00
Gtk::TreeIter iter = sequenceChooser.get_active();
if(iter)
2009-03-21 17:57:56 +01:00
{
2009-03-27 15:26:08 +01:00
weak_ptr<Sequence> sequence_ptr =
(*iter)[sequenceChooserColumns.sequenceColumn];
shared_ptr<Sequence> sequence(sequence_ptr.lock());
if(sequence)
{
shared_ptr<timeline::TimelineState> old_state(
timelineWidget->get_state());
REQUIRE(old_state);
if(sequence != old_state->get_sequence())
timelineWidget->set_state(load_state(sequence));
}
2009-03-21 17:57:56 +01:00
}
2009-03-27 15:26:08 +01:00
update_zoom_buttons();
2008-11-22 20:08:12 +01:00
}
void
2009-03-27 15:26:08 +01:00
TimelinePanel::update_sequence_chooser()
{
2009-03-27 15:26:08 +01:00
REQUIRE(sequenceChooserModel);
// Block the event handler
sequenceChooserChangedConnection.block();
2009-03-27 15:26:08 +01:00
// Repopulate the sequence chooser
sequenceChooserModel->clear();
shared_ptr<timeline::TimelineState> state =
timelineWidget->get_state();
BOOST_FOREACH( shared_ptr< model::Sequence > sequence,
2009-04-13 17:11:50 +02:00
get_project().get_sequences() )
{
2009-03-27 15:26:08 +01:00
Gtk::TreeIter iter = sequenceChooserModel->append();
Gtk::TreeModel::Row row = *iter;
row[sequenceChooserColumns.sequenceColumn] = sequence;
row[sequenceChooserColumns.nameColumn] = sequence->get_name();
if(state && state->get_sequence() == sequence)
2009-03-27 15:26:08 +01:00
sequenceChooser.set_active(iter);
}
2008-11-22 20:08:12 +01:00
// If there's no active sequence, then unselect
if(!state)
sequenceChooser.set_active(-1);
2009-03-27 15:26:08 +01:00
// Unblock the event handler
sequenceChooserChangedConnection.unblock();
}
2008-10-07 22:17:29 +02:00
void
TimelinePanel::update_playback_buttons()
{
2010-07-07 04:07:15 +02:00
if (is_playing())
{
playPauseButton.set_stock_id(Stock::MEDIA_PAUSE);
playPauseButton.set_tooltip_text("Pause playback");
}
else
{
playPauseButton.set_stock_id(Stock::MEDIA_PLAY);
playPauseButton.set_tooltip_text("Start playback");
}
2008-08-16 23:06:46 +02:00
}
void
TimelinePanel::update_tool_buttons()
{
if(!updatingToolbar)
2008-12-06 20:12:18 +01:00
{
updatingToolbar = true;
arrowTool.set_active(currentTool == timeline::Arrow);
iBeamTool.set_active(currentTool == timeline::IBeam);
updatingToolbar = false;
}
}
void
TimelinePanel::update_zoom_buttons()
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
const shared_ptr<timeline::TimelineState> state =
timelineWidget->get_state();
if(state)
{
timeline::TimelineViewWindow &viewWindow =
state->get_view_window();
zoomIn.set_sensitive(viewWindow.get_time_scale() != 1);
zoomOut.set_sensitive(viewWindow.get_time_scale()
!= TimelineWidget::MaxScale);
}
}
2008-10-07 22:17:29 +02:00
void
TimelinePanel::play()
{
2009-04-13 17:11:50 +02:00
get_controller().get_playback_controller().play();
}
void
TimelinePanel::pause()
2008-10-07 22:17:29 +02:00
{
2009-04-13 17:11:50 +02:00
get_controller().get_playback_controller().pause();
2008-10-07 22:17:29 +02:00
}
bool
2009-04-13 17:11:50 +02:00
TimelinePanel::is_playing()
2008-10-07 22:17:29 +02:00
{
2009-04-13 17:11:50 +02:00
return get_controller().get_playback_controller().is_playing();
2008-10-07 22:17:29 +02:00
}
void
TimelinePanel::set_tool(timeline::ToolType tool)
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
if(updatingToolbar) return;
2009-03-27 15:26:08 +01:00
currentTool = tool;
timelineWidget->set_tool(tool);
update_tool_buttons();
}
2008-08-30 15:00:47 +02:00
void
TimelinePanel::show_time(gavl_time_t time)
{
timeIndicator.set_text(lumiera_tmpbuf_print_time(time));
}
2008-10-07 22:17:29 +02:00
bool
TimelinePanel::on_frame()
{
// TEST CODE!
/*const gavl_time_t point = timelineWidget.get_playback_point()
2008-10-07 22:17:29 +02:00
+ GAVL_TIME_SCALE / 25;
if(point < timelineWidget.get_playback_period_end())
{
show_time(point);
timelineWidget.set_playback_point(point);
}
else
on_stop();*/
2008-10-07 22:17:29 +02:00
return true;
}
2009-03-27 15:26:08 +01:00
shared_ptr<timeline::TimelineState>
TimelinePanel::load_state(weak_ptr<Sequence> sequence)
{
if(contains(timelineStates, sequence))
return timelineStates[sequence];
shared_ptr<Sequence> shared_sequence = sequence.lock();
if(shared_sequence)
{
shared_ptr<timeline::TimelineState> new_state(
new timeline::TimelineState(shared_sequence));
timelineStates[sequence] = new_state;
return new_state;
}
2009-03-27 15:26:08 +01:00
return shared_ptr< timeline::TimelineState >();
}
} // namespace panels
} // namespace gui