add new boxblur plugin, mods to videoscope, fix segv for menu btns kfrm-tweak/kfrm...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / transportque.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 "bcsignals.h"
23 #include "clip.h"
24 #include "condition.h"
25 #include "edl.h"
26 #include "edlsession.h"
27 #include "localsession.h"
28 #include "playbackengine.h"
29 #include "tracks.h"
30 #include "transportque.h"
31
32 TransportCommand::TransportCommand()
33 {
34 // In rendering we want a master EDL so settings don't get clobbered
35 // in the middle of a job.
36         edl = new EDL;
37         edl->create_objects();
38         command = 0;
39         change_type = 0;
40         reset();
41 }
42
43 TransportCommand::~TransportCommand()
44 {
45         edl->Garbage::remove_user();
46 }
47
48 void TransportCommand::reset()
49 {
50         command = COMMAND_NONE;
51         change_type = 0;
52         playbackstart = 0;
53         start_position = 0;
54         end_position = 0;
55         infinite = 0;
56         realtime = 0;
57         resume = 0;
58         locked = 0;
59         toggle_audio = 0;
60         loop_play = 0;
61         displacement = 0;
62         speed = 0;
63 }
64
65 EDL* TransportCommand::get_edl()
66 {
67         return edl;
68 }
69
70 void TransportCommand::delete_edl()
71 {
72         edl->Garbage::remove_user();
73         edl = 0;
74 }
75
76 void TransportCommand::new_edl()
77 {
78         edl = new EDL;
79         edl->create_objects();
80 }
81
82
83 void TransportCommand::copy_from(TransportCommand *command)
84 {
85         this->command = command->command;
86         this->change_type = command->change_type;
87         this->edl->copy_all(command->edl);
88         this->start_position = command->start_position;
89         this->end_position = command->end_position;
90         this->playbackstart = command->playbackstart;
91         this->realtime = command->realtime;
92         this->resume = command->resume;
93         this->locked = command->locked;
94         this->toggle_audio = command->toggle_audio;
95         this->loop_play = command->loop_play;
96         this->displacement = command->displacement;
97         this->speed = command->speed;
98 }
99
100 TransportCommand& TransportCommand::operator=(TransportCommand &command)
101 {
102         copy_from(&command);
103         return *this;
104 }
105
106 int TransportCommand::single_frame(int command)
107 {
108         return (command == SINGLE_FRAME_FWD || command == SINGLE_FRAME_REWIND ||
109                 command == CURRENT_FRAME || command == LAST_FRAME);
110 }
111
112 int TransportCommand::get_direction(int command)
113 {
114         switch(command) {
115         case SINGLE_FRAME_FWD:
116         case NORMAL_FWD:
117         case FAST_FWD:
118         case SLOW_FWD:
119         case CURRENT_FRAME:
120                 return PLAY_FORWARD;
121
122         case SINGLE_FRAME_REWIND:
123         case NORMAL_REWIND:
124         case FAST_REWIND:
125         case SLOW_REWIND:
126         case LAST_FRAME:
127                 return PLAY_REVERSE;
128
129         default:
130                 break;
131         }
132         return PLAY_FORWARD;
133 }
134
135 float TransportCommand::get_speed(int command, float speed)
136 {
137         switch(command) {
138         case SLOW_FWD:
139         case SLOW_REWIND:
140                 return speed ? speed : 0.5;
141
142         case NORMAL_FWD:
143         case NORMAL_REWIND:
144         case SINGLE_FRAME_FWD:
145         case SINGLE_FRAME_REWIND:
146         case CURRENT_FRAME:
147         case LAST_FRAME:
148                 return 1.;
149
150         case FAST_FWD:
151         case FAST_REWIND:
152                 return speed ? speed : 2.;
153         }
154
155         return 0.;
156 }
157
158 // Assume starting without pause
159 void TransportCommand::set_playback_range(EDL *edl, int use_inout, int do_displacement)
160 {
161         if( !edl ) edl = this->edl;
162         double length = edl->tracks->total_playable_length();
163         double frame_period = 1.0 / edl->session->frame_rate;
164         displacement = 0;
165
166         start_position = use_inout && edl->local_session->inpoint_valid() ?
167                 edl->local_session->get_inpoint() :
168                 !loop_play ? edl->local_session->get_selectionstart(1) : 0;
169         end_position = use_inout && edl->local_session->outpoint_valid() ?
170                 edl->local_session->get_outpoint() :
171                 !loop_play ? edl->local_session->get_selectionend(1) : length;
172         if( start_position >= length )
173                 length = edl->tracks->total_length();
174
175         if( command == REWIND ) {
176                 start_position = end_position = 0;
177                 command = CURRENT_FRAME;
178         }
179         else if( command == GOTO_END ) {
180                 start_position = end_position = length;
181                 command = LAST_FRAME;
182         }
183         else if( !use_inout && EQUIV(start_position, end_position) ) {
184 // starting play at or past end_position, play to end_position of media (for mixers)
185                 switch( command ) {
186                 case SLOW_FWD:
187                 case FAST_FWD:
188                 case NORMAL_FWD: {
189                         end_position = length;
190 // this prevents a crash if start_position position is after the loop when playing forwards
191                         if( edl->local_session->loop_playback &&
192                             start_position > edl->local_session->loop_end ) {
193                                 start_position = edl->local_session->loop_start;
194                         }
195                         displacement = realtime && do_displacement ? frame_period : 0;
196                         break; }
197
198                 case SLOW_REWIND:
199                 case FAST_REWIND:
200                 case NORMAL_REWIND:
201                         start_position = 0;
202 // this prevents a crash if start_position position is before the loop when playing backwards
203                         if( edl->local_session->loop_playback &&
204                             end_position <= edl->local_session->loop_start ) {
205                                         end_position = edl->local_session->loop_end;
206                         }
207                         break;
208
209                 case SINGLE_FRAME_FWD:
210                         displacement = realtime && do_displacement ? frame_period : 0;
211                 case CURRENT_FRAME:
212                 case LAST_FRAME:
213                         end_position = start_position + frame_period;
214                         break;
215
216                 case SINGLE_FRAME_REWIND:
217                         start_position = end_position - frame_period;
218                         break;
219                 }
220                 start_position += displacement;
221                 end_position += displacement;
222         }
223 //      if( start_position < 0 )
224 //              start_position = 0;
225 //      if( end_position > length )
226 //              end_position = length;
227         if( end_position < start_position )
228                 end_position = start_position;
229
230         playbackstart = get_direction() == PLAY_FORWARD ?
231                 start_position : end_position;
232 }
233
234 void TransportCommand::playback_range_adjust_inout()
235 {
236         if(edl->local_session->inpoint_valid() ||
237                 edl->local_session->outpoint_valid())
238         {
239                 playback_range_inout();
240         }
241 }
242
243 void TransportCommand::playback_range_inout()
244 {
245         if(edl->local_session->inpoint_valid())
246                 start_position = edl->local_session->get_inpoint();
247         else
248                 start_position = 0;
249
250         if(edl->local_session->outpoint_valid())
251                 end_position = edl->local_session->get_outpoint();
252         else {
253                 end_position = edl->tracks->total_playable_length();
254                 if( start_position >= end_position )
255                         end_position = edl->tracks->total_length();
256         }
257 }
258
259 void TransportCommand::playback_range_project()
260 {
261         start_position = 0;
262         end_position = edl->tracks->total_playable_length();
263 }
264
265 void TransportCommand::playback_range_1frame()
266 {
267         start_position = end_position = edl->local_session->get_selectionstart(1);
268         if( edl->session->frame_rate > 0 ) end_position += 1./edl->session->frame_rate;
269 }
270
271