4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
24 #include "commonrender.h"
25 #include "condition.h"
27 #include "edlsession.h"
29 #include "localsession.h"
30 #include "mainsession.h"
35 #include "playabletracks.h"
36 #include "preferences.h"
37 #include "renderengine.h"
40 #include "transportque.h"
41 #include "virtualconsole.h"
43 CommonRender::CommonRender(RenderEngine *renderengine)
46 this->renderengine = renderengine;
48 start_lock = new Condition(0, "CommonRender::start_lock");
51 CommonRender::~CommonRender()
56 for(int i = 0; i < total_modules; i++)
63 void CommonRender::reset_parameters()
74 void CommonRender::arm_command()
76 int64_t temp_length = 1;
78 current_position = tounits(renderengine->command->playbackstart, 0);
79 if(renderengine->command->realtime) init_output_buffers();
81 if(test_reconfigure(current_position, temp_length))
87 vconsole->start_playback();
97 void CommonRender::create_modules()
99 // Create a module for every track, playable or not
100 Track *current = renderengine->get_edl()->tracks->first;
102 // printf("CommonRender::create_modules %d modules=%p total_modules=%d\n",
109 total_modules = get_total_tracks();
110 modules = new Module*[total_modules];
112 // printf("CommonRender::create_modules %d total_modules=%d\n",
115 for(module = 0; module < total_modules && current; current = NEXT)
117 if(current->data_type == data_type)
119 modules[module] = new_module(current);
120 modules[module]->create_objects();
126 // Update changes in plugins for existing modules
128 for(module = 0; module < total_modules; module++)
130 modules[module]->Module::create_objects();
135 void CommonRender::start_plugins()
137 // Only start if virtual console was created
140 for(int i = 0; i < total_modules; i++)
142 modules[i]->render_init();
147 void CommonRender::stop_plugins()
149 for(int i = 0; i < total_modules; i++)
151 modules[i]->render_stop();
155 int CommonRender::test_reconfigure(int64_t position, int64_t &length)
157 if(!vconsole) return 1;
158 if(!modules) return 1;
160 return vconsole->test_reconfigure(position, length);
164 void CommonRender::build_virtual_console()
166 // Create new virtual console object
169 vconsole = new_vconsole_object();
173 vconsole->create_objects();
176 void CommonRender::start_command()
178 if(renderengine->command->realtime)
180 Thread::set_realtime(renderengine->get_edl()->session->real_time_playback &&
181 data_type == TRACK_AUDIO);
183 start_lock->lock("CommonRender::start_command");
187 void CommonRender::interrupt_playback()
192 int CommonRender::restart_playback()
194 //printf("CommonRender::restart_playback %d\n", __LINE__);
197 build_virtual_console();
200 //printf("CommonRender::restart_playback %d\n", __LINE__);
208 void CommonRender::delete_vconsole()
210 if(vconsole) delete vconsole;
214 int CommonRender::get_boundaries(int64_t ¤t_render_length)
216 int64_t loop_end = tounits(renderengine->get_edl()->local_session->loop_end, 1);
217 int64_t loop_start = tounits(renderengine->get_edl()->local_session->loop_start, 0);
218 int64_t start_position = tounits(renderengine->command->start_position, 0);
219 int64_t end_position = tounits(renderengine->command->end_position, 1);
222 // test absolute boundaries if no loop and not infinite
223 if(renderengine->command->single_frame() ||
224 (!renderengine->get_edl()->local_session->loop_playback &&
225 !renderengine->command->infinite))
227 if(renderengine->command->get_direction() == PLAY_FORWARD)
229 if(current_position + current_render_length >= end_position)
231 current_render_length = end_position - current_position;
232 if(current_render_length <= 0) done = 1;
238 if(current_position - current_render_length <= start_position)
240 current_render_length = current_position - start_position;
241 if(current_render_length <= 0) done = 1;
246 // test against loop boundaries
247 if(!renderengine->command->single_frame() &&
248 renderengine->get_edl()->local_session->loop_playback &&
249 !renderengine->command->infinite)
251 if(renderengine->command->get_direction() == PLAY_FORWARD)
253 int64_t segment_end = current_position + current_render_length;
254 if(segment_end > loop_end)
256 current_render_length = loop_end - current_position;
261 int64_t segment_end = current_position - current_render_length;
262 if(segment_end < loop_start)
264 current_render_length = current_position - loop_start;
269 if(renderengine->command->single_frame() && !renderengine->command->audio_toggle)
270 current_render_length = 1;
272 if(current_render_length < 0) current_render_length = 0;
276 void CommonRender::run()
278 start_lock->unlock();
281 int64_t CommonRender::tounits(double position, int round)
283 return (int64_t)position;
286 double CommonRender::fromunits(int64_t position)
288 return (double)position;
291 int CommonRender::advance_position(int64_t current_render_length)
293 int direction = renderengine->command->get_direction();
295 // advance the playback position
296 if(direction == PLAY_REVERSE)
297 current_position -= current_render_length;
299 current_position += current_render_length;
301 int64_t start_position, end_position;
302 int play_loop = renderengine->command->play_loop;
303 int loop_playback = renderengine->get_edl()->local_session->loop_playback;
304 if( play_loop || !loop_playback ) {
305 start_position = tounits(renderengine->command->start_position, 0);
306 end_position = tounits(renderengine->command->end_position, 1);
309 start_position = tounits(renderengine->get_edl()->local_session->loop_start, 0);
310 end_position = tounits(renderengine->get_edl()->local_session->loop_end, 1);
314 if( play_loop && !renderengine->command->infinite ) {
315 if( direction == PLAY_REVERSE ) {
316 if( current_position <= start_position )
317 current_position = end_position - (start_position - current_position);
320 if( current_position >= end_position )
321 current_position = start_position + (current_position - end_position);
325 // test end of file again
326 if( (direction == PLAY_FORWARD && current_position >= end_position) ||
327 (direction == PLAY_REVERSE && current_position <= start_position) )