r999: maintainers added to README_en.
[cinelerra_cv/mob.git] / cinelerra / commonrender.C
blobb71589a842e9d46f9e59e80ebe2d602130b74e0f
1 #include "auto.h"
2 #include "cache.h"
3 #include "commonrender.h"
4 #include "condition.h"
5 #include "edl.h"
6 #include "edlsession.h"
7 #include "intautos.h"
8 #include "localsession.h"
9 #include "mainsession.h"
10 #include "module.h"
11 #include "mwindow.h"
12 #include "patchbay.h"
13 #include "patch.h"
14 #include "playabletracks.h"
15 #include "preferences.h"
16 #include "renderengine.h"
17 #include "track.h"
18 #include "tracks.h"
19 #include "transportque.h"
20 #include "virtualconsole.h"
22 CommonRender::CommonRender(RenderEngine *renderengine)
23  : Thread(1, 0, 0)
25         this->renderengine = renderengine;
26         reset_parameters();
27         start_lock = new Condition(0, "CommonRender::start_lock");
30 CommonRender::~CommonRender()
32         delete_vconsole();
33         if(modules)
34         {
35                 for(int i = 0; i < total_modules; i++)
36                         delete modules[i];
37                 delete [] modules;
38         }
39         delete start_lock;
42 void CommonRender::reset_parameters()
44         total_modules = 0;
45         modules = 0;
46         vconsole = 0;
47         done = 0;
48         interrupt = 0;
49         last_playback = 0;
50         asynchronous = 0;
51         restart_plugins = 0;
54 void CommonRender::arm_command()
56         int64_t temp_length = 1;
58         current_position = tounits(renderengine->command->playbackstart, 0);
60         init_output_buffers();
62         last_playback = 0;
63         if(test_reconfigure(current_position, temp_length))
64         {
65                 restart_playback();
66         }
67         else
68         {
69                 vconsole->start_playback();
70         }
72         done = 0;
73         interrupt = 0;
74         last_playback = 0;
75         restart_plugins = 0;
80 void CommonRender::create_modules()
82 // Create a module for every track, playable or not
83         Track *current = renderengine->edl->tracks->first;
84         int module = 0;
86         if(!modules)
87         {
88                 total_modules = get_total_tracks();
89                 modules = new Module*[total_modules];
91                 for(module = 0; module < total_modules && current; current = NEXT)
92                 {
93                         if(current->data_type == data_type)
94                         {
95                                 modules[module] = new_module(current);
96                                 modules[module]->create_objects();
97                                 module++;
98                         }
99                 }
100         }
101         else
102 // Update changes in plugins for existing modules
103         {
104                 for(module = 0; module < total_modules; module++)
105                 {
106                         modules[module]->create_objects();
107                 }
108         }
111 void CommonRender::start_plugins()
113 // Only start if virtual console was created
114         if(restart_plugins)
115         {
116                 for(int i = 0; i < total_modules; i++)
117                 {
118                         modules[i]->render_init();
119                 }
120         }
123 void CommonRender::stop_plugins()
125         for(int i = 0; i < total_modules; i++)
126         {
127                 modules[i]->render_stop();
128         }
131 int CommonRender::test_reconfigure(int64_t position, int64_t &length)
133         if(!vconsole) return 1;
134         if(!modules) return 1;
135         
136         return vconsole->test_reconfigure(position, length, last_playback);
140 void CommonRender::build_virtual_console()
142 // Create new virtual console object
143         if(!vconsole)
144         {
145                 vconsole = new_vconsole_object();
146         }
148 // Create nodes
149         vconsole->create_objects();
152 void CommonRender::start_command()
154         if(renderengine->command->realtime)
155         {
156                 Thread::set_realtime(renderengine->edl->session->real_time_playback &&
157                         data_type == TRACK_AUDIO);
158                 Thread::start();
159                 start_lock->lock("CommonRender::start_command");
160         }
163 int CommonRender::restart_playback()
165         delete_vconsole();
166         create_modules();
167         build_virtual_console();
168         start_plugins();
170         done = 0;
171         interrupt = 0;
172         last_playback = 0;
173         restart_plugins = 0;
174         return 0;
177 void CommonRender::delete_vconsole()
179         if(vconsole) delete vconsole;
180         vconsole = 0;
183 int CommonRender::get_boundaries(int64_t &current_render_length)
185         int64_t loop_end = tounits(renderengine->edl->local_session->loop_end, 1);
186         int64_t loop_start = tounits(renderengine->edl->local_session->loop_start, 0);
187         int64_t start_position = tounits(renderengine->command->start_position, 0);
188         int64_t end_position = tounits(renderengine->command->end_position, 1);
191 // test absolute boundaries if no loop and not infinite
192         if(renderengine->command->single_frame() || 
193                 (!renderengine->edl->local_session->loop_playback && 
194                 !renderengine->command->infinite))
195         {
196                 if(renderengine->command->get_direction() == PLAY_FORWARD)
197                 {
198                         if(current_position + current_render_length >= end_position)
199                         {
200                                 last_playback = 1;
201                                 current_render_length = end_position - current_position;
202                         }
203                 }
204 // reverse playback
205                 else               
206                 {
207                         if(current_position - current_render_length <= start_position)
208                         {
209                                 last_playback = 1;
210                                 current_render_length = current_position - start_position;
211                         }
212                 }
213         }
215 // test against loop boundaries
216         if(!renderengine->command->single_frame() &&
217                 renderengine->edl->local_session->loop_playback && 
218                 !renderengine->command->infinite)
219         {
220                 if(renderengine->command->get_direction() == PLAY_FORWARD)
221                 {
222                         int64_t segment_end = current_position + current_render_length;
223                         if(segment_end > loop_end)
224                         {
225                                 current_render_length = loop_end - current_position;
226                         }
227                 }
228                 else
229                 {
230                         int64_t segment_end = current_position - current_render_length;
231                         if(segment_end < loop_start)
232                         {
233                                 current_render_length = current_position - loop_start;
234                         }
235                 }
236         }
238         if(renderengine->command->single_frame())
239                 current_render_length = 1;
241         if(current_render_length < 0) current_render_length = 0;
242         return 0;
245 void CommonRender::run()
247         start_lock->unlock();
270 CommonRender::CommonRender(MWindow *mwindow, RenderEngine *renderengine)
271  : Thread()
273         this->mwindow = mwindow;
274         this->renderengine = renderengine;
275         current_position = 0;
276         interrupt = 0;
277         done = 0;
278         last_playback = 0;
279         vconsole = 0;
280         asynchronous = 1;
284 int CommonRender::wait_for_completion()
286         join();
293 int CommonRender::advance_position(int64_t current_render_length)
295         int64_t loop_end = tounits(renderengine->edl->local_session->loop_end, 1);
296         int64_t loop_start = tounits(renderengine->edl->local_session->loop_start, 0);
298 // advance the playback position
299         if(renderengine->command->get_direction() == PLAY_REVERSE)
300                 current_position -= current_render_length;
301         else
302                 current_position += current_render_length;
304 // test loop again
305         if(renderengine->edl->local_session->loop_playback && 
306                 !renderengine->command->infinite)
307         {
308                 if(renderengine->command->get_direction() == PLAY_REVERSE)
309                 {
310                         if(current_position <= loop_start)
311                                 current_position = loop_end;
312                 }
313                 else
314                 {
315                         if(current_position >= loop_end)
316                                 current_position = loop_start + (current_position - loop_end);
317                 }
318         }
319         return 0;
322 int64_t CommonRender::tounits(double position, int round)
324         return (int64_t)position;
327 double CommonRender::fromunits(int64_t position)
329         return (double)position;