Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / cinelerra / virtualconsole.C
diff --git a/cinelerra-5.1/cinelerra/virtualconsole.C b/cinelerra-5.1/cinelerra/virtualconsole.C
new file mode 100644 (file)
index 0000000..322fb22
--- /dev/null
@@ -0,0 +1,304 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008-2013 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "auto.h"
+#include "automation.h"
+#include "autos.h"
+#include "commonrender.h"
+#include "condition.h"
+#include "edl.h"
+#include "edlsession.h"
+#include "intautos.h"
+#include "module.h"
+#include "mutex.h"
+#include "playabletracks.h"
+#include "renderengine.h"
+#include "tracks.h"
+#include "transportque.h"
+#include "virtualconsole.h"
+#include "virtualnode.h"
+
+
+VirtualConsole::VirtualConsole(RenderEngine *renderengine,
+       CommonRender *commonrender,
+       int data_type)
+{
+       this->renderengine = renderengine;
+       this->commonrender = commonrender;
+       this->data_type = data_type;
+       total_exit_nodes = 0;
+       playable_tracks = 0;
+       entry_nodes = 0;
+       debug_tree = 0;
+//printf("VirtualConsole::VirtualConsole\n");
+}
+
+
+VirtualConsole::~VirtualConsole()
+{
+       delete_virtual_console();
+
+       delete playable_tracks;
+//printf("VirtualConsole::~VirtualConsole\n");
+}
+
+
+void VirtualConsole::create_objects()
+{
+       interrupt = 0;
+       done = 0;
+
+       get_playable_tracks();
+       total_exit_nodes = playable_tracks->size();
+       build_virtual_console(1);
+//dump();
+}
+
+void VirtualConsole::start_playback()
+{
+       interrupt = 0;
+       done = 0;
+}
+
+void VirtualConsole::get_playable_tracks()
+{
+}
+
+Module* VirtualConsole::module_of(Track *track)
+{
+       for(int i = 0; i < commonrender->total_modules; i++)
+       {
+               if(commonrender->modules[i]->track == track)
+                       return commonrender->modules[i];
+       }
+       return 0;
+}
+
+Module* VirtualConsole::module_number(int track_number)
+{
+// The track number is an absolute number of the track independant of
+// the tracks with matching data type but virtual modules only exist for
+// the matching data type.
+// Convert from absolute track number to data type track number.
+       Track *current = renderengine->get_edl()->tracks->first;
+       int data_type_number = 0, number = 0;
+
+       for( ; current; current = NEXT, number++)
+       {
+               if(current->data_type == data_type)
+               {
+                       if(number == track_number)
+                               return commonrender->modules[data_type_number];
+                       else
+                               data_type_number++;
+               }
+       }
+
+
+       return 0;
+}
+
+void VirtualConsole::build_virtual_console(int persistent_plugins)
+{
+// allocate the entry nodes
+       if(!entry_nodes)
+       {
+               entry_nodes = new VirtualNode*[total_exit_nodes];
+
+// printf("VirtualConsole::build_virtual_console %d total_exit_nodes=%d\n",
+// __LINE__,
+// total_exit_nodes);
+               for(int i = 0; i < total_exit_nodes; i++)
+               {
+// printf("VirtualConsole::build_virtual_console %d track=%p module=%p\n",
+// __LINE__,
+// playable_tracks->get(i),
+// module_of(playable_tracks->get(i)));
+                       entry_nodes[i] = new_entry_node(playable_tracks->get(i),
+                               module_of(playable_tracks->get(i)),
+                               i);
+
+// Expand the trees
+                       entry_nodes[i]->expand(persistent_plugins,
+                               commonrender->current_position);
+               }
+               commonrender->restart_plugins = 1;
+       }
+//dump();
+}
+
+VirtualNode* VirtualConsole::new_entry_node(Track *track,
+       Module *module,
+       int track_number)
+{
+       printf("VirtualConsole::new_entry_node should not be called\n");
+       return 0;
+}
+
+void VirtualConsole::append_exit_node(VirtualNode *node)
+{
+       node->is_exit = 1;
+       exit_nodes.append(node);
+}
+
+void VirtualConsole::reset_attachments()
+{
+       for(int i = 0; i < commonrender->total_modules; i++)
+       {
+               commonrender->modules[i]->reset_attachments();
+       }
+}
+
+void VirtualConsole::dump()
+{
+       printf("VirtualConsole\n");
+       printf(" Modules\n");
+       for(int i = 0; i < commonrender->total_modules; i++)
+               commonrender->modules[i]->dump();
+       printf(" Nodes\n");
+       for(int i = 0; i < total_exit_nodes; i++)
+               entry_nodes[i]->dump(0);
+}
+
+
+int VirtualConsole::test_reconfigure(int64_t position,
+       int64_t &length)
+{
+       int result = 0;
+       Track *current_track;
+       int direction = renderengine->command->get_direction();
+
+// Test playback status against virtual console for current position.
+       for(current_track = renderengine->get_edl()->tracks->first;
+               current_track && !result;
+               current_track = current_track->next)
+       {
+               if(current_track->data_type == data_type)
+               {
+// Playable status changed
+                       if(playable_tracks->is_playable(current_track,
+                               commonrender->current_position,
+                               direction,
+                               1))
+                       {
+                               if(!playable_tracks->is_listed(current_track))
+                                       result = 1;
+                       }
+                       else
+                       if(playable_tracks->is_listed(current_track))
+                       {
+                               result = 1;
+                       }
+               }
+       }
+
+// Test plugins against virtual console at current position
+       for(int i = 0; i < commonrender->total_modules && !result; i++)
+               result = commonrender->modules[i]->test_plugins();
+
+
+
+
+
+// Now get the length of time until next reconfiguration.
+// This part is not concerned with result.
+// Don't clip input length if only rendering 1 frame.
+       if(length == 1) return result;
+
+
+
+
+
+// GCC 3.2 requires this or optimization error results.
+       int64_t longest_duration1;
+       int64_t longest_duration2;
+       int64_t longest_duration3;
+
+// Length of time until next transition, edit, or effect change.
+// Why do we need the edit change?  Probably for changing to and from silence.
+       for(current_track = renderengine->get_edl()->tracks->first;
+               current_track;
+               current_track = current_track->next)
+       {
+               if(current_track->data_type == data_type)
+               {
+// Test the transitions
+                       longest_duration1 = current_track->edit_change_duration(
+                               commonrender->current_position,
+                               length,
+                               direction == PLAY_REVERSE,
+                               1,
+                               1);
+
+
+// Test the edits
+                       longest_duration2 = current_track->edit_change_duration(
+                               commonrender->current_position,
+                               length,
+                               direction,
+                               0,
+                               1);
+
+
+// Test the plugins
+                       longest_duration3 = current_track->plugin_change_duration(
+                               commonrender->current_position,
+                               length,
+                               direction == PLAY_REVERSE,
+                               1);
+
+                       if(longest_duration1 < length)
+                       {
+                               length = longest_duration1;
+                       }
+                       if(longest_duration2 < length)
+                       {
+                               length = longest_duration2;
+                       }
+                       if(longest_duration3 < length)
+                       {
+                               length = longest_duration3;
+                       }
+
+               }
+       }
+
+       return result;
+}
+
+
+
+
+
+void VirtualConsole::delete_virtual_console()
+{
+// delete the virtual node tree
+       for(int i = 0; i < total_exit_nodes; i++)
+       {
+               delete entry_nodes[i];
+       }
+// Seems to get allocated even if new[0].
+       if(entry_nodes) delete [] entry_nodes;
+       entry_nodes = 0;
+       exit_nodes.remove_all();
+}
+
+