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
23 #include "bcsignals.h"
25 #include "commonrender.h"
26 #include "condition.h"
28 #include "edlsession.h"
30 #include "localsession.h"
31 #include "mainsession.h"
36 #include "playabletracks.h"
37 #include "preferences.h"
38 #include "renderengine.h"
41 #include "transportque.h"
42 #include "virtualconsole.h"
44 CommonRender::CommonRender(RenderEngine *renderengine)
47 this->renderengine = renderengine;
49 start_lock = new Condition(0, "CommonRender::start_lock");
52 CommonRender::~CommonRender()
57 for(int i = 0; i < total_modules; i++)
64 void CommonRender::reset_parameters()
75 void CommonRender::arm_command()
77 int64_t temp_length = 1;
79 current_position = tounits(renderengine->command->playbackstart, 0);
80 if(renderengine->command->realtime) init_output_buffers();
82 if(test_reconfigure(current_position, temp_length))
88 vconsole->start_playback();
98 void CommonRender::create_modules()
100 // Create a module for every track, playable or not
101 Track *current = renderengine->get_edl()->tracks->first;
103 // printf("CommonRender::create_modules %d modules=%p total_modules=%d\n",
110 total_modules = get_total_tracks();
111 modules = new Module*[total_modules];
113 // printf("CommonRender::create_modules %d total_modules=%d\n",
116 for(module = 0; module < total_modules && current; current = NEXT)
118 if(current->data_type == data_type)
120 modules[module] = new_module(current);
121 modules[module]->create_objects();
127 // Update changes in plugins for existing modules
129 for(module = 0; module < total_modules; module++)
131 modules[module]->create_objects();
136 void CommonRender::start_plugins()
138 // Only start if virtual console was created
141 for(int i = 0; i < total_modules; i++)
143 modules[i]->render_init();
148 void CommonRender::stop_plugins()
150 for(int i = 0; i < total_modules; i++)
152 modules[i]->render_stop();
156 int CommonRender::test_reconfigure(int64_t position, int64_t &length)
158 if(!vconsole) return 1;
159 if(!modules) return 1;
161 return vconsole->test_reconfigure(position, length);
165 void CommonRender::build_virtual_console()
167 // Create new virtual console object
170 vconsole = new_vconsole_object();
174 vconsole->create_objects();
177 void CommonRender::start_command()
179 if(renderengine->command->realtime)
181 Thread::set_realtime(renderengine->get_edl()->session->real_time_playback &&
182 data_type == TRACK_AUDIO);
184 start_lock->lock("CommonRender::start_command");
188 void CommonRender::interrupt_playback()
193 int CommonRender::restart_playback()
195 //printf("CommonRender::restart_playback %d\n", __LINE__);
198 build_virtual_console();
201 //printf("CommonRender::restart_playback %d\n", __LINE__);
209 void CommonRender::delete_vconsole()
211 if(vconsole) delete vconsole;
215 int CommonRender::get_boundaries(int64_t ¤t_render_length)
217 int64_t loop_end = tounits(renderengine->get_edl()->local_session->loop_end, 1);
218 int64_t loop_start = tounits(renderengine->get_edl()->local_session->loop_start, 0);
219 int64_t start_position = tounits(renderengine->command->start_position, 0);
220 int64_t end_position = tounits(renderengine->command->end_position, 1);
223 // test absolute boundaries if no loop and not infinite
224 if(renderengine->command->single_frame() ||
225 (!renderengine->get_edl()->local_session->loop_playback &&
226 !renderengine->command->infinite))
228 if(renderengine->command->get_direction() == PLAY_FORWARD)
230 if(current_position + current_render_length >= end_position)
232 current_render_length = end_position - current_position;
233 if(current_render_length <= 0) done = 1;
239 if(current_position - current_render_length <= start_position)
241 current_render_length = current_position - start_position;
242 if(current_render_length <= 0) done = 1;
247 // test against loop boundaries
248 if(!renderengine->command->single_frame() &&
249 renderengine->get_edl()->local_session->loop_playback &&
250 !renderengine->command->infinite)
252 if(renderengine->command->get_direction() == PLAY_FORWARD)
254 int64_t segment_end = current_position + current_render_length;
255 if(segment_end > loop_end)
257 current_render_length = loop_end - current_position;
262 int64_t segment_end = current_position - current_render_length;
263 if(segment_end < loop_start)
265 current_render_length = current_position - loop_start;
270 if(renderengine->command->single_frame())
271 current_render_length = 1;
273 if(current_render_length < 0) current_render_length = 0;
277 void CommonRender::run()
279 start_lock->unlock();
282 int64_t CommonRender::tounits(double position, int round)
284 return (int64_t)position;
287 double CommonRender::fromunits(int64_t position)
289 return (double)position;
292 int CommonRender::advance_position(int64_t current_render_length)
294 int64_t loop_end = tounits(renderengine->get_edl()->local_session->loop_end, 1);
295 int64_t loop_start = tounits(renderengine->get_edl()->local_session->loop_start, 0);
296 int64_t start_position = tounits(renderengine->command->start_position, 0);
297 int64_t end_position = tounits(renderengine->command->end_position, 1);
298 int direction = renderengine->command->get_direction();
300 // advance the playback position
301 if(direction == PLAY_REVERSE)
302 current_position -= current_render_length;
304 current_position += current_render_length;
307 if(renderengine->get_edl()->local_session->loop_playback &&
308 !renderengine->command->infinite)
310 if(direction == PLAY_REVERSE)
312 if(current_position <= loop_start)
313 current_position = loop_end;
317 if(current_position >= loop_end)
318 current_position = loop_start + (current_position - loop_end);
322 // test end of file again
324 if( (direction == PLAY_FORWARD && current_position >= end_position) ||
325 (direction == PLAY_REVERSE && current_position <= start_position) )