2 Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "lib/screen.h"
21 #include "lib/config.h"
22 #include "lib/player_manager.h"
24 #include "film_player.h"
28 using namespace boost;
30 FilmPlayer::FilmPlayer (Film const * f)
35 , _ignore_position_changed (false)
39 vector<shared_ptr<Screen> > const scr = Config::instance()->screens ();
40 for (vector<shared_ptr<Screen> >::const_iterator i = scr.begin(); i != scr.end(); ++i) {
41 _screen.append_text ((*i)->name ());
45 _screen.set_active (0);
48 _status.set_use_markup (true);
50 _position.set_digits (0);
52 _main_vbox.set_spacing (12);
54 Gtk::HBox* l = manage (new Gtk::HBox);
55 l->pack_start (_play);
56 l->pack_start (_pause);
57 l->pack_start (_stop);
59 Gtk::VBox* r = manage (new Gtk::VBox);
60 r->pack_start (_screen, false, false);
61 r->pack_start (_ab, false, false);
62 r->pack_start (*manage (new Gtk::Label ("")), true, true);
64 Gtk::HBox* t = manage (new Gtk::HBox);
65 t->pack_start (*l, true, true);
66 t->pack_start (*r, false, false);
68 _main_vbox.pack_start (*t, true, true);
69 _main_vbox.pack_start (_position, false, false);
70 _main_vbox.pack_start (_status, false, false);
72 _play.signal_clicked().connect (sigc::mem_fun (*this, &FilmPlayer::play_clicked));
73 _pause.signal_clicked().connect (sigc::mem_fun (*this, &FilmPlayer::pause_clicked));
74 _stop.signal_clicked().connect (sigc::mem_fun (*this, &FilmPlayer::stop_clicked));
75 _position.signal_value_changed().connect (sigc::mem_fun (*this, &FilmPlayer::position_changed));
76 _position.signal_format_value().connect (sigc::mem_fun (*this, &FilmPlayer::format_position));
79 Glib::signal_timeout().connect (sigc::bind_return (sigc::mem_fun (*this, &FilmPlayer::update), true), 1000);
81 Config::instance()->Changed.connect (sigc::mem_fun (*this, &FilmPlayer::update_screens));
85 FilmPlayer::set_film (Film const * f)
89 if (_film && _film->length() != 0 && _film->frames_per_second() != 0) {
90 _position.set_range (0, _film->length() / _film->frames_per_second());
94 _film->Changed.connect (sigc::mem_fun (*this, &FilmPlayer::film_changed));
105 FilmPlayer::set_button_states ()
108 _play.set_sensitive (false);
109 _pause.set_sensitive (false);
110 _stop.set_sensitive (false);
111 _screen.set_sensitive (false);
112 _position.set_sensitive (false);
113 _ab.set_sensitive (false);
117 PlayerManager::State s = PlayerManager::instance()->state ();
120 case PlayerManager::QUIESCENT:
121 _play.set_sensitive (true);
122 _pause.set_sensitive (false);
123 _stop.set_sensitive (false);
124 _screen.set_sensitive (true);
125 _position.set_sensitive (false);
126 _ab.set_sensitive (true);
128 case PlayerManager::PLAYING:
129 _play.set_sensitive (false);
130 _pause.set_sensitive (true);
131 _stop.set_sensitive (true);
132 _screen.set_sensitive (false);
133 _position.set_sensitive (true);
134 _ab.set_sensitive (false);
136 case PlayerManager::PAUSED:
137 _play.set_sensitive (true);
138 _pause.set_sensitive (false);
139 _stop.set_sensitive (true);
140 _screen.set_sensitive (false);
141 _position.set_sensitive (false);
142 _ab.set_sensitive (false);
148 FilmPlayer::play_clicked ()
150 PlayerManager* p = PlayerManager::instance ();
152 switch (p->state ()) {
153 case PlayerManager::QUIESCENT:
154 _last_play_fs = _film->state_copy ();
155 if (_ab.get_active ()) {
156 shared_ptr<FilmState> fs_a = _film->state_copy ();
157 fs_a->filters.clear ();
158 /* This is somewhat arbitrary, but hey ho */
159 fs_a->scaler = Scaler::from_id ("bicubic");
160 p->setup (fs_a, _last_play_fs, screen ());
162 p->setup (_last_play_fs, screen ());
164 p->pause_or_unpause ();
166 case PlayerManager::PLAYING:
168 case PlayerManager::PAUSED:
169 p->pause_or_unpause ();
175 FilmPlayer::pause_clicked ()
177 PlayerManager* p = PlayerManager::instance ();
179 switch (p->state ()) {
180 case PlayerManager::QUIESCENT:
182 case PlayerManager::PLAYING:
183 p->pause_or_unpause ();
185 case PlayerManager::PAUSED:
191 FilmPlayer::stop_clicked ()
193 PlayerManager::instance()->stop ();
197 FilmPlayer::screen () const
199 vector<shared_ptr<Screen> > const s = Config::instance()->screens ();
201 return shared_ptr<Screen> ();
204 int const r = _screen.get_active_row_number ();
205 if (r >= int (s.size ())) {
213 FilmPlayer::update ()
215 set_button_states ();
220 FilmPlayer::set_status ()
222 PlayerManager::State s = PlayerManager::instance()->state ();
226 case PlayerManager::QUIESCENT:
229 case PlayerManager::PLAYING:
230 m << "<span foreground=\"red\" weight=\"bold\">PLAYING</span>";
232 case PlayerManager::PAUSED:
233 m << "<b>Paused</b>";
237 _ignore_position_changed = true;
239 if (s != PlayerManager::QUIESCENT) {
240 float const p = PlayerManager::instance()->position ();
241 if (_last_play_fs->frames_per_second != 0 && _last_play_fs->length != 0) {
242 m << " <i>(" << seconds_to_hms (_last_play_fs->length / _last_play_fs->frames_per_second - p) << " remaining)</i>";
245 _position.set_value (p);
247 _position.set_value (0);
250 _ignore_position_changed = false;
252 _status.set_markup (m.str ());
256 FilmPlayer::position_changed ()
258 if (_ignore_position_changed) {
262 PlayerManager::instance()->set_position (_position.get_value ());
266 FilmPlayer::format_position (double v)
268 return seconds_to_hms (v);
272 FilmPlayer::update_screens ()
274 string const c = _screen.get_active_text ();
278 vector<shared_ptr<Screen> > const scr = Config::instance()->screens ();
279 bool have_last_active_text = false;
280 for (vector<shared_ptr<Screen> >::const_iterator i = scr.begin(); i != scr.end(); ++i) {
281 _screen.append_text ((*i)->name ());
282 if ((*i)->name() == c) {
283 have_last_active_text = true;
287 if (have_last_active_text) {
288 _screen.set_active_text (c);
289 } else if (!scr.empty ()) {
290 _screen.set_active (0);
295 FilmPlayer::film_changed (Film::Property p)
297 if (p == Film::CONTENT) {
303 FilmPlayer::setup_visibility ()
309 widget().property_visible() = (_film->content_type() == VIDEO);