r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / virtualconsole.C
blob7f9f6c46899ef94022f35f4488ffa05ab150aa92
1 #include "auto.h"
2 #include "automation.h"
3 #include "autos.h"
4 #include "commonrender.h"
5 #include "edl.h"
6 #include "edlsession.h"
7 #include "virtualconsole.h"
8 #include "module.h"
9 #include "mutex.h"
10 #include "playabletracks.h"
11 #include "renderengine.h"
12 #include "intautos.h"
13 #include "tracks.h"
14 #include "transportque.h"
15 #include "virtualnode.h"
18 VirtualConsole::VirtualConsole(RenderEngine *renderengine, 
19         CommonRender *commonrender,
20         int data_type)
21  : Thread()
23         this->renderengine = renderengine;
24         this->commonrender = commonrender;
25         this->data_type = data_type;
26         total_tracks = 0;
27         startup_lock = new Mutex;
28         playable_tracks = 0;
29         ring_buffers = 0;
30         virtual_modules = 0;
34 VirtualConsole::~VirtualConsole()
36 //printf("VirtualConsole::~VirtualConsole 1\n");
37         delete_virtual_console();
38         delete_input_buffers();
40         delete startup_lock;
41         if(playable_tracks) delete playable_tracks;
44 int VirtualConsole::total_ring_buffers()
46         return 2;
50 void VirtualConsole::create_objects()
52         interrupt = 0;
53         done = 0;
54         current_input_buffer = 0;
55         current_vconsole_buffer = 0;
57         get_playable_tracks();
58         total_tracks = playable_tracks->total;
59         allocate_input_buffers();
60         build_virtual_console(1);
61         sort_virtual_console();
62 //dump();
66 void VirtualConsole::start_playback()
68         done = 0;
69         interrupt = 0;
70         current_input_buffer = 0;
71         current_vconsole_buffer = 0;
72 //printf("VirtualConsole::start_playback 1 %d %d\n", renderengine->command->realtime, data_type);
73         if(renderengine->command->realtime && data_type == TRACK_AUDIO)
74         {
75 // don't start a thread unless writing to an audio device
76                 startup_lock->lock();
77                 for(int ring_buffer = 0; ring_buffer < ring_buffers; ring_buffer++)
78                 {
79                         input_lock[ring_buffer]->reset();
80                         output_lock[ring_buffer]->reset();
81                         input_lock[ring_buffer]->lock();
82                 }
83                 Thread::set_synchronous(1);   // prepare thread base class
84 //printf("VirtualConsole::start_playback 2 %d\n", renderengine->edl->session->real_time_playback);
85                 Thread::start();
86 //printf("VirtualConsole::start_playback 3 %d\n", renderengine->edl->session->real_time_playback);
87                 startup_lock->lock();
88                 startup_lock->unlock();
89         }
93 Module* VirtualConsole::module_of(Track *track)
95         for(int i = 0; i < commonrender->total_modules; i++)
96         {
97 //printf("VirtualConsole::module_of %p %p\n", (Track*)commonrender->modules[i]->track, track); 
98                 if(commonrender->modules[i]->track == track) return commonrender->modules[i];
99         }
100         return 0;
103 Module* VirtualConsole::module_number(int track_number)
105 // The track number is an absolute number of the track independant of
106 // the tracks with matching data type but virtual modules only exist for
107 // the matching data type.
108 // Convert from absolute track number to data type track number.
109         Track *current = renderengine->edl->tracks->first;
110         int data_type_number = 0, number = 0;
112         for( ; current; current = NEXT, number++)
113         {
114                 if(current->data_type == data_type)
115                 {
116                         if(number == track_number)
117                                 return commonrender->modules[data_type_number];
118                         else
119                                 data_type_number++;
120                 }
121         }
124         return 0;
127 int VirtualConsole::allocate_input_buffers()
129         if(!ring_buffers)
130         {
131                 ring_buffers = total_ring_buffers();
133 // allocate the drive read buffers
134                 for(int ring_buffer = 0; 
135                         ring_buffer < ring_buffers; 
136                         ring_buffer++)
137                 {
138                         input_lock[ring_buffer] = new Mutex;
139                         output_lock[ring_buffer] = new Mutex;
140                         last_playback[ring_buffer] = 0;
141                         new_input_buffer(ring_buffer);
142                 }
143         }
145         return 0;
148 void VirtualConsole::build_virtual_console(int persistant_plugins)
150 // allocate the virtual modules
151 //printf("VirtualConsole::build_virtual_console 1\n");
152         if(!virtual_modules)
153         {
154                 virtual_modules = new VirtualNode*[total_tracks];
156 //printf("VirtualConsole::build_virtual_console 2 %d %d\n", data_type, total_tracks);
157                 for(int i = 0; i < total_tracks; i++)
158                 {
159 //printf("VirtualConsole::build_virtual_console 3\n");
160                         virtual_modules[i] = new_toplevel_node(playable_tracks->values[i], 
161                                 module_of(playable_tracks->values[i]), 
162                                 i);
164 // Expand the track
165                         virtual_modules[i]->expand(persistant_plugins, commonrender->current_position);
166 //printf("VirtualConsole::build_virtual_console 3\n");
167                 }
168                 commonrender->restart_plugins = 1;
169         }
172 int VirtualConsole::sort_virtual_console()
174 // sort the console
175         int done = 0, result = 0;
176         int64_t attempts = 0;
177         int i;
179 //printf("VirtualConsole::sort_virtual_console 1\n");
180         if(!render_list.total)
181         {
182                 while(!done && attempts < 50)
183                 {
184 // Sort iteratively until all the remaining plugins can be rendered.
185 // Iterate backwards so video is composited properly
186                         done = 1;
187                         for(i = total_tracks - 1; i >= 0; i--)
188                         {
189                                 result = virtual_modules[i]->sort(&render_list);
190                                 if(result) done = 0;
191                         }
192                         attempts++;
193                 }
195 //printf("VirtualConsole::sort_virtual_console 2 %d\n", render_list.total);
196 // prevent short circuts
197                 if(attempts >= 50)
198                 {
199                         printf("VirtualConsole::sort_virtual_console: Recursive.\n");
200                 }
201 //printf("VirtualConsole::sort_virtual_console 2\n");
202         }
203         return 0;
206 void VirtualConsole::dump()
208         printf("VirtualConsole\n");
209         printf(" Modules\n");
210         for(int i = 0; i < commonrender->total_modules; i++)
211                 commonrender->modules[i]->dump();
212         printf(" Nodes\n");
213         for(int i = 0; i < total_tracks; i++)
214                 virtual_modules[i]->dump(0);
218 int VirtualConsole::test_reconfigure(int64_t position, 
219         int64_t &length, 
220         int &last_playback)
222         int result = 0;
223         Track *current_track;
224         Module *module;
226 //printf("VirtualConsole::test_reconfigure 1\n");
228 // Test playback status against virtual console for current position.
229         for(current_track = renderengine->edl->tracks->first;
230                 current_track && !result;
231                 current_track = current_track->next)
232         {
233                 if(current_track->data_type == data_type)
234                 {
235 // Playable status changed
236                         if(playable_tracks->is_playable(current_track, 
237                                 commonrender->current_position))
238                         {
239                                 if(!playable_tracks->is_listed(current_track))
240                                         result = 1;
241                         }
242                         else
243                         if(playable_tracks->is_listed(current_track))
244                         {
245                                 result = 1;
246                         }
247                 }
248         }
250 // Test plugins against virtual console at current position
251         for(int i = 0; i < commonrender->total_modules && !result; i++)
252                 result = commonrender->modules[i]->test_plugins();
258 // Now get the length of time until next reconfiguration.
259 // This part is not concerned with result.
260 // Don't clip input length if only rendering 1 frame.
261         if(length == 1)  return result;
267         int direction = renderengine->command->get_direction();
268 // GCC 3.2 requires this or optimization error results.
269         int64_t longest_duration1;
270         int64_t longest_duration2;
271         int64_t longest_duration3;
273 //printf("VirtualConsole::test_reconfigure 6 %d %d\n", length, result);
274 // Length of time until next transition, edit, or effect change.
275 // Why do we need the edit change?  Probably for changing to and from silence.
276         for(current_track = renderengine->edl->tracks->first;
277                 current_track;
278                 current_track = current_track->next)
279         {
280                 if(current_track->data_type == data_type)
281                 {
282 // Test the transitions
283                         longest_duration1 = current_track->edit_change_duration(
284                                 commonrender->current_position, 
285                                 length, 
286                                 direction == PLAY_REVERSE, 
287                                 1);
289 //printf("VirtualConsole::test_reconfigure 10 %d\n", length);
291 // Test the edits
292                         longest_duration2 = current_track->edit_change_duration(
293                                 commonrender->current_position, 
294                                 length, 
295                                 direction, 
296                                 0);
298 //printf("VirtualConsole::test_reconfigure 20 %d\n", length);
300 // Test the plugins
301                         longest_duration3 = current_track->plugin_change_duration(
302                                 commonrender->current_position,
303                                 length,
304                                 direction == PLAY_REVERSE);
306                         if(longest_duration1 < length)
307                         {
308                                 length = longest_duration1;
309                                 last_playback = 0;
310                         }
311                         if(longest_duration2 < length)
312                         {
313                                 length = longest_duration2;
314                                 last_playback = 0;
315                         }
316                         if(longest_duration3 < length)
317                         {
318                                 length = longest_duration3;
319                                 last_playback = 0;
320                         }
322 //printf("VirtualConsole::test_reconfigure 30 %d\n", length);
323                 }
324         }
325 //printf("VirtualConsole::test_reconfigure 11 %d %d\n", length, result);
327         return result;
330 void VirtualConsole::run()
332         startup_lock->unlock();
356 int VirtualConsole::delete_virtual_console()
358 // delete the virtual modules
359         for(int i = 0; i < total_tracks; i++)
360         {
361                 delete virtual_modules[i];
362         }
363 // Seems to get allocated even if new[0].
364         if(virtual_modules) delete [] virtual_modules;
365         virtual_modules = 0;
367 // delete sort order
368         render_list.remove_all();
371 int VirtualConsole::delete_input_buffers()
373 // delete input buffers
374         for(int buffer = 0; buffer < ring_buffers; buffer++)
375         {
376                 delete_input_buffer(buffer);
377         }
379         for(int i = 0; i < ring_buffers; i++)
380         {
381                 delete input_lock[i];
382                 delete output_lock[i];
383         }
385         total_tracks = 0;
386         ring_buffers = 0;
387         return 0;
390 int VirtualConsole::start_rendering(int duplicate)
392         this->interrupt = 0;
394         if(renderengine->command->realtime && commonrender->asynchronous)
395         {
396 // don't start a thread unless writing to an audio device
397                 startup_lock->lock();
398                 set_synchronous(1);   // prepare thread base class
399                 start();
400         }
401         return 0;
404 int VirtualConsole::wait_for_completion()
406         if(renderengine->command->realtime && commonrender->asynchronous)
407         {
408                 join();
409         }
410         return 0;
413 int VirtualConsole::swap_input_buffer()
415         current_input_buffer++;
416         if(current_input_buffer >= total_ring_buffers()) current_input_buffer = 0;
417         return 0;
420 int VirtualConsole::swap_thread_buffer()
422         current_vconsole_buffer++;
423         if(current_vconsole_buffer >= total_ring_buffers()) current_vconsole_buffer = 0;
424         return 0;