initial commit
[goodguy/history.git] / cinelerra-5.0 / cinelerra / commonrender.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
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.
10  * 
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.
15  * 
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
19  * 
20  */
21
22 #include "auto.h"
23 #include "bcsignals.h"
24 #include "cache.h"
25 #include "commonrender.h"
26 #include "condition.h"
27 #include "edl.h"
28 #include "edlsession.h"
29 #include "intautos.h"
30 #include "localsession.h"
31 #include "mainsession.h"
32 #include "module.h"
33 #include "mwindow.h"
34 #include "patchbay.h"
35 #include "patch.h"
36 #include "playabletracks.h"
37 #include "preferences.h"
38 #include "renderengine.h"
39 #include "track.h"
40 #include "tracks.h"
41 #include "transportque.h"
42 #include "virtualconsole.h"
43
44 CommonRender::CommonRender(RenderEngine *renderengine)
45  : Thread(1, 0, 0)
46 {
47         this->renderengine = renderengine;
48         reset_parameters();
49         start_lock = new Condition(0, "CommonRender::start_lock");
50 }
51
52 CommonRender::~CommonRender()
53 {
54         delete_vconsole();
55         if(modules)
56         {
57                 for(int i = 0; i < total_modules; i++)
58                         delete modules[i];
59                 delete [] modules;
60         }
61         delete start_lock;
62 }
63
64 void CommonRender::reset_parameters()
65 {
66         total_modules = 0;
67         modules = 0;
68         vconsole = 0;
69         done = 0;
70         interrupt = 0;
71         asynchronous = 0;
72         restart_plugins = 0;
73 }
74
75 void CommonRender::arm_command()
76 {
77         int64_t temp_length = 1;
78
79         current_position = tounits(renderengine->command->playbackstart, 0);
80         if(renderengine->command->realtime) init_output_buffers();
81
82         if(test_reconfigure(current_position, temp_length))
83         {
84                 restart_playback();
85         }
86         else
87         {
88                 vconsole->start_playback();
89         }
90
91         done = 0;
92         interrupt = 0;
93         restart_plugins = 0;
94 }
95
96
97
98 void CommonRender::create_modules()
99 {
100 // Create a module for every track, playable or not
101         Track *current = renderengine->get_edl()->tracks->first;
102         int module = 0;
103 // printf("CommonRender::create_modules %d modules=%p total_modules=%d\n",
104 // __LINE__,
105 // modules,
106 // total_modules);
107
108         if(!modules)
109         {
110                 total_modules = get_total_tracks();
111                 modules = new Module*[total_modules];
112
113 // printf("CommonRender::create_modules %d total_modules=%d\n",
114 // __LINE__,
115 // total_modules);
116                 for(module = 0; module < total_modules && current; current = NEXT)
117                 {
118                         if(current->data_type == data_type)
119                         {
120                                 modules[module] = new_module(current);
121                                 modules[module]->create_objects();
122                                 module++;
123                         }
124                 }
125         }
126         else
127 // Update changes in plugins for existing modules
128         {
129                 for(module = 0; module < total_modules; module++)
130                 {
131                         modules[module]->create_objects();
132                 }
133         }
134 }
135
136 void CommonRender::start_plugins()
137 {
138 // Only start if virtual console was created
139         if(restart_plugins)
140         {
141                 for(int i = 0; i < total_modules; i++)
142                 {
143                         modules[i]->render_init();
144                 }
145         }
146 }
147
148 void CommonRender::stop_plugins()
149 {
150         for(int i = 0; i < total_modules; i++)
151         {
152                 modules[i]->render_stop();
153         }
154 }
155
156 int CommonRender::test_reconfigure(int64_t position, int64_t &length)
157 {
158         if(!vconsole) return 1;
159         if(!modules) return 1;
160         
161         return vconsole->test_reconfigure(position, length);
162 }
163
164
165 void CommonRender::build_virtual_console()
166 {
167 // Create new virtual console object
168         if(!vconsole)
169         {
170                 vconsole = new_vconsole_object();
171         }
172
173 // Create nodes
174         vconsole->create_objects();
175 }
176
177 void CommonRender::start_command()
178 {
179         if(renderengine->command->realtime)
180         {
181                 Thread::set_realtime(renderengine->get_edl()->session->real_time_playback &&
182                         data_type == TRACK_AUDIO);
183                 Thread::start();
184                 start_lock->lock("CommonRender::start_command");
185         }
186 }
187
188 void CommonRender::interrupt_playback()
189 {
190         interrupt = 1;
191 }
192
193 int CommonRender::restart_playback()
194 {
195 //printf("CommonRender::restart_playback %d\n", __LINE__);
196         delete_vconsole();
197         create_modules();
198         build_virtual_console();
199 //vconsole->dump();
200         start_plugins();
201 //printf("CommonRender::restart_playback %d\n", __LINE__);
202
203         done = 0;
204         interrupt = 0;
205         restart_plugins = 0;
206         return 0;
207 }
208
209 void CommonRender::delete_vconsole()
210 {
211         if(vconsole) delete vconsole;
212         vconsole = 0;
213 }
214
215 int CommonRender::get_boundaries(int64_t &current_render_length)
216 {
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);
221
222
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))
227         {
228                 if(renderengine->command->get_direction() == PLAY_FORWARD)
229                 {
230                         if(current_position + current_render_length >= end_position)
231                         {
232                                 current_render_length = end_position - current_position;
233                                 if(current_render_length <= 0) done = 1;
234                         }
235                 }
236 // reverse playback
237                 else               
238                 {
239                         if(current_position - current_render_length <= start_position)
240                         {
241                                 current_render_length = current_position - start_position;
242                                 if(current_render_length <= 0) done = 1;
243                         }
244                 }
245         }
246
247 // test against loop boundaries
248         if(!renderengine->command->single_frame() &&
249                 renderengine->get_edl()->local_session->loop_playback && 
250                 !renderengine->command->infinite)
251         {
252                 if(renderengine->command->get_direction() == PLAY_FORWARD)
253                 {
254                         int64_t segment_end = current_position + current_render_length;
255                         if(segment_end > loop_end)
256                         {
257                                 current_render_length = loop_end - current_position;
258                         }
259                 }
260                 else
261                 {
262                         int64_t segment_end = current_position - current_render_length;
263                         if(segment_end < loop_start)
264                         {
265                                 current_render_length = current_position - loop_start;
266                         }
267                 }
268         }
269
270         if(renderengine->command->single_frame())
271                 current_render_length = 1;
272
273         if(current_render_length < 0) current_render_length = 0;
274         return 0;
275 }
276
277 void CommonRender::run()
278 {
279         start_lock->unlock();
280 }
281
282 int64_t CommonRender::tounits(double position, int round)
283 {
284         return (int64_t)position;
285 }
286
287 double CommonRender::fromunits(int64_t position)
288 {
289         return (double)position;
290 }
291
292 int CommonRender::advance_position(int64_t current_render_length)
293 {
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();
299
300 // advance the playback position
301         if(direction == PLAY_REVERSE)
302                 current_position -= current_render_length;
303         else
304                 current_position += current_render_length;
305
306 // test loop again
307         if(renderengine->get_edl()->local_session->loop_playback && 
308                 !renderengine->command->infinite)
309         {
310                 if(direction == PLAY_REVERSE)
311                 {
312                         if(current_position <= loop_start)
313                                 current_position = loop_end;
314                 }
315                 else
316                 {
317                         if(current_position >= loop_end)
318                                 current_position = loop_start + (current_position - loop_end);
319                 }
320         }
321         else
322 // test end of file again
323         {
324                 if( (direction == PLAY_FORWARD && current_position >= end_position) ||
325                         (direction == PLAY_REVERSE && current_position <= start_position) )
326                         done = 1;
327         }
328
329         return 0;
330 }
331
332
333
334
335