r807: Minor fix...
[cinelerra_cv/mob.git] / cinelerra / commonrender.C
blob5aa6b659f40b0a56085ac75f5db7cb5fabcc589b
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 int CommonRender::test_reconfigure(int64_t position, int64_t &length)
125         if(!vconsole) return 1;
126         if(!modules) return 1;
127         
128         return vconsole->test_reconfigure(position, length, last_playback);
132 void CommonRender::build_virtual_console()
134 // Create new virtual console object
135         if(!vconsole)
136         {
137                 vconsole = new_vconsole_object();
138         }
140 // Create nodes
141         vconsole->create_objects();
144 void CommonRender::start_command()
146         if(renderengine->command->realtime)
147         {
148                 Thread::set_realtime(renderengine->edl->session->real_time_playback &&
149                         data_type == TRACK_AUDIO);
150                 Thread::start();
151                 start_lock->lock("CommonRender::start_command");
152         }
155 int CommonRender::restart_playback()
157         delete_vconsole();
158         create_modules();
159         build_virtual_console();
160         start_plugins();
162         done = 0;
163         interrupt = 0;
164         last_playback = 0;
165         restart_plugins = 0;
166         return 0;
169 void CommonRender::delete_vconsole()
171         if(vconsole) delete vconsole;
172         vconsole = 0;
175 int CommonRender::get_boundaries(int64_t &current_render_length)
177         int64_t loop_end = tounits(renderengine->edl->local_session->loop_end, 1);
178         int64_t loop_start = tounits(renderengine->edl->local_session->loop_start, 0);
179         int64_t start_position = tounits(renderengine->command->start_position, 0);
180         int64_t end_position = tounits(renderengine->command->end_position, 1);
183 // test absolute boundaries if no loop and not infinite
184         if(renderengine->command->single_frame() || 
185                 (!renderengine->edl->local_session->loop_playback && 
186                 !renderengine->command->infinite))
187         {
188                 if(renderengine->command->get_direction() == PLAY_FORWARD)
189                 {
190                         if(current_position + current_render_length >= end_position)
191                         {
192                                 last_playback = 1;
193                                 current_render_length = end_position - current_position;
194                         }
195                 }
196 // reverse playback
197                 else               
198                 {
199                         if(current_position - current_render_length <= start_position)
200                         {
201                                 last_playback = 1;
202                                 current_render_length = current_position - start_position;
203                         }
204                 }
205         }
207 // test against loop boundaries
208         if(!renderengine->command->single_frame() &&
209                 renderengine->edl->local_session->loop_playback && 
210                 !renderengine->command->infinite)
211         {
212                 if(renderengine->command->get_direction() == PLAY_FORWARD)
213                 {
214                         int64_t segment_end = current_position + current_render_length;
215                         if(segment_end > loop_end)
216                         {
217                                 current_render_length = loop_end - current_position;
218                         }
219                 }
220                 else
221                 {
222                         int64_t segment_end = current_position - current_render_length;
223                         if(segment_end < loop_start)
224                         {
225                                 current_render_length = current_position - loop_start;
226                         }
227                 }
228         }
230         if(renderengine->command->single_frame())
231                 current_render_length = 1;
233         if(current_render_length < 0) current_render_length = 0;
234         return 0;
237 void CommonRender::run()
239         start_lock->unlock();
262 CommonRender::CommonRender(MWindow *mwindow, RenderEngine *renderengine)
263  : Thread()
265         this->mwindow = mwindow;
266         this->renderengine = renderengine;
267         current_position = 0;
268         interrupt = 0;
269         done = 0;
270         last_playback = 0;
271         vconsole = 0;
272         asynchronous = 1;
276 int CommonRender::wait_for_completion()
278         join();
285 int CommonRender::advance_position(int64_t current_render_length)
287         int64_t loop_end = tounits(renderengine->edl->local_session->loop_end, 1);
288         int64_t loop_start = tounits(renderengine->edl->local_session->loop_start, 0);
290 // advance the playback position
291         if(renderengine->command->get_direction() == PLAY_REVERSE)
292                 current_position -= current_render_length;
293         else
294                 current_position += current_render_length;
296 // test loop again
297         if(renderengine->edl->local_session->loop_playback && 
298                 !renderengine->command->infinite)
299         {
300                 if(renderengine->command->get_direction() == PLAY_REVERSE)
301                 {
302                         if(current_position <= loop_start)
303                                 current_position = loop_end;
304                 }
305                 else
306                 {
307                         if(current_position >= loop_end)
308                                 current_position = loop_start + (current_position - loop_end);
309                 }
310         }
311         return 0;
314 int64_t CommonRender::tounits(double position, int round)
316         return (int64_t)position;
319 double CommonRender::fromunits(int64_t position)
321         return (double)position;