initial commit
[goodguy/history.git] / cinelerra-5.0 / cinelerra / playtransport.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
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.
10  * 
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.
15  * 
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
19  * 
20  */
21
22 #include "edl.h"
23 #include "keys.h"
24 #include "language.h"
25 #include "localsession.h"
26 #include "mwindow.h"
27 #include "mwindowgui.h"
28 #include "playbackengine.h"
29 #include "playtransport.h"
30 #include "preferences.h"
31 #include "theme.h"
32 #include "transportque.h"
33 #include "vframe.h"
34
35
36
37 PlayTransport::PlayTransport(MWindow *mwindow, 
38         BC_WindowBase *subwindow, 
39         int x, 
40         int y)
41 {
42         this->subwindow = subwindow;
43         this->mwindow = mwindow;
44         this->x = x;
45         this->y = y;
46         this->engine = 0;
47         this->status = 0;
48         this->using_inout = 0;
49 }
50
51
52 PlayTransport::~PlayTransport()
53 {
54         delete forward_play;
55         delete frame_forward_play;
56         delete reverse_play;
57         delete frame_reverse_play;
58         delete fast_reverse;
59         delete fast_play;
60         delete rewind_button;
61         delete stop_button;
62         delete end_button;
63 }
64
65 void PlayTransport::set_engine(PlaybackEngine *engine)
66 {
67         this->engine = engine;
68 }
69
70 int PlayTransport::get_transport_width(MWindow *mwindow)
71 {
72         return mwindow->theme->get_image_set("stop")[0]->get_w() * 7 +
73                 mwindow->theme->get_image_set("rewind")[0]->get_w() * 2;
74 }
75
76 void PlayTransport::create_objects()
77 {
78         int x = this->x, y = this->y;
79         subwindow->add_subwindow(rewind_button = new RewindButton(mwindow, this, x, y));
80         x += rewind_button->get_w();
81         subwindow->add_subwindow(fast_reverse = new FastReverseButton(mwindow, this, x, y)); 
82         x += fast_reverse->get_w();
83         subwindow->add_subwindow(reverse_play = new ReverseButton(mwindow, this, x, y)); 
84         x += reverse_play->get_w();
85         subwindow->add_subwindow(frame_reverse_play = new FrameReverseButton(mwindow, this, x, y)); 
86         x += frame_reverse_play->get_w();
87         subwindow->add_subwindow(stop_button = new StopButton(mwindow, this, x, y)); 
88         x += stop_button->get_w();
89         subwindow->add_subwindow(frame_forward_play = new FramePlayButton(mwindow, this, x, y)); 
90         x += frame_forward_play->get_w();
91         subwindow->add_subwindow(forward_play = new PlayButton(mwindow, this, x, y)); 
92         x += forward_play->get_w();
93         subwindow->add_subwindow(fast_play = new FastPlayButton(mwindow, this, x, y)); 
94         x += fast_play->get_w();
95         subwindow->add_subwindow(end_button = new EndButton(mwindow, this, x, y)); 
96         x += end_button->get_w();
97
98         reverse = 0;
99         speed = 0;
100
101 }
102
103 void PlayTransport::reposition_buttons(int x, int y)
104 {
105         this->x = x;
106         this->y = y;
107         rewind_button->reposition_window(x, y);
108         x += rewind_button->get_w();
109         fast_reverse->reposition_window(x, y);
110         x += fast_reverse->get_w();
111         reverse_play->reposition_window(x, y);
112         x += reverse_play->get_w();
113         frame_reverse_play->reposition_window(x, y);
114         x += frame_reverse_play->get_w();
115         stop_button->reposition_window(x, y);
116         x += stop_button->get_w();
117         frame_forward_play->reposition_window(x, y);
118         x += frame_forward_play->get_w();
119         forward_play->reposition_window(x, y);
120         x += forward_play->get_w();
121         fast_play->reposition_window(x, y);
122         x += fast_play->get_w();
123         end_button->reposition_window(x, y);
124         x += end_button->get_w();
125 }
126
127 int PlayTransport::get_w()
128 {
129         return end_button->get_x() + end_button->get_w() - rewind_button->get_x();
130 }
131
132 int PlayTransport::flip_vertical(int vertical, int &x, int &y)
133 {
134         if(vertical)
135         {
136                 rewind_button->reposition_window(x, y); 
137                 y += rewind_button->get_h();
138                 fast_reverse->reposition_window(x, y); 
139                 y += fast_reverse->get_h();
140                 reverse_play->reposition_window(x, y); 
141                 y += reverse_play->get_h();
142                 frame_reverse_play->reposition_window(x, y); 
143                 y += frame_reverse_play->get_h();
144                 stop_button->reposition_window(x, y); 
145                 y += stop_button->get_h();
146                 frame_forward_play->reposition_window(x, y); 
147                 y += frame_forward_play->get_h();
148                 forward_play->reposition_window(x, y); 
149                 y += forward_play->get_h();
150                 fast_play->reposition_window(x, y); 
151                 y += fast_play->get_h();
152                 end_button->reposition_window(x, y); 
153                 y += end_button->get_h();
154         }
155         else
156         {
157                 rewind_button->reposition_window(x, y - 2); 
158                 x += rewind_button->get_w();
159                 fast_reverse->reposition_window(x, y - 2); 
160                 x += fast_reverse->get_w();
161                 reverse_play->reposition_window(x, y - 2); 
162                 x += reverse_play->get_w();
163                 frame_reverse_play->reposition_window(x, y - 2); 
164                 x += frame_reverse_play->get_w();
165                 stop_button->reposition_window(x, y - 2); 
166                 x += stop_button->get_w();
167                 frame_forward_play->reposition_window(x, y - 2); 
168                 x += frame_forward_play->get_w();
169                 forward_play->reposition_window(x, y - 2); 
170                 x += forward_play->get_w();
171                 fast_play->reposition_window(x, y - 2); 
172                 x += fast_play->get_w();
173                 end_button->reposition_window(x, y - 2); 
174                 x += end_button->get_w();
175         }
176
177         return 0;
178 }
179
180 int PlayTransport::keypress_event()
181 {
182         int result = 1;
183         if(subwindow->shift_down())
184         {
185                 switch(subwindow->get_keypress())
186                 {
187                         case END:
188                                 subwindow->lock_window("PlayTransport::keypress_event 1");
189                                 goto_end();                                   
190                                 subwindow->unlock_window();
191                                 break;
192                         case HOME:
193                                 subwindow->lock_window("PlayTransport::keypress_event 2");
194                                 goto_start();                                 
195                                 subwindow->unlock_window();
196                                 break;
197                         default:
198                                 result = 0;
199                                 break;
200                 }
201                 return result;
202         }
203
204 // Set playback range to in/out points if CTRL is down
205         int use_inout = 0;
206         if(subwindow->ctrl_down())
207         {
208                 use_inout = 1;
209         }
210         using_inout = use_inout;
211         subwindow->unlock_window();
212
213
214         switch(subwindow->get_keypress())
215         {
216                 case KPPLUS:    handle_transport(FAST_REWIND, 0, use_inout);            break;
217                 case KP6:       handle_transport(NORMAL_REWIND, 0, use_inout);          break;
218                 case KP5:       handle_transport(SLOW_REWIND, 0, use_inout);            break;
219                 case KP4:       handle_transport(SINGLE_FRAME_REWIND, 0, use_inout);    break;
220                 case KP1:       handle_transport(SINGLE_FRAME_FWD, 0, use_inout);       break;
221                 case KP2:       handle_transport(SLOW_FWD, 0, use_inout);               break;
222                 case KP3:       handle_transport(NORMAL_FWD, 0, use_inout);             break;
223                 case KPENTER:   handle_transport(FAST_FWD, 0, use_inout);               break;
224                 case KPINS:     handle_transport(STOP, 0, use_inout);                   break;
225                 case ' ': {
226                         int prev_command = engine->command->command;
227                         int new_command = prev_command == COMMAND_NONE ||
228                                         prev_command == CURRENT_FRAME ||
229                                         prev_command == PAUSE ||
230                                         prev_command == STOP ? NORMAL_FWD : STOP;
231                                 handle_transport(new_command, 0, use_inout);            break;
232                           }
233                 case 'k':       handle_transport(STOP, 0, use_inout);                   break;
234                 case END:
235                         subwindow->lock_window("PlayTransport::keypress_event 3");
236                         goto_end();                                   
237                         subwindow->unlock_window();
238                         break;
239                 case HOME:
240                         subwindow->lock_window("PlayTransport::keypress_event 4");
241                         goto_start();                                 
242                         subwindow->unlock_window();
243                         break;
244                 default:
245                         result = 0; 
246                         break;
247         }
248
249         subwindow->lock_window("PlayTransport::keypress_event 5");
250
251         return result;
252 }
253
254
255 void PlayTransport::goto_start()
256 {
257         handle_transport(REWIND, 1, 0);
258 }
259
260 void PlayTransport::goto_end()
261 {
262         handle_transport(GOTO_END, 1, 0);
263 }
264
265
266
267 void PlayTransport::handle_transport(int command, 
268         int wait_tracking,
269         int use_inout,
270         int update_refresh)
271 {
272         if(!get_edl()) return;
273
274 // Stop requires transferring the output buffer to a refresh buffer.
275         int do_stop = 0;
276 //printf("PlayTransport::handle_transport 1 %d\n", command);
277         int prev_command = engine->command->command;
278         int prev_direction = engine->command->get_direction();
279         int prev_single_frame = engine->command->single_frame();
280
281 // Dispatch command
282         switch(command)
283         {
284 // Commands that play back
285                 case FAST_REWIND:
286                 case NORMAL_REWIND:
287                 case SLOW_REWIND:
288                 case SINGLE_FRAME_REWIND:
289                 case SINGLE_FRAME_FWD:
290                 case SLOW_FWD:
291                 case NORMAL_FWD:
292                 case FAST_FWD:
293 // Same direction pressed twice.  Stop
294                         if(prev_command == command && 
295                                 !prev_single_frame)
296                         {
297                                 do_stop = 1;
298                         }
299                         else
300 // Resume or change direction
301                         if(prev_command != STOP &&
302                                 prev_command != COMMAND_NONE &&
303                                 prev_command != SINGLE_FRAME_FWD &&
304                                 prev_command != SINGLE_FRAME_REWIND)
305                         {
306                                 engine->que->send_command(STOP,
307                                         CHANGE_NONE, 
308                                         0,
309                                         0,
310                                         0,
311                                         0);
312                                 engine->interrupt_playback(wait_tracking);
313                                 engine->que->send_command(command,
314                                         CHANGE_NONE, 
315                                         get_edl(),
316                                         1,
317                                         1,
318                                         use_inout);
319                         }
320                         else
321 // Start from scratch
322                         {
323                                 engine->que->send_command(command,
324                                         CHANGE_NONE, 
325                                         get_edl(),
326                                         1,
327                                         0,
328                                         use_inout);
329                         }
330                         break;
331
332 // Commands that stop
333                 case STOP:
334                         do_stop = 1;
335                         break;
336
337                 case REWIND:
338                 case GOTO_END:
339                         engine->que->send_command(STOP,
340                                 CHANGE_NONE, 
341                                 0,
342                                 0,
343                                 0,
344                                 0);
345                         engine->interrupt_playback(wait_tracking);
346                         break;
347         }
348
349         if(do_stop)
350         {
351                 engine->que->send_command(STOP,
352                         CHANGE_NONE, 
353                         0,
354                         0,
355                         0,
356                         0);
357                 engine->interrupt_playback(wait_tracking);
358 // This is necessary to get an OpenGL output buffer
359 // printf("PlayTransport::handle_transport 2 update_refresh=%d prev_command=%d prev_direction=%d\n", 
360 // update_refresh, prev_command, prev_direction);
361                 if(!prev_single_frame && 
362                         update_refresh &&
363                         prev_command != STOP &&
364                         prev_command != COMMAND_NONE)
365                 {
366                         engine->que->send_command(
367                                 (prev_direction == PLAY_FORWARD) ? SINGLE_FRAME_REWIND : SINGLE_FRAME_FWD,
368                                 CHANGE_NONE, 
369                                 get_edl(),
370                                 1,
371                                 0,
372                                 0);
373                 }
374         }
375 }
376
377 EDL* PlayTransport::get_edl()
378 {
379         return mwindow->edl;
380 }
381
382 int PlayTransport::pause_transport()
383 {
384         if(active_button) active_button->set_mode(PLAY_MODE);
385         return 0;
386 }
387
388
389 int PlayTransport::reset_transport()
390 {
391         fast_reverse->set_mode(PLAY_MODE);
392         reverse_play->set_mode(PLAY_MODE);
393         forward_play->set_mode(PLAY_MODE);
394         frame_reverse_play->set_mode(PLAY_MODE);
395         frame_forward_play->set_mode(PLAY_MODE);
396         fast_play->set_mode(PLAY_MODE);
397         return 0;
398 }
399
400 PTransportButton::PTransportButton(MWindow *mwindow, PlayTransport *transport, int x, int y, VFrame **data)
401  : BC_Button(x, y, data)
402 {
403         this->mwindow = mwindow;
404         this->transport = transport;
405         mode = PLAY_MODE;
406 }
407 PTransportButton::~PTransportButton()
408 {
409 }
410
411 int PTransportButton::set_mode(int mode)
412 {
413         this->mode = mode;
414         return 0;
415 }
416
417
418 RewindButton::RewindButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
419  : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("rewind"))
420 {
421         set_tooltip(_("Rewind ( Home )"));
422 }
423 int RewindButton::handle_event()
424 {
425 //      unlock_window();
426         transport->goto_start();
427 //      lock_window();
428         return 1;
429 }
430
431 FastReverseButton::FastReverseButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
432  : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("fastrev")) 
433 {
434         set_tooltip(_("Fast reverse ( + )"));
435 }
436 int FastReverseButton::handle_event() 
437 {
438         unlock_window();
439         transport->handle_transport(FAST_REWIND, 0, ctrl_down());
440         lock_window("FastReverseButton::handle_event");
441         return 1;
442 }
443
444 // Reverse playback normal speed
445
446 ReverseButton::ReverseButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
447  : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("reverse")) 
448 {
449         set_tooltip(_("Normal reverse ( 6 )"));
450 }
451 int ReverseButton::handle_event()
452 {
453         unlock_window();
454         transport->handle_transport(NORMAL_REWIND, 0, ctrl_down());
455         lock_window("ReverseButton::handle_event");
456         return 1;
457 }
458
459 // Reverse playback one frame
460
461 FrameReverseButton::FrameReverseButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
462  : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("framerev"))
463 {
464         set_tooltip(_("Frame reverse ( 4 )"));
465 }
466 int FrameReverseButton::handle_event()
467 {
468         unlock_window();
469         transport->handle_transport(SINGLE_FRAME_REWIND, 0, ctrl_down());
470         lock_window("FrameReverseButton::handle_event");
471         return 1;
472 }
473
474 // forward playback normal speed
475
476 PlayButton::PlayButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
477  : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("play")) 
478 {
479         set_tooltip(_("Normal forward ( 3 )"));
480 }
481 int PlayButton::handle_event()
482 {
483         unlock_window();
484         transport->handle_transport(NORMAL_FWD, 0, ctrl_down());
485         lock_window("PlayButton::handle_event");
486         return 1;
487 }
488
489
490
491 // forward playback one frame
492
493 FramePlayButton::FramePlayButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
494  : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("framefwd")) 
495 {
496         set_tooltip(_("Frame forward ( 1 )"));
497 }
498 int FramePlayButton::handle_event()
499 {
500         unlock_window();
501         transport->handle_transport(SINGLE_FRAME_FWD, 0, ctrl_down());
502         lock_window("FramePlayButton::handle_event");
503         return 1;
504 }
505
506
507
508 FastPlayButton::FastPlayButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
509  : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("fastfwd")) 
510 {
511         set_tooltip(_("Fast forward ( Enter )"));
512 }
513 int FastPlayButton::handle_event() 
514 {
515         unlock_window();
516         transport->handle_transport(FAST_FWD, 0, ctrl_down());
517         lock_window("FastPlayButton::handle_event");
518         return 1;
519 }
520
521 EndButton::EndButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
522  : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("end")) 
523 {
524         set_tooltip(_("Jump to end ( End )"));
525 }
526 int EndButton::handle_event()
527 {       
528 //      unlock_window();
529         transport->goto_end();
530 //      lock_window();
531         return 1;
532 }
533
534 StopButton::StopButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
535  : PTransportButton(mwindow, transport, x, y, mwindow->theme->get_image_set("stop")) 
536 {
537         set_tooltip(_("Stop ( 0 )"));
538 }
539 int StopButton::handle_event()
540 {
541         unlock_window();
542         transport->handle_transport(STOP, 0, 0);
543         lock_window("StopButton::handle_event");
544         return 1;
545 }
546
547
548
549 void PlayTransport::change_position(double position)
550 {
551         EDL *edl = get_edl();
552         if( !edl ) return;
553         int prev_command = engine->command->command;
554 // stop transport
555         if( prev_command != STOP && prev_command != COMMAND_NONE &&
556             prev_command != SINGLE_FRAME_FWD && prev_command != SINGLE_FRAME_REWIND ) {
557                 engine->que->send_command(STOP, CHANGE_NONE, 0, 0, 0, 0);
558                 engine->interrupt_playback(0);
559         }
560         mwindow->gui->lock_window("PlayTransport::change_position");
561         mwindow->goto_position(position);
562         mwindow->gui->unlock_window();
563 // restart command
564         switch(prev_command) {
565         case FAST_REWIND:
566         case NORMAL_REWIND:
567         case SLOW_REWIND:
568         case SLOW_FWD:
569         case NORMAL_FWD:
570         case FAST_FWD:
571                 engine->que->send_command(prev_command, CHANGE_NONE,
572                                 get_edl(), 1, 1, using_inout);
573         }
574 }
575