4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "localsession.h"
27 #include "mwindowgui.h"
28 #include "playbackengine.h"
29 #include "playtransport.h"
30 #include "preferences.h"
34 #include "transportque.h"
39 PlayTransport::PlayTransport(MWindow *mwindow,
40 BC_WindowBase *subwindow,
44 this->subwindow = subwindow;
45 this->mwindow = mwindow;
50 this->using_inout = 0;
54 PlayTransport::~PlayTransport()
57 delete frame_forward_play;
59 delete frame_reverse_play;
67 void PlayTransport::set_engine(PlaybackEngine *engine)
69 this->engine = engine;
72 int PlayTransport::get_transport_width(MWindow *mwindow)
74 return mwindow->theme->get_image_set("stop")[0]->get_w() * 7 +
75 mwindow->theme->get_image_set("rewind")[0]->get_w() * 2;
78 void PlayTransport::create_objects()
80 int x = this->x, y = this->y;
81 subwindow->add_subwindow(rewind_button = new RewindButton(mwindow, this, x, y));
82 x += rewind_button->get_w();
83 subwindow->add_subwindow(fast_reverse = new FastReverseButton(mwindow, this, x, y));
84 x += fast_reverse->get_w();
85 subwindow->add_subwindow(reverse_play = new ReverseButton(mwindow, this, x, y));
86 x += reverse_play->get_w();
87 subwindow->add_subwindow(frame_reverse_play = new FrameReverseButton(mwindow, this, x, y));
88 x += frame_reverse_play->get_w();
89 subwindow->add_subwindow(stop_button = new StopButton(mwindow, this, x, y));
90 x += stop_button->get_w();
91 subwindow->add_subwindow(frame_forward_play = new FramePlayButton(mwindow, this, x, y));
92 x += frame_forward_play->get_w();
93 subwindow->add_subwindow(forward_play = new PlayButton(mwindow, this, x, y));
94 x += forward_play->get_w();
95 subwindow->add_subwindow(fast_play = new FastPlayButton(mwindow, this, x, y));
96 x += fast_play->get_w();
97 subwindow->add_subwindow(end_button = new EndButton(mwindow, this, x, y));
98 x += end_button->get_w();
105 void PlayTransport::reposition_buttons(int x, int y)
109 rewind_button->reposition_window(x, y);
110 x += rewind_button->get_w();
111 fast_reverse->reposition_window(x, y);
112 x += fast_reverse->get_w();
113 reverse_play->reposition_window(x, y);
114 x += reverse_play->get_w();
115 frame_reverse_play->reposition_window(x, y);
116 x += frame_reverse_play->get_w();
117 stop_button->reposition_window(x, y);
118 x += stop_button->get_w();
119 frame_forward_play->reposition_window(x, y);
120 x += frame_forward_play->get_w();
121 forward_play->reposition_window(x, y);
122 x += forward_play->get_w();
123 fast_play->reposition_window(x, y);
124 x += fast_play->get_w();
125 end_button->reposition_window(x, y);
126 x += end_button->get_w();
129 int PlayTransport::get_w()
131 return end_button->get_x() + end_button->get_w() - rewind_button->get_x();
134 int PlayTransport::is_stopped()
136 return engine->is_playing_back ? 0 : 1;
139 int PlayTransport::flip_vertical(int vertical, int &x, int &y)
143 rewind_button->reposition_window(x, y);
144 y += rewind_button->get_h();
145 fast_reverse->reposition_window(x, y);
146 y += fast_reverse->get_h();
147 reverse_play->reposition_window(x, y);
148 y += reverse_play->get_h();
149 frame_reverse_play->reposition_window(x, y);
150 y += frame_reverse_play->get_h();
151 stop_button->reposition_window(x, y);
152 y += stop_button->get_h();
153 frame_forward_play->reposition_window(x, y);
154 y += frame_forward_play->get_h();
155 forward_play->reposition_window(x, y);
156 y += forward_play->get_h();
157 fast_play->reposition_window(x, y);
158 y += fast_play->get_h();
159 end_button->reposition_window(x, y);
160 y += end_button->get_h();
164 rewind_button->reposition_window(x, y - 2);
165 x += rewind_button->get_w();
166 fast_reverse->reposition_window(x, y - 2);
167 x += fast_reverse->get_w();
168 reverse_play->reposition_window(x, y - 2);
169 x += reverse_play->get_w();
170 frame_reverse_play->reposition_window(x, y - 2);
171 x += frame_reverse_play->get_w();
172 stop_button->reposition_window(x, y - 2);
173 x += stop_button->get_w();
174 frame_forward_play->reposition_window(x, y - 2);
175 x += frame_forward_play->get_w();
176 forward_play->reposition_window(x, y - 2);
177 x += forward_play->get_w();
178 fast_play->reposition_window(x, y - 2);
179 x += fast_play->get_w();
180 end_button->reposition_window(x, y - 2);
181 x += end_button->get_w();
187 int PlayTransport::keypress_event()
189 int key = subwindow->get_keypress();
190 return do_keypress(key);
193 int PlayTransport::do_keypress(int key)
196 // unqualified keys, still holding lock
206 int ctrl_key = subwindow->ctrl_down() ? 1 : 0;
207 int shft_key = subwindow->shift_down() ? 1 : 0;
208 int alt_key = subwindow->alt_down() ? 1 : 0;
209 int use_inout = ctrl_key;
210 int toggle_audio = shft_key & ~ctrl_key;
211 int loop_play = shft_key & ctrl_key;
214 int curr_command = engine->is_playing_back ? engine->command->command : STOP;
215 subwindow->unlock_window();
219 if( key >= SKEY_MIN && key <= SKEY_MAX ) {
220 speed = SHUTTLE_MAX_SPEED *
221 (key - (SKEY_MAX + SKEY_MIN)/2.f) /
222 ((SKEY_MAX - SKEY_MIN) / 2.f);
225 command = speed < 1 ? SLOW_REWIND :
226 speed > 1 ? FAST_REWIND : NORMAL_REWIND;
228 else if( speed > 0 ) {
229 command = speed < 1 ? SLOW_FWD :
230 speed > 1 ? FAST_FWD : NORMAL_FWD;
238 case KPINS: command = STOP; break;
239 case KPPLUS: command = FAST_REWIND; break;
240 case KP6: command = NORMAL_REWIND; break;
241 case KP5: command = SLOW_REWIND; break;
242 case KP4: command = SINGLE_FRAME_REWIND; break;
243 case KP1: command = SINGLE_FRAME_FWD; break;
244 case KP2: command = SLOW_FWD; break;
245 case KP3: command = NORMAL_FWD; break;
246 case KPENTER: command = FAST_FWD; break;
249 switch( curr_command ) {
255 command = NORMAL_FWD;
263 if( alt_key ) command = SINGLE_FRAME_REWIND;
266 if( alt_key ) command = SLOW_REWIND;
269 if( alt_key ) command = NORMAL_REWIND;
272 if( alt_key ) command = FAST_REWIND;
275 if( alt_key ) command = SINGLE_FRAME_FWD;
278 if( alt_key ) command = SLOW_FWD;
281 if( alt_key ) command = NORMAL_FWD;
284 if( alt_key ) command = FAST_FWD;
287 if( alt_key ) command = STOP;
291 handle_transport(command, 0, use_inout, toggle_audio, loop_play, speed);
295 subwindow->lock_window("PlayTransport::keypress_event 5");
300 void PlayTransport::goto_start()
302 handle_transport(REWIND, 1);
305 void PlayTransport::goto_end()
307 handle_transport(GOTO_END, 1);
312 void PlayTransport::handle_transport(int command, int wait_tracking,
313 int use_inout, int toggle_audio, int loop_play, float speed)
315 EDL *edl = get_edl();
317 using_inout = use_inout;
320 mwindow->handle_mixers(edl, command, wait_tracking,
321 use_inout, toggle_audio, 0, speed);
322 engine->next_command->toggle_audio = toggle_audio;
323 engine->next_command->loop_play = loop_play;
324 engine->next_command->speed = speed;
325 engine->send_command(command, edl, wait_tracking, use_inout);
328 EDL* PlayTransport::get_edl()
333 int PlayTransport::set_transport(int mode)
335 fast_reverse->set_mode(mode);
336 reverse_play->set_mode(mode);
337 forward_play->set_mode(mode);
338 frame_reverse_play->set_mode(mode);
339 frame_forward_play->set_mode(mode);
340 fast_play->set_mode(mode);
344 PTransportButton::PTransportButton(MWindow *mwindow, PlayTransport *transport, int x, int y, VFrame **data)
345 : BC_Button(x, y, data)
347 this->mwindow = mwindow;
348 this->transport = transport;
351 PTransportButton::~PTransportButton()
355 void PTransportButton::set_mode(int mode)
360 void PTransportButton::loop_mode(int dir)
362 if( mode != LOOP_MODE ) return;
363 EDL *edl = transport->get_edl();
365 PlaybackEngine *engine = transport->engine;
366 if( !engine || engine->is_playing_back ) return;
367 double position = engine->get_tracking_position();
370 if( position >= edl->tracks->total_playable_length() )
371 transport->goto_start();
375 transport->goto_end();
380 int PTransportButton::play_command(const char *lock_msg, int command)
382 int ctrl_key = transport->subwindow->ctrl_down() ? 1 : 0;
383 int shft_key = transport->subwindow->shift_down() ? 1 : 0;
384 int use_inout = ctrl_key;
385 int toggle_audio = shft_key & ~ctrl_key;
386 int loop_play = shft_key & ctrl_key;
388 transport->handle_transport(command, 0, use_inout, toggle_audio, loop_play, 0);
389 lock_window(lock_msg);
394 RewindButton::RewindButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
395 : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("rewind"))
397 set_tooltip(_("Rewind ( Home )"));
398 // *** CONTEXT_HELP ***
399 context_help_set_keyword("Transport Controls");
401 int RewindButton::handle_event()
404 transport->goto_start();
409 FastReverseButton::FastReverseButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
410 : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("fastrev"))
412 set_tooltip(_("Fast reverse ( + or Alt-p )"));
413 // *** CONTEXT_HELP ***
414 context_help_set_keyword("Transport Controls");
416 int FastReverseButton::handle_event()
418 loop_mode(PLAY_REVERSE);
419 return play_command("FastReverseButton::handle_event", FAST_REWIND);
422 // Reverse playback normal speed
424 ReverseButton::ReverseButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
425 : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("reverse"))
427 set_tooltip(_("Normal reverse ( 6 or Alt-o )"));
428 // *** CONTEXT_HELP ***
429 context_help_set_keyword("Transport Controls");
431 int ReverseButton::handle_event()
433 loop_mode(PLAY_REVERSE);
434 return play_command("ReverseButton::handle_event", NORMAL_REWIND);
437 // Reverse playback one frame
439 FrameReverseButton::FrameReverseButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
440 : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("framerev"))
442 set_tooltip(_("Frame reverse ( 4 or Alt-u )"));
443 // *** CONTEXT_HELP ***
444 context_help_set_keyword("Transport Controls");
446 int FrameReverseButton::handle_event()
449 transport->handle_transport(SINGLE_FRAME_REWIND, 0, ctrl_down());
450 lock_window("FrameReverseButton::handle_event");
454 // forward playback normal speed
456 PlayButton::PlayButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
457 : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("play"))
459 set_tooltip(_("Normal forward ( 3 or Alt-l )"));
460 // *** CONTEXT_HELP ***
461 context_help_set_keyword("Transport Controls");
463 int PlayButton::handle_event()
465 loop_mode(PLAY_FORWARD);
466 return play_command("PlayButton::handle_event", NORMAL_FWD);
471 // forward playback one frame
473 FramePlayButton::FramePlayButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
474 : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("framefwd"))
476 set_tooltip(_("Frame forward ( 1 or Alt-j )"));
477 // *** CONTEXT_HELP ***
478 context_help_set_keyword("Transport Controls");
480 int FramePlayButton::handle_event()
483 transport->handle_transport(SINGLE_FRAME_FWD, 0, ctrl_down());
484 lock_window("FramePlayButton::handle_event");
490 FastPlayButton::FastPlayButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
491 : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("fastfwd"))
493 set_tooltip(_("Fast forward ( Enter or Alt-; )"));
494 // *** CONTEXT_HELP ***
495 context_help_set_keyword("Transport Controls");
497 int FastPlayButton::handle_event()
499 loop_mode(PLAY_FORWARD);
500 return play_command("FastPlayButton::handle_event", FAST_FWD);
503 EndButton::EndButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
504 : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("end"))
506 set_tooltip(_("Jump to end ( End )"));
507 // *** CONTEXT_HELP ***
508 context_help_set_keyword("Transport Controls");
510 int EndButton::handle_event()
513 transport->goto_end();
518 StopButton::StopButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
519 : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("stop"))
521 set_tooltip(_("Stop ( 0 or Alt-m )"));
522 // *** CONTEXT_HELP ***
523 context_help_set_keyword("Transport Controls");
525 int StopButton::handle_event()
528 transport->handle_transport(STOP);
529 lock_window("StopButton::handle_event");
535 void PlayTransport::change_position(double position)
537 if( !get_edl() ) return;
538 int command = engine->command->command;
540 engine->stop_playback(0);
541 mwindow->gui->lock_window("PlayTransport::change_position");
542 mwindow->goto_position(position);
543 mwindow->gui->unlock_window();
552 engine->next_command->realtime = 1;
553 engine->next_command->resume = 1;
554 engine->transport_command(command, CHANGE_NONE, get_edl(), using_inout);