4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5 * Copyright (C) 2003-2016 Cinelerra CV contributors
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bcsignals.h"
25 #include "condition.h"
27 #include "edlsession.h"
28 #include "localsession.h"
29 #include "playbackengine.h"
30 #include "preferences.h"
32 #include "transportque.h"
35 TransportCommand::TransportCommand(Preferences *preferences)
37 // In rendering we want a master EDL so settings don't get clobbered
38 // in the middle of a job.
40 edl->create_objects();
43 this->preferences = preferences;
47 TransportCommand::~TransportCommand()
49 edl->Garbage::remove_user();
52 void TransportCommand::reset()
54 command = COMMAND_NONE;
69 EDL* TransportCommand::get_edl()
74 void TransportCommand::delete_edl()
76 edl->Garbage::remove_user();
80 void TransportCommand::new_edl()
83 edl->create_objects();
87 void TransportCommand::copy_from(TransportCommand *command)
89 this->command = command->command;
90 this->change_type = command->change_type;
91 this->edl->copy_all(command->edl);
92 this->start_position = command->start_position;
93 this->end_position = command->end_position;
94 this->playbackstart = command->playbackstart;
95 this->realtime = command->realtime;
96 this->resume = command->resume;
97 this->locked = command->locked;
98 this->toggle_audio = command->toggle_audio;
99 this->loop_play = command->loop_play;
100 this->displacement = command->displacement;
101 this->speed = command->speed;
104 TransportCommand& TransportCommand::operator=(TransportCommand &command)
110 int TransportCommand::single_frame(int command)
112 return (command == SINGLE_FRAME_FWD || command == SINGLE_FRAME_REWIND ||
113 command == CURRENT_FRAME || command == LAST_FRAME);
116 int TransportCommand::get_direction(int command)
119 case SINGLE_FRAME_FWD:
126 case SINGLE_FRAME_REWIND:
139 float TransportCommand::get_speed(int command, float speed)
141 // fast = 2.0, slow = 0.5
142 // float my_fast_speed = 2.0;
143 // float my_slow_speed = 0.5;
144 float my_fast_speed = preferences->fast_speed;
145 float my_slow_speed = preferences->slow_speed;
150 return speed ? speed : my_slow_speed;
154 case SINGLE_FRAME_FWD:
155 case SINGLE_FRAME_REWIND:
162 return speed ? speed : my_fast_speed;
168 // Assume starting without pause
169 void TransportCommand::set_playback_range(EDL *edl, int use_inout, int do_displacement)
171 if( !edl ) edl = this->edl;
172 double length = edl->tracks->total_playable_length();
173 double frame_period = 1.0 / edl->session->frame_rate;
176 start_position = use_inout && edl->local_session->inpoint_valid() ?
177 edl->local_session->get_inpoint() :
178 !loop_play ? edl->local_session->get_selectionstart(1) : 0;
179 end_position = use_inout && edl->local_session->outpoint_valid() ?
180 edl->local_session->get_outpoint() :
181 !loop_play ? edl->local_session->get_selectionend(1) : length;
182 if( start_position >= length )
183 length = edl->tracks->total_length();
185 if( command == REWIND ) {
186 start_position = end_position = 0;
187 command = CURRENT_FRAME;
189 else if( command == GOTO_END ) {
190 start_position = end_position = length;
191 command = LAST_FRAME;
193 else if( !use_inout && EQUIV(start_position, end_position) ) {
194 // starting play at or past end_position, play to end_position of media (for mixers)
199 end_position = length;
200 // this prevents a crash if start_position position is after the loop when playing forwards
201 if( edl->local_session->loop_playback &&
202 start_position > edl->local_session->loop_end ) {
203 start_position = edl->local_session->loop_start;
205 displacement = realtime && do_displacement ? frame_period : 0;
212 // this prevents a crash if start_position position is before the loop when playing backwards
213 if( edl->local_session->loop_playback &&
214 end_position <= edl->local_session->loop_start ) {
215 end_position = edl->local_session->loop_end;
219 case SINGLE_FRAME_FWD:
220 displacement = realtime && do_displacement ? frame_period : 0;
223 end_position = start_position + frame_period;
226 case SINGLE_FRAME_REWIND:
227 start_position = end_position - frame_period;
230 start_position += displacement;
231 end_position += displacement;
233 // if( start_position < 0 )
234 // start_position = 0;
235 // if( end_position > length )
236 // end_position = length;
237 if( end_position < start_position )
238 end_position = start_position;
240 playbackstart = get_direction() == PLAY_FORWARD ?
241 start_position : end_position;
244 void TransportCommand::playback_range_adjust_inout()
246 if(edl->local_session->inpoint_valid() ||
247 edl->local_session->outpoint_valid())
249 playback_range_inout();
253 void TransportCommand::playback_range_inout()
255 if(edl->local_session->inpoint_valid())
256 start_position = edl->local_session->get_inpoint();
260 if(edl->local_session->outpoint_valid())
261 end_position = edl->local_session->get_outpoint();
263 end_position = edl->tracks->total_playable_length();
264 if( start_position >= end_position )
265 end_position = edl->tracks->total_length();
269 void TransportCommand::playback_range_project()
272 end_position = edl->tracks->total_playable_length();
275 void TransportCommand::playback_range_1frame()
277 start_position = end_position = edl->local_session->get_selectionstart(1);
278 if( edl->session->frame_rate > 0 ) end_position += 1./edl->session->frame_rate;