asset drag/drop to viewers, bluebanana bug, listbox fontlist highlight
[goodguy/history.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 "tracks.h"
29 #include "transportque.h"
30
31 TransportCommand::TransportCommand()
32 {
33 // In rendering we want a master EDL so settings don't get clobbered
34 // in the middle of a job.
35         edl = new EDL;
36         edl->create_objects();
37         command = 0;
38         change_type = 0;
39         reset();
40 }
41
42 TransportCommand::~TransportCommand()
43 {
44         edl->Garbage::remove_user();
45 }
46
47 void TransportCommand::reset()
48 {
49         playbackstart = 0;
50         start_position = 0;
51         end_position = 0;
52         infinite = 0;
53         realtime = 0;
54         resume = 0;
55 // Don't reset the change type for commands which don't perform the change
56         if(command != STOP) change_type = 0;
57         command = COMMAND_NONE;
58 }
59
60 EDL* TransportCommand::get_edl()
61 {
62         return edl;
63 }
64
65 void TransportCommand::delete_edl()
66 {
67         edl->Garbage::remove_user();
68         edl = 0;
69 }
70
71 void TransportCommand::new_edl()
72 {
73         edl = new EDL;
74         edl->create_objects();
75 }
76
77
78 void TransportCommand::copy_from(TransportCommand *command)
79 {
80         this->command = command->command;
81         this->change_type = command->change_type;
82         this->edl->copy_all(command->edl);
83         this->start_position = command->start_position;
84         this->end_position = command->end_position;
85         this->playbackstart = command->playbackstart;
86         this->realtime = command->realtime;
87         this->resume = command->resume;
88 }
89
90 TransportCommand& TransportCommand::operator=(TransportCommand &command)
91 {
92         copy_from(&command);
93         return *this;
94 }
95
96 int TransportCommand::single_frame()
97 {
98         return (command == SINGLE_FRAME_FWD ||
99                 command == SINGLE_FRAME_REWIND ||
100                 command == CURRENT_FRAME);
101 }
102
103
104 int TransportCommand::get_direction()
105 {
106         switch(command)
107         {
108                 case SINGLE_FRAME_FWD:
109                 case NORMAL_FWD:
110                 case FAST_FWD:
111                 case SLOW_FWD:
112                 case CURRENT_FRAME:
113                         return PLAY_FORWARD;
114
115                 case SINGLE_FRAME_REWIND:
116                 case NORMAL_REWIND:
117                 case FAST_REWIND:
118                 case SLOW_REWIND:
119                         return PLAY_REVERSE;
120
121                 default:
122                         break;
123         }
124         return PLAY_FORWARD;
125 }
126
127 float TransportCommand::get_speed()
128 {
129         switch(command)
130         {
131                 case SLOW_FWD:
132                 case SLOW_REWIND:
133                         return 0.5;
134
135                 case NORMAL_FWD:
136                 case NORMAL_REWIND:
137                 case SINGLE_FRAME_FWD:
138                 case SINGLE_FRAME_REWIND:
139                 case CURRENT_FRAME:
140                         return 1.;
141
142                 case FAST_FWD:
143                 case FAST_REWIND:
144                         return 2.;
145         }
146
147         return 0.;
148 }
149
150 // Assume starting without pause
151 void TransportCommand::set_playback_range(EDL *edl, int use_inout)
152 {
153         if(!edl) edl = this->edl;
154
155
156
157
158         switch(command)
159         {
160                 case SLOW_FWD:
161                 case FAST_FWD:
162                 case NORMAL_FWD:
163                         start_position = edl->local_session->get_selectionstart(1);
164                         if(EQUIV(edl->local_session->get_selectionend(1), edl->local_session->get_selectionstart(1)))
165                                 end_position = edl->tracks->total_playable_length();
166                         else
167                                 end_position = edl->local_session->get_selectionend(1);
168 // this prevents a crash if start position is after the loop when playing forwards
169                     if (edl->local_session->loop_playback &&
170                                 start_position > edl->local_session->loop_end)
171                         {
172                                     start_position = edl->local_session->loop_start;
173                         }
174                         break;
175
176                 case SLOW_REWIND:
177                 case FAST_REWIND:
178                 case NORMAL_REWIND:
179                         end_position = edl->local_session->get_selectionend(1);
180                         if(EQUIV(edl->local_session->get_selectionend(1), edl->local_session->get_selectionstart(1)))
181                                 start_position = 0;
182                         else
183                                 start_position = edl->local_session->get_selectionstart(1);
184
185 // this prevents a crash if start position is before the loop when playing backwards
186                         if (edl->local_session->loop_playback &&
187                                 end_position <= edl->local_session->loop_start)
188                         {
189                                         end_position = edl->local_session->loop_end;
190                         }
191                         break;
192
193                 case CURRENT_FRAME:
194                 case SINGLE_FRAME_FWD:
195                         start_position = edl->local_session->get_selectionstart(1);
196                         end_position = start_position +
197                                 1.0 /
198                                 edl->session->frame_rate;
199                         break;
200
201                 case SINGLE_FRAME_REWIND:
202                         start_position = edl->local_session->get_selectionend(1);
203                         end_position = start_position -
204                                 1.0 /
205                                 edl->session->frame_rate;
206                         break;
207         }
208
209
210         if(use_inout)
211         {
212                 if(edl->local_session->inpoint_valid())
213                         start_position = edl->local_session->get_inpoint();
214                 if(edl->local_session->outpoint_valid())
215                         end_position = edl->local_session->get_outpoint();
216         }
217
218         switch(get_direction())
219         {
220                 case PLAY_FORWARD:
221                         playbackstart = start_position;
222                         break;
223
224                 case PLAY_REVERSE:
225                         playbackstart = end_position;
226                         break;
227         }
228
229 }
230
231 void TransportCommand::playback_range_adjust_inout()
232 {
233         if(edl->local_session->inpoint_valid() ||
234                 edl->local_session->outpoint_valid())
235         {
236                 playback_range_inout();
237         }
238 }
239
240 void TransportCommand::playback_range_inout()
241 {
242         if(edl->local_session->inpoint_valid())
243                 start_position = edl->local_session->get_inpoint();
244         else
245                 start_position = 0;
246
247         if(edl->local_session->outpoint_valid())
248                 end_position = edl->local_session->get_outpoint();
249         else
250                 end_position = edl->tracks->total_playable_length();
251 }
252
253 void TransportCommand::playback_range_project()
254 {
255         start_position = 0;
256         end_position = edl->tracks->total_playable_length();
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 TransportQue::TransportQue()
275 {
276         input_lock = new Condition(1, "TransportQue::input_lock");
277         output_lock = new Condition(0, "TransportQue::output_lock", 1);
278 }
279
280 TransportQue::~TransportQue()
281 {
282         delete input_lock;
283         delete output_lock;
284 }
285
286 int TransportQue::send_command(int command,
287                 int change_type,
288                 EDL *new_edl,
289                 int realtime,
290                 int resume,
291                 int use_inout)
292 {
293         input_lock->lock("TransportQue::send_command 1");
294         this->command.command = command;
295 // Mutually exclusive operation
296         this->command.change_type |= change_type;
297         this->command.realtime = realtime;
298         this->command.resume = resume;
299
300         if(new_edl)
301         {
302 // Just change the EDL if the change requires it because renderengine
303 // structures won't point to the new EDL otherwise and because copying the
304 // EDL for every cursor movement is slow.
305                 if(change_type == CHANGE_EDL ||
306                         (uint32_t)change_type == CHANGE_ALL)
307                 {
308 // Copy EDL
309                         this->command.get_edl()->copy_all(new_edl);
310                 }
311                 else
312                 if(change_type == CHANGE_PARAMS)
313                 {
314                         this->command.get_edl()->synchronize_params(new_edl);
315                 }
316
317 // Set playback range
318                 this->command.set_playback_range(new_edl, use_inout);
319         }
320
321         input_lock->unlock();
322
323         output_lock->unlock();
324         return 0;
325 }
326
327 void TransportQue::update_change_type(int change_type)
328 {
329         input_lock->lock("TransportQue::update_change_type");
330         this->command.change_type |= change_type;
331         input_lock->unlock();
332 }