Credit Andrew - improve in-tree documentation
[goodguy/cinelerra.git] / cinelerra / virtualconsole.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008-2013 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 "automation.h"
24 #include "autos.h"
25 #include "commonrender.h"
26 #include "condition.h"
27 #include "edl.h"
28 #include "edlsession.h"
29 #include "intautos.h"
30 #include "module.h"
31 #include "mutex.h"
32 #include "playabletracks.h"
33 #include "renderengine.h"
34 #include "tracks.h"
35 #include "transportque.h"
36 #include "virtualconsole.h"
37 #include "virtualnode.h"
38
39
40 VirtualConsole::VirtualConsole(RenderEngine *renderengine,
41         CommonRender *commonrender,
42         int data_type)
43 {
44         this->renderengine = renderengine;
45         this->commonrender = commonrender;
46         this->data_type = data_type;
47         total_exit_nodes = 0;
48         playable_tracks = 0;
49         entry_nodes = 0;
50         debug_tree = 0;
51 //printf("VirtualConsole::VirtualConsole\n");
52 }
53
54
55 VirtualConsole::~VirtualConsole()
56 {
57         delete_virtual_console();
58
59         delete playable_tracks;
60 //printf("VirtualConsole::~VirtualConsole\n");
61 }
62
63
64 void VirtualConsole::create_objects()
65 {
66         interrupt = 0;
67         done = 0;
68
69         get_playable_tracks();
70         total_exit_nodes = playable_tracks->size();
71         build_virtual_console(1);
72 //dump();
73 }
74
75 void VirtualConsole::start_playback()
76 {
77         interrupt = 0;
78         done = 0;
79 }
80
81 void VirtualConsole::get_playable_tracks()
82 {
83 }
84
85 Module* VirtualConsole::module_of(Track *track)
86 {
87         for(int i = 0; i < commonrender->total_modules; i++)
88         {
89                 if(commonrender->modules[i]->track == track)
90                         return commonrender->modules[i];
91         }
92         return 0;
93 }
94
95 Module* VirtualConsole::module_number(int track_number)
96 {
97 // The track number is an absolute number of the track independant of
98 // the tracks with matching data type but virtual modules only exist for
99 // the matching data type.
100 // Convert from absolute track number to data type track number.
101         Track *current = renderengine->get_edl()->tracks->first;
102         int data_type_number = 0, number = 0;
103
104         for( ; current; current = NEXT, number++)
105         {
106                 if(current->data_type == data_type)
107                 {
108                         if(number == track_number)
109                                 return commonrender->modules[data_type_number];
110                         else
111                                 data_type_number++;
112                 }
113         }
114
115
116         return 0;
117 }
118
119 void VirtualConsole::build_virtual_console(int persistent_plugins)
120 {
121 // allocate the entry nodes
122         if(!entry_nodes)
123         {
124                 entry_nodes = new VirtualNode*[total_exit_nodes];
125
126 // printf("VirtualConsole::build_virtual_console %d total_exit_nodes=%d\n",
127 // __LINE__,
128 // total_exit_nodes);
129                 for(int i = 0; i < total_exit_nodes; i++)
130                 {
131 // printf("VirtualConsole::build_virtual_console %d track=%p module=%p\n",
132 // __LINE__,
133 // playable_tracks->get(i),
134 // module_of(playable_tracks->get(i)));
135                         entry_nodes[i] = new_entry_node(playable_tracks->get(i),
136                                 module_of(playable_tracks->get(i)),
137                                 i);
138
139 // Expand the trees
140                         entry_nodes[i]->expand(persistent_plugins,
141                                 commonrender->current_position);
142                 }
143                 commonrender->restart_plugins = 1;
144         }
145 //dump();
146 }
147
148 VirtualNode* VirtualConsole::new_entry_node(Track *track,
149         Module *module,
150         int track_number)
151 {
152         printf("VirtualConsole::new_entry_node should not be called\n");
153         return 0;
154 }
155
156 void VirtualConsole::append_exit_node(VirtualNode *node)
157 {
158         node->is_exit = 1;
159         exit_nodes.append(node);
160 }
161
162 void VirtualConsole::reset_attachments()
163 {
164         for(int i = 0; i < commonrender->total_modules; i++)
165         {
166                 commonrender->modules[i]->reset_attachments();
167         }
168 }
169
170 void VirtualConsole::dump()
171 {
172         printf("VirtualConsole\n");
173         printf(" Modules\n");
174         for(int i = 0; i < commonrender->total_modules; i++)
175                 commonrender->modules[i]->dump();
176         printf(" Nodes\n");
177         for(int i = 0; i < total_exit_nodes; i++)
178                 entry_nodes[i]->dump(0);
179 }
180
181
182 int VirtualConsole::test_reconfigure(int64_t position,
183         int64_t &length)
184 {
185         int result = 0;
186         Track *current_track;
187         int direction = renderengine->command->get_direction();
188
189 // Test playback status against virtual console for current position.
190         for(current_track = renderengine->get_edl()->tracks->first;
191                 current_track && !result;
192                 current_track = current_track->next)
193         {
194                 if(current_track->data_type == data_type)
195                 {
196 // Playable status changed
197                         if(playable_tracks->is_playable(current_track,
198                                 commonrender->current_position,
199                                 direction,
200                                 1))
201                         {
202                                 if(!playable_tracks->is_listed(current_track))
203                                         result = 1;
204                         }
205                         else
206                         if(playable_tracks->is_listed(current_track))
207                         {
208                                 result = 1;
209                         }
210                 }
211         }
212
213 // Test plugins against virtual console at current position
214         for(int i = 0; i < commonrender->total_modules && !result; i++)
215                 result = commonrender->modules[i]->test_plugins();
216
217
218
219
220
221 // Now get the length of time until next reconfiguration.
222 // This part is not concerned with result.
223 // Don't clip input length if only rendering 1 frame.
224         if(length == 1) return result;
225
226
227
228
229
230 // GCC 3.2 requires this or optimization error results.
231         int64_t longest_duration1;
232         int64_t longest_duration2;
233         int64_t longest_duration3;
234
235 // Length of time until next transition, edit, or effect change.
236 // Why do we need the edit change?  Probably for changing to and from silence.
237         for(current_track = renderengine->get_edl()->tracks->first;
238                 current_track;
239                 current_track = current_track->next)
240         {
241                 if(current_track->data_type == data_type)
242                 {
243 // Test the transitions
244                         longest_duration1 = current_track->edit_change_duration(
245                                 commonrender->current_position,
246                                 length,
247                                 direction == PLAY_REVERSE,
248                                 1,
249                                 1);
250
251
252 // Test the edits
253                         longest_duration2 = current_track->edit_change_duration(
254                                 commonrender->current_position,
255                                 length,
256                                 direction,
257                                 0,
258                                 1);
259
260
261 // Test the plugins
262                         longest_duration3 = current_track->plugin_change_duration(
263                                 commonrender->current_position,
264                                 length,
265                                 direction == PLAY_REVERSE,
266                                 1);
267
268                         if(longest_duration1 < length)
269                         {
270                                 length = longest_duration1;
271                         }
272                         if(longest_duration2 < length)
273                         {
274                                 length = longest_duration2;
275                         }
276                         if(longest_duration3 < length)
277                         {
278                                 length = longest_duration3;
279                         }
280
281                 }
282         }
283
284         return result;
285 }
286
287
288
289
290
291 void VirtualConsole::delete_virtual_console()
292 {
293 // delete the virtual node tree
294         for(int i = 0; i < total_exit_nodes; i++)
295         {
296                 delete entry_nodes[i];
297         }
298 // Seems to get allocated even if new[0].
299         if(entry_nodes) delete [] entry_nodes;
300         entry_nodes = 0;
301         exit_nodes.remove_all();
302 }
303
304