Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / cinelerra / commonrender.C
diff --git a/cinelerra-5.1/cinelerra/commonrender.C b/cinelerra-5.1/cinelerra/commonrender.C
new file mode 100644 (file)
index 0000000..1823978
--- /dev/null
@@ -0,0 +1,331 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 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 "cache.h"
+#include "commonrender.h"
+#include "condition.h"
+#include "edl.h"
+#include "edlsession.h"
+#include "intautos.h"
+#include "localsession.h"
+#include "mainsession.h"
+#include "module.h"
+#include "mwindow.h"
+#include "patchbay.h"
+#include "patch.h"
+#include "playabletracks.h"
+#include "preferences.h"
+#include "renderengine.h"
+#include "track.h"
+#include "tracks.h"
+#include "transportque.h"
+#include "virtualconsole.h"
+
+CommonRender::CommonRender(RenderEngine *renderengine)
+ : Thread(1, 0, 0)
+{
+       this->renderengine = renderengine;
+       reset_parameters();
+       start_lock = new Condition(0, "CommonRender::start_lock");
+}
+
+CommonRender::~CommonRender()
+{
+       delete_vconsole();
+       if(modules)
+       {
+               for(int i = 0; i < total_modules; i++)
+                       delete modules[i];
+               delete [] modules;
+       }
+       delete start_lock;
+}
+
+void CommonRender::reset_parameters()
+{
+       total_modules = 0;
+       modules = 0;
+       vconsole = 0;
+       done = 0;
+       interrupt = 0;
+       asynchronous = 0;
+       restart_plugins = 0;
+}
+
+void CommonRender::arm_command()
+{
+       int64_t temp_length = 1;
+
+       current_position = tounits(renderengine->command->playbackstart, 0);
+       if(renderengine->command->realtime) init_output_buffers();
+
+       if(test_reconfigure(current_position, temp_length))
+       {
+               restart_playback();
+       }
+       else
+       {
+               vconsole->start_playback();
+       }
+
+       done = 0;
+       interrupt = 0;
+       restart_plugins = 0;
+}
+
+
+
+void CommonRender::create_modules()
+{
+// Create a module for every track, playable or not
+       Track *current = renderengine->get_edl()->tracks->first;
+       int module = 0;
+// printf("CommonRender::create_modules %d modules=%p total_modules=%d\n",
+// __LINE__,
+// modules,
+// total_modules);
+
+       if(!modules)
+       {
+               total_modules = get_total_tracks();
+               modules = new Module*[total_modules];
+
+// printf("CommonRender::create_modules %d total_modules=%d\n",
+// __LINE__,
+// total_modules);
+               for(module = 0; module < total_modules && current; current = NEXT)
+               {
+                       if(current->data_type == data_type)
+                       {
+                               modules[module] = new_module(current);
+                               modules[module]->create_objects();
+                               module++;
+                       }
+               }
+       }
+       else
+// Update changes in plugins for existing modules
+       {
+               for(module = 0; module < total_modules; module++)
+               {
+                       modules[module]->create_objects();
+               }
+       }
+}
+
+void CommonRender::start_plugins()
+{
+// Only start if virtual console was created
+       if(restart_plugins)
+       {
+               for(int i = 0; i < total_modules; i++)
+               {
+                       modules[i]->render_init();
+               }
+       }
+}
+
+void CommonRender::stop_plugins()
+{
+       for(int i = 0; i < total_modules; i++)
+       {
+               modules[i]->render_stop();
+       }
+}
+
+int CommonRender::test_reconfigure(int64_t position, int64_t &length)
+{
+       if(!vconsole) return 1;
+       if(!modules) return 1;
+
+       return vconsole->test_reconfigure(position, length);
+}
+
+
+void CommonRender::build_virtual_console()
+{
+// Create new virtual console object
+       if(!vconsole)
+       {
+               vconsole = new_vconsole_object();
+       }
+
+// Create nodes
+       vconsole->create_objects();
+}
+
+void CommonRender::start_command()
+{
+       if(renderengine->command->realtime)
+       {
+               Thread::set_realtime(renderengine->get_edl()->session->real_time_playback &&
+                       data_type == TRACK_AUDIO);
+               Thread::start();
+               start_lock->lock("CommonRender::start_command");
+       }
+}
+
+void CommonRender::interrupt_playback()
+{
+       interrupt = 1;
+}
+
+int CommonRender::restart_playback()
+{
+//printf("CommonRender::restart_playback %d\n", __LINE__);
+       delete_vconsole();
+       create_modules();
+       build_virtual_console();
+//vconsole->dump();
+       start_plugins();
+//printf("CommonRender::restart_playback %d\n", __LINE__);
+
+       done = 0;
+       interrupt = 0;
+       restart_plugins = 0;
+       return 0;
+}
+
+void CommonRender::delete_vconsole()
+{
+       if(vconsole) delete vconsole;
+       vconsole = 0;
+}
+
+int CommonRender::get_boundaries(int64_t &current_render_length)
+{
+       int64_t loop_end = tounits(renderengine->get_edl()->local_session->loop_end, 1);
+       int64_t loop_start = tounits(renderengine->get_edl()->local_session->loop_start, 0);
+       int64_t start_position = tounits(renderengine->command->start_position, 0);
+       int64_t end_position = tounits(renderengine->command->end_position, 1);
+
+
+// test absolute boundaries if no loop and not infinite
+       if(renderengine->command->single_frame() ||
+               (!renderengine->get_edl()->local_session->loop_playback &&
+               !renderengine->command->infinite))
+       {
+               if(renderengine->command->get_direction() == PLAY_FORWARD)
+               {
+                       if(current_position + current_render_length >= end_position)
+                       {
+                               current_render_length = end_position - current_position;
+                               if(current_render_length <= 0) done = 1;
+                       }
+               }
+// reverse playback
+               else
+               {
+                       if(current_position - current_render_length <= start_position)
+                       {
+                               current_render_length = current_position - start_position;
+                               if(current_render_length <= 0) done = 1;
+                       }
+               }
+       }
+
+// test against loop boundaries
+       if(!renderengine->command->single_frame() &&
+               renderengine->get_edl()->local_session->loop_playback &&
+               !renderengine->command->infinite)
+       {
+               if(renderengine->command->get_direction() == PLAY_FORWARD)
+               {
+                       int64_t segment_end = current_position + current_render_length;
+                       if(segment_end > loop_end)
+                       {
+                               current_render_length = loop_end - current_position;
+                       }
+               }
+               else
+               {
+                       int64_t segment_end = current_position - current_render_length;
+                       if(segment_end < loop_start)
+                       {
+                               current_render_length = current_position - loop_start;
+                       }
+               }
+       }
+
+       if(renderengine->command->single_frame())
+               current_render_length = 1;
+
+       if(current_render_length < 0) current_render_length = 0;
+       return 0;
+}
+
+void CommonRender::run()
+{
+       start_lock->unlock();
+}
+
+int64_t CommonRender::tounits(double position, int round)
+{
+       return (int64_t)position;
+}
+
+double CommonRender::fromunits(int64_t position)
+{
+       return (double)position;
+}
+
+int CommonRender::advance_position(int64_t current_render_length)
+{
+       int64_t loop_end = tounits(renderengine->get_edl()->local_session->loop_end, 1);
+       int64_t loop_start = tounits(renderengine->get_edl()->local_session->loop_start, 0);
+       int64_t start_position = tounits(renderengine->command->start_position, 0);
+       int64_t end_position = tounits(renderengine->command->end_position, 1);
+       int direction = renderengine->command->get_direction();
+
+// advance the playback position
+       if(direction == PLAY_REVERSE)
+               current_position -= current_render_length;
+       else
+               current_position += current_render_length;
+
+// test loop again
+       if(renderengine->get_edl()->local_session->loop_playback &&
+               !renderengine->command->infinite)
+       {
+               if(direction == PLAY_REVERSE)
+               {
+                       if(current_position <= loop_start)
+                               current_position = loop_end;
+               }
+               else
+               {
+                       if(current_position >= loop_end)
+                               current_position = loop_start + (current_position - loop_end);
+               }
+       }
+       else
+// test end of file again
+       {
+               if( (direction == PLAY_FORWARD && current_position >= end_position) ||
+                       (direction == PLAY_REVERSE && current_position <= start_position) )
+                       done = 1;
+       }
+
+       return 0;
+}
+
+