/* * CINELERRA * Copyright (C) 2008-2013 Adam Williams * * 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(); }