Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / cinelerra / transportque.C
blobef560df4870ee7b67e97f802cd4d1fdb8659bfd5
1 #include "bcsignals.h"
2 #include "clip.h"
3 #include "condition.h"
4 #include "edl.h"
5 #include "edlsession.h"
6 #include "localsession.h"
7 #include "tracks.h"
8 #include "transportque.h"
10 TransportCommand::TransportCommand()
12 // In rendering we want a master EDL so settings don't get clobbered
13 // in the middle of a job.
14         edl = new EDL;
15         edl->create_objects();
16         command = 0;
17         change_type = 0;
18         reset();
21 TransportCommand::~TransportCommand()
23         delete edl;
26 void TransportCommand::reset()
28         playbackstart = 0;
29         start_position = 0;
30         end_position = 0;
31         infinite = 0;
32         realtime = 0;
33         resume = 0;
34 // Don't reset the change type for commands which don't perform the change
35         if(command != STOP) change_type = 0;
36         command = COMMAND_NONE;
39 EDL* TransportCommand::get_edl()
41         return edl;
44 void TransportCommand::delete_edl()
46         delete edl;
47         edl = 0;
50 void TransportCommand::new_edl()
52         edl = new EDL;
53         edl->create_objects();
57 void TransportCommand::copy_from(TransportCommand *command)
59         this->command = command->command;
60         this->change_type = command->change_type;
61         this->edl->copy_all(command->edl);
62         this->start_position = command->start_position;
63         this->end_position = command->end_position;
64         this->playbackstart = command->playbackstart;
65         this->realtime = command->realtime;
66         this->resume = command->resume;
69 TransportCommand& TransportCommand::operator=(TransportCommand &command)
71         copy_from(&command);
72         return *this;
75 int TransportCommand::single_frame()
77         return (command == SINGLE_FRAME_FWD ||
78                 command == SINGLE_FRAME_REWIND ||
79                 command == CURRENT_FRAME);
83 int TransportCommand::get_direction()
85         switch(command)
86         {
87                 case SINGLE_FRAME_FWD:
88                 case NORMAL_FWD:
89                 case FAST_FWD:
90                 case SLOW_FWD:
91                 case CURRENT_FRAME:
92                         return PLAY_FORWARD;
93                         break;
95                 case SINGLE_FRAME_REWIND:
96                 case NORMAL_REWIND:
97                 case FAST_REWIND:
98                 case SLOW_REWIND:
99                         return PLAY_REVERSE;
100                         break;
102                 default:
103                         return PLAY_FORWARD;
104                         break;
105         }
108 float TransportCommand::get_speed()
110         switch(command)
111         {
112                 case SLOW_FWD:
113                 case SLOW_REWIND:
114                         return 0.5;
115                         break;
116                 
117                 case NORMAL_FWD:
118                 case NORMAL_REWIND:
119                 case SINGLE_FRAME_FWD:
120                 case SINGLE_FRAME_REWIND:
121                 case CURRENT_FRAME:
122                         return 1;
123                         break;
124                 
125                 case FAST_FWD:
126                 case FAST_REWIND:
127                         return 2;
128                         break;
129         }
132 // Assume starting without pause
133 void TransportCommand::set_playback_range(EDL *edl, int use_inout)
135         if(!edl) edl = this->edl;
140         switch(command)
141         {
142                 case SLOW_FWD:
143                 case FAST_FWD:
144                 case NORMAL_FWD:
145                         start_position = edl->local_session->get_selectionstart(1);
146                         if(EQUIV(edl->local_session->get_selectionend(1), edl->local_session->get_selectionstart(1)))
147                                 end_position = edl->tracks->total_playable_length();
148                         else
149                                 end_position = edl->local_session->get_selectionend(1);
150 // this prevents a crash if start position is after the loop when playing forwards
151                     if (edl->local_session->loop_playback && start_position > edl->local_session->loop_end)  
152                         {
153                                     start_position = edl->local_session->loop_start;
154                         }
155                         break;
156                 
157                 case SLOW_REWIND:
158                 case FAST_REWIND:
159                 case NORMAL_REWIND:
160                         end_position = edl->local_session->get_selectionend(1);
161                         if(EQUIV(edl->local_session->get_selectionend(1), edl->local_session->get_selectionstart(1)))
162                                 start_position = 0;
163                         else
164                                 start_position = edl->local_session->get_selectionstart(1);
165 // this prevents a crash if start position is before the loop when playing backwards
166                         if (edl->local_session->loop_playback && start_position <= edl->local_session->loop_start)
167                         {
168                                         start_position = edl->local_session->loop_end;
169                                         end_position = edl->local_session->loop_end;
170                         }
171                         break;
172                 
173                 case CURRENT_FRAME:
174                 case SINGLE_FRAME_FWD:
175                         start_position = edl->local_session->get_selectionstart(1);
176                         end_position = start_position + 
177                                 1.0 / 
178                                 edl->session->frame_rate;
179                         break;
180                 
181                 case SINGLE_FRAME_REWIND:
182                         start_position = edl->local_session->get_selectionend(1);
183                         end_position = start_position - 
184                                 1.0 / 
185                                 edl->session->frame_rate;
186                         break;
187         }
190         if(use_inout)
191         {
192                 if(edl->local_session->inpoint_valid())
193                         start_position = edl->local_session->get_inpoint();
194                 if(edl->local_session->outpoint_valid())
195                         end_position = edl->local_session->get_outpoint();
196         }
198         switch(get_direction())
199         {
200                 case PLAY_FORWARD:
201                         playbackstart = start_position;
202                         break;
204                 case PLAY_REVERSE:
205                         playbackstart = end_position;
206                         break;
207         }
211 void TransportCommand::playback_range_adjust_inout()
213         if(edl->local_session->inpoint_valid() ||
214                 edl->local_session->outpoint_valid())
215         {
216                 playback_range_inout();
217         }
220 void TransportCommand::playback_range_inout()
222         if(edl->local_session->inpoint_valid())
223                 start_position = edl->local_session->get_inpoint();
224         else
225                 start_position = 0;
227         if(edl->local_session->outpoint_valid())
228                 end_position = edl->local_session->get_outpoint();
229         else
230                 end_position = edl->tracks->total_playable_length();
233 void TransportCommand::playback_range_project()
235         start_position = 0;
236         end_position = edl->tracks->total_playable_length();
254 TransportQue::TransportQue()
256         input_lock = new Condition(1, "TransportQue::input_lock");
257         output_lock = new Condition(0, "TransportQue::output_lock", 1);
260 TransportQue::~TransportQue()
262         delete input_lock;
263         delete output_lock;
266 int TransportQue::send_command(int command, 
267                 int change_type, 
268                 EDL *new_edl, 
269                 int realtime,
270                 int resume,
271                 int use_inout)
273         input_lock->lock("TransportQue::send_command 1");
274         this->command.command = command;
275 // Mutually exclusive operation
276         this->command.change_type |= change_type;
277         this->command.realtime = realtime;
278         this->command.resume = resume;
280         if(new_edl)
281         {
282 // Just change the EDL if the change requires it because renderengine
283 // structures won't point to the new EDL otherwise and because copying the
284 // EDL for every cursor movement is slow.
285                 if(change_type == CHANGE_EDL ||
286                         change_type == CHANGE_ALL)
287                 {
288 // Copy EDL
289                         this->command.get_edl()->copy_all(new_edl);
290                 }
291                 else
292                 if(change_type == CHANGE_PARAMS)
293                 {
294                         this->command.get_edl()->synchronize_params(new_edl);
295                 }
297 // Set playback range
298                 this->command.set_playback_range(new_edl, use_inout);
299         }
301         input_lock->unlock();
303         output_lock->unlock();
304         return 0;
307 void TransportQue::update_change_type(int change_type)
309         input_lock->lock("TransportQue::update_change_type");
310         this->command.change_type |= change_type;
311         input_lock->unlock();
314 //      Local Variables:
315 //      mode: C++
316 //      c-file-style: "linux"
317 //      End: