Пример #1
0
int Track::clear(double start, 
	double end, 
	int edit_edits,
	int edit_labels,
	int edit_plugins,
	int edit_autos,
	int convert_units,
	Edits *trim_edits)
{
// Edits::move_auto calls this routine after the units are converted to the track
// format.
//printf("Track::clear 1 %d %d %d\n", edit_edits, edit_labels, edit_plugins);
	if(convert_units)
	{
		start = to_units(start, 0);
		end = to_units(end, 0);
	}


	if(edit_autos)
		automation->clear((int64_t)start, (int64_t)end, 0, 1);

	if(edit_plugins)
	{
		for(int i = 0; i < plugin_set.total; i++)
		{
			if(!trim_edits || trim_edits == (Edits*)plugin_set.values[i])
				plugin_set.values[i]->clear((int64_t)start, (int64_t)end, edit_autos);
		}
	}

	if(edit_edits)
		edits->clear((int64_t)start, (int64_t)end);
	return 0;
}
Пример #2
0
int Track::copy_assets(double start, 
	double end, 
	ArrayList<Asset*> *asset_list)
{
	int i, result = 0;

	start = to_units(start, 0);
	end = to_units(end, 0);

	Edit *current = edits->editof((int64_t)start, PLAY_FORWARD, 0);

// Search all edits
	while(current && current->startproject < end)
	{
// Check for duplicate assets
		if(current->asset)
		{
			for(i = 0, result = 0; i < asset_list->total; i++)
			{
				if(asset_list->values[i] == current->asset) result = 1;
			}
// append pointer to new asset
			if(!result) asset_list->append(current->asset);
		}

		current = NEXT;
	}

	return 0;
}
Пример #3
0
void Track::set_automation_mode(double selectionstart, 
	double selectionend,
	int mode)
{
	int64_t start = to_units(selectionstart, 0);
	int64_t end = to_units(selectionend, 0);

	automation->set_automation_mode(start, end, mode, edl->session->auto_conf);
}
Пример #4
0
void Track::insert_asset(Asset *asset, 
	EDL *nested_edl,
	double length, 
	double position, 
	int track_number)
{
	edits->insert_asset(asset, 
		nested_edl,
		to_units(length, 1), 
		to_units(position, 0), 
		track_number);
}
Пример #5
0
int Track::paste_silence(double start, double end, int edit_plugins, int edit_autos)
{
	int64_t start_i = to_units(start, 0);
	int64_t end_i = to_units(end, 1);

	edits->paste_silence(start_i, end_i);
	if(edit_autos) shift_keyframes(start_i, end_i - start_i);
	if(edit_plugins) shift_effects(start_i, end_i - start_i, edit_autos);

	edits->optimize();
	return 0;
}
Пример #6
0
void Track::clear_automation(double selectionstart, 
	double selectionend, 
	int shift_autos,
	int default_only)
{
	int64_t start = to_units(selectionstart, 0);
	int64_t end = to_units(selectionend, 0);

	automation->clear(start, end, edl->session->auto_conf, 0);

	if(edl->session->auto_conf->plugins)
	{
		for(int i = 0; i < plugin_set.total; i++)
		{
			plugin_set.values[i]->clear_keyframes(start, end);
		}
	}

}
Пример #7
0
// used for copying automation alone
int Track::copy_automation(double selectionstart, 
	double selectionend, 
	FileXML *file,
	int default_only,
	int active_only)
{
	int64_t start = to_units(selectionstart, 0);
	int64_t end = to_units(selectionend, 0);

	file->tag.set_title("TRACK");
// Video or audio
    save_header(file);
	file->append_tag();
	file->append_newline();

	automation->copy(start, end, file, default_only, active_only);

	if(edl->session->auto_conf->plugins)
	{
		for(int i = 0; i < plugin_set.total; i++)
		{
		
			plugin_set.values[i]->copy_keyframes(start, 
				end, 
				file, 
				default_only,
				active_only);
		}
	}

	file->tag.set_title("/TRACK");
	file->append_tag();
	file->append_newline();
	file->append_newline();
	file->append_newline();
	file->append_newline();

	return 0;
}
Пример #8
0
void Track::get_source_dimensions(double position, int &w, int &h)
{
	int64_t native_position = to_units(position, 0);
	for(Edit *current = edits->first; current; current = NEXT)
	{
		if(current->startproject <= native_position &&
			current->startproject + current->length > native_position &&
			current->asset)
		{
			w = current->asset->width;
			h = current->asset->height;
			return;
		}
	}
}
Пример #9
0
void Track::insert_track(Track *track, 
	double position, 
	int replace_default,
	int edit_plugins,
	int edit_autos,
	double edl_length)
{
// Calculate minimum length of data to pad.
	int64_t min_length = to_units(
		MAX(edl_length, track->get_length()),
		1);
//printf("Track::insert_track %d %s " _LD "\n", __LINE__, title, min_length);

// Decide whether to copy settings based on load_mode
	if(replace_default) copy_settings(track);

	edits->insert_edits(track->edits, 
		to_units(position, 0),
		min_length,
		edit_autos);

	if(edit_plugins)
		insert_plugin_set(track, 
			to_units(position, 0),
			min_length,
			edit_autos);

	if(edit_autos)
		automation->insert_track(track->automation, 
			to_units(position, 0), 
			min_length,
			replace_default);

	optimize();

}
Пример #10
0
Plugin* Track::get_current_plugin(double position, 
	int plugin_set, 
	int direction, 
	int convert_units,
	int use_nudge)
{
	Plugin *current;
	if(convert_units) position = to_units(position, 0);
	if(use_nudge) position += nudge;
	
	if(plugin_set >= this->plugin_set.total || plugin_set < 0) return 0;

//printf("Track::get_current_plugin 1 %d %d %d\n", position, this->plugin_set.total, direction);
	if(direction == PLAY_FORWARD)
	{
		for(current = (Plugin*)this->plugin_set.values[plugin_set]->last; 
			current; 
			current = (Plugin*)PREVIOUS)
		{
// printf("Track::get_current_plugin 2 %d %ld %ld\n", 
// current->startproject, 
// current->startproject + current->length, 
// position);
			if(current->startproject <= position && 
				current->startproject + current->length > position)
			{
				return current;
			}
		}
	}
	else
	if(direction == PLAY_REVERSE)
	{
		for(current = (Plugin*)this->plugin_set.values[plugin_set]->first; 
			current; 
			current = (Plugin*)NEXT)
		{
			if(current->startproject < position && 
				current->startproject + current->length >= position)
			{
				return current;
			}
		}
	}

	return 0;
}
Пример #11
0
Plugin* Track::get_current_transition(double position, 
	int direction, 
	int convert_units,
	int use_nudge)
{
	Edit *current;
	Plugin *result = 0;
	if(convert_units) position = to_units(position, 0);
	if(use_nudge) position += nudge;

	if(direction == PLAY_FORWARD)
	{
		for(current = edits->last; current; current = PREVIOUS)
		{
			if(current->startproject <= position && current->startproject + current->length > position)
			{
//printf("Track::get_current_transition %p\n", current->transition);
				if(current->transition && position < current->startproject + current->transition->length)
				{
					result = current->transition;
					break;
				}
			}
		}
	}
	else
	if(direction == PLAY_REVERSE)
	{
		for(current = edits->first; current; current = NEXT)
		{
			if(current->startproject < position && current->startproject + current->length >= position)
			{
				if(current->transition && position <= current->startproject + current->transition->length)
				{
					result = current->transition;
					break;
				}
			}
		}
	}

	return result;
}
Пример #12
0
// for recent effect menu items and running new effects
// prompts for an effect if title is blank
void MenuEffectThread::run()
{
	for(int i = 0; i < dead_plugins->size(); i++)
	{
		delete dead_plugins->get(i);
	}
	dead_plugins->remove_all();




// get stuff from main window
	ArrayList<PluginServer*> *plugindb = mwindow->plugindb;
	BC_Hash *defaults = mwindow->defaults;
	ArrayList<BC_ListBoxItem*> plugin_list;
	ArrayList<PluginServer*> local_plugindb;
	char string[1024];
	int i;
	int result = 0;
// Default configuration
	Asset *default_asset = new Asset;
// Output
	ArrayList<Indexable*> assets;


// check for recordable tracks
	if(!get_recordable_tracks(default_asset))
	{
		sprintf(string, _("No recordable tracks specified."));
		ErrorBox error(PROGRAM_NAME ": Error");
		error.create_objects(string);
		error.run_window();
		default_asset->Garbage::remove_user();
		return;
	}

// check for plugins
	if(!plugindb->total)
	{
		sprintf(string, _("No plugins available."));
		ErrorBox error(PROGRAM_NAME ": Error");
		error.create_objects(string);
		error.run_window();
		default_asset->Garbage::remove_user();
		return;
	}


// get default attributes for output file
// used after completion
	get_derived_attributes(default_asset, defaults);
//	to_tracks = defaults->get("RENDER_EFFECT_TO_TRACKS", 1);
	load_mode = defaults->get("RENDER_EFFECT_LOADMODE", LOADMODE_PASTE);
	strategy = defaults->get("RENDER_EFFECT_STRATEGY", SINGLE_PASS);

// get plugin information
	int need_plugin;
	if(!strlen(title)) 
		need_plugin = 1; 
	else 
		need_plugin = 0;

// generate a list of plugins for the window
	if(need_plugin)
	{
		mwindow->search_plugindb(default_asset->audio_data, 
			default_asset->video_data, 
			-1, 
			0,
			0,
			local_plugindb);

		for(int i = 0; i < local_plugindb.total; i++)
		{
			plugin_list.append(new BC_ListBoxItem(_(local_plugindb.values[i]->title)));
		}
	}

// find out which effect to run and get output file
	int plugin_number, format_error = 0;

	do
	{
		{
			MenuEffectWindow window(mwindow, 
				this, 
				need_plugin ? &plugin_list : 0, 
				default_asset);
			window.create_objects();
			result = window.run_window();
			plugin_number = window.result;
		}

		if(!result)
		{
			FormatCheck format_check(default_asset);
			format_error = format_check.check_format();
		}
	}while(format_error && !result);

// save defaults
	save_derived_attributes(default_asset, defaults);
	defaults->update("RENDER_EFFECT_LOADMODE", load_mode);
	defaults->update("RENDER_EFFECT_STRATEGY", strategy);
	mwindow->save_defaults();

// get plugin server to use and delete the plugin list
	PluginServer *plugin_server = 0;
	PluginServer *plugin = 0;
	if(need_plugin)
	{
		plugin_list.remove_all_objects();
		if(plugin_number > -1)
		{
			plugin_server = local_plugindb.values[plugin_number];
			strcpy(title, plugin_server->title);
		}
	}
	else
	{
		for(int i = 0; i < plugindb->total && !plugin_server; i++)
		{
			if(!strcmp(plugindb->values[i]->title, title))
			{
				plugin_server = plugindb->values[i];
				plugin_number = i;
			}
		}
	}

// Update the  most recently used effects and copy the plugin server.
	if(plugin_server)
	{
		plugin = new PluginServer(*plugin_server);
		fix_menu(title);
	}

	if(!result && !strlen(default_asset->path))
	{
		result = 1;        // no output path given
		ErrorBox error(PROGRAM_NAME ": Error");
		error.create_objects(_("No output file specified."));
		error.run_window();
	}

	if(!result && plugin_number < 0)
	{
		result = 1;        // no output path given
		ErrorBox error(PROGRAM_NAME ": Error");
		error.create_objects(_("No effect selected."));
		error.run_window();
	}

// Configuration for realtime plugins.
	KeyFrame plugin_data;        

// get selection to render
// Range
	double total_start, total_end;

	total_start = mwindow->edl->local_session->get_selectionstart();


	if(mwindow->edl->local_session->get_selectionend() == 
		mwindow->edl->local_session->get_selectionstart())
		total_end = mwindow->edl->tracks->total_playable_length();
	else
		total_end = mwindow->edl->local_session->get_selectionend();



// get native units for range
	total_start = to_units(total_start, 0);
	total_end = to_units(total_end, 1);



// Trick boundaries in case of a non-realtime synthesis plugin
	if(plugin && 
		!plugin->realtime && 
		total_end == total_start) total_end = total_start + 1;

// Units are now in the track's units.
	int64_t total_length = (int64_t)total_end - (int64_t)total_start;
// length of output file
	int64_t output_start, output_end;        

	if(!result && total_length <= 0)
	{
		result = 1;        // no output path given
		ErrorBox error(PROGRAM_NAME ": Error");
		error.create_objects(_("No selected range to process."));
		error.run_window();
	}

// ========================= get keyframe from user
	if(!result)
	{
// ========================= realtime plugin 
// no get_parameters
		if(plugin->realtime)
		{
// Open a prompt GUI
			MenuEffectPrompt prompt(mwindow);
			prompt.create_objects();
			char title[BCTEXTLEN];
			sprintf(title, PROGRAM_NAME ": %s", plugin->title);

// Open the plugin GUI
			plugin->set_mwindow(mwindow);
			plugin->set_keyframe(&plugin_data);
			plugin->set_prompt(&prompt);
			plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
// Must set parameters since there is no plugin object to draw from.
			plugin->get_parameters((int64_t)total_start,
				(int64_t)total_end,
				1);
			plugin->show_gui();

// wait for user input
			result = prompt.run_window();

// Close plugin.
			plugin->save_data(&plugin_data);
			plugin->hide_gui();

// Can't delete here.
			dead_plugins->append(plugin);
			default_asset->sample_rate = mwindow->edl->session->sample_rate;
			default_asset->frame_rate = mwindow->edl->session->frame_rate;
			realtime = 1;
		}
		else
// ============================non realtime plugin 
		{
			plugin->set_mwindow(mwindow);
			plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
			result = plugin->get_parameters((int64_t)total_start, 
				(int64_t)total_end, 
				get_recordable_tracks(default_asset));
// some plugins can change the sample rate and the frame rate


			if(!result)
			{
				default_asset->sample_rate = plugin->get_samplerate();
				default_asset->frame_rate = plugin->get_framerate();
			}
			delete plugin;
			realtime = 0;
		}

// Should take from first recordable track
		default_asset->width = mwindow->edl->session->output_w;
		default_asset->height = mwindow->edl->session->output_h;
	}

// Process the total length in fragments
	ArrayList<MenuEffectPacket*> packets;
	if(!result)
	{
		Label *current_label = mwindow->edl->labels->first;
		mwindow->stop_brender();

		int current_number;
		int number_start;
		int total_digits;
		Render::get_starting_number(default_asset->path, 
			current_number,
			number_start, 
			total_digits);



// Construct all packets for single overwrite confirmation
		for(int64_t fragment_start = (int64_t)total_start, fragment_end;
			fragment_start < (int64_t)total_end;
			fragment_start = fragment_end)
		{
// Get fragment end
			if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
			{
				while(current_label  &&
					to_units(current_label->position, 0) <= fragment_start)
					current_label = current_label->next;
				if(!current_label)
					fragment_end = (int64_t)total_end;
				else
					fragment_end = to_units(current_label->position, 0);
			}
			else
			{
				fragment_end = (int64_t)total_end;
			}

// Get path
			char path[BCTEXTLEN];
			if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM) 
				Render::create_filename(path, 
					default_asset->path, 
					current_number,
					total_digits,
					number_start);
			else
				strcpy(path, default_asset->path);
			current_number++;

			MenuEffectPacket *packet = new MenuEffectPacket(path, 
				fragment_start,
				fragment_end);
			packets.append(packet);
		}


// Test existence of files
		ArrayList<char*> paths;
		for(int i = 0; i < packets.total; i++)
		{
			paths.append(packets.values[i]->path);
		}
		result = ConfirmSave::test_files(mwindow, &paths);
		paths.remove_all();
	}



	for(int current_packet = 0; 
		current_packet < packets.total && !result; 
		current_packet++)
	{
		Asset *asset = new Asset(*default_asset);
		MenuEffectPacket *packet = packets.values[current_packet];
		int64_t fragment_start = packet->start;
		int64_t fragment_end = packet->end;
		strcpy(asset->path, packet->path);

		assets.append(asset);
		File *file = new File;

// Open the output file after getting the information because the sample rate
// is needed here.
		if(!result)
		{
// open output file in write mode
			file->set_processors(mwindow->preferences->processors);
			file->set_cache(mwindow->preferences->cache_size);
			if(file->open_file(mwindow->preferences, 
				asset, 
				0, 
				1))
			{
// open failed
				sprintf(string, _("Couldn't open %s"), asset->path);
				ErrorBox error(PROGRAM_NAME ": Error");
				error.create_objects(string);
				error.run_window();
				result = 1;
			}
			else
			{
				mwindow->sighandler->push_file(file);
				IndexFile::delete_index(mwindow->preferences, 
					asset);
			}
		}

// run plugins
		if(!result)
		{
// position file
			output_start = 0;

			PluginArray *plugin_array;
			plugin_array = create_plugin_array();

			plugin_array->start_plugins(mwindow, 
				mwindow->edl, 
				plugin_server, 
				&plugin_data,
				fragment_start,
				fragment_end,
				file);
			plugin_array->run_plugins();

			plugin_array->stop_plugins();
			mwindow->sighandler->pull_file(file);
			file->close_file();
			asset->audio_length = file->asset->audio_length;
			asset->video_length = file->asset->video_length;
			delete plugin_array;
		}

		delete file;
	}

	packets.remove_all_objects();

// paste output to tracks
	if(!result && load_mode != LOADMODE_NOTHING)
	{
		mwindow->gui->lock_window("MenuEffectThread::run");

		mwindow->undo->update_undo_before("", 0);
		if(load_mode == LOADMODE_PASTE)
			mwindow->clear(0);


		mwindow->load_assets(&assets,
			-1,
			load_mode,
			0,
			0,
			mwindow->edl->session->labels_follow_edits, 
			mwindow->edl->session->plugins_follow_edits,
			mwindow->edl->session->autos_follow_edits);


		mwindow->save_backup();
		mwindow->undo->update_undo_after(title, LOAD_ALL);



		mwindow->restart_brender();
		mwindow->update_plugin_guis();
		mwindow->gui->update(1, 
			2,
			1,
			1,
			1,
			1,
			0);
		mwindow->sync_parameters(CHANGE_ALL);
		mwindow->gui->unlock_window();


		mwindow->awindow->gui->lock_window("MenuEffectThread::run");
		mwindow->awindow->gui->update_assets();
		mwindow->awindow->gui->flush();
		mwindow->awindow->gui->unlock_window();


	}

	for(int i = 0; i < assets.total; i++)
		assets.values[i]->Garbage::remove_user();
	assets.remove_all();

	default_asset->Garbage::remove_user();
}
Пример #13
0
int Track::paste_automation(double selectionstart, 
	double total_length, 
	double frame_rate,
	int64_t sample_rate,
	FileXML *file,
	int default_only,
	int active_only)
{
// Only used for pasting automation alone.
	int64_t start;
	int64_t length;
	int result;
	double scale;
	int current_pluginset;

	if(data_type == TRACK_AUDIO)
		scale = edl->session->sample_rate / sample_rate;
	else
		scale = edl->session->frame_rate / frame_rate;

	total_length *= scale;
	start = to_units(selectionstart, 0);
	length = to_units(total_length, 0);
	result = 0;
	current_pluginset = 0;
//printf("Track::paste_automation 1\n");

	while(!result)
	{
		result = file->read_tag();

		if(!result)
		{
			if(file->tag.title_is("/TRACK"))
				result = 1;
			else
			if(automation->paste(start, 
					length, 
					scale,
					file,
					default_only,
					active_only,
					0))
			{
				;
			}
			else
			if(file->tag.title_is("PLUGINSET"))
			{
				if(current_pluginset < plugin_set.total)
				{
					plugin_set.values[current_pluginset]->paste_keyframes(start, 
						length, 
						file,
						default_only,
						active_only);
					current_pluginset++;
				}
			}
		}
	}
	

	return 0;
}
Пример #14
0
int Track::copy(double start, 
	double end, 
	FileXML *file, 
	const char *output_path)
{
// Use a copy of the selection in converted units
// So copy_automation doesn't reconvert.
	int64_t start_unit = to_units(start, 0);
	int64_t end_unit = to_units(end, 1);




	file->tag.set_title("TRACK");
	file->tag.set_property("RECORD", record);
	file->tag.set_property("NUDGE", nudge);
	file->tag.set_property("PLAY", play);
	file->tag.set_property("GANG", gang);
	file->tag.set_property("DRAW", draw);
	file->tag.set_property("EXPAND", expand_view);
	file->tag.set_property("TRACK_W", track_w);
	file->tag.set_property("TRACK_H", track_h);
	save_header(file);
	file->append_tag();
	file->append_newline();
	save_derived(file);

	file->tag.set_title("TITLE");
	file->append_tag();
	file->append_text(title);
	file->tag.set_title("/TITLE");
	file->append_tag();
	file->append_newline();

// 	if(data_type == TRACK_AUDIO)
// 		file->tag.set_property("TYPE", "AUDIO");
// 	else
// 		file->tag.set_property("TYPE", "VIDEO");
// 
// 	file->append_tag();
// 	file->append_newline();

	edits->copy(start_unit, end_unit, file, output_path);

	AutoConf auto_conf;
	auto_conf.set_all(1);
	automation->copy(start_unit, end_unit, file, 0, 0);


	for(int i = 0; i < plugin_set.total; i++)
	{
		plugin_set.values[i]->copy(start_unit, end_unit, file);
	}

	copy_derived(start_unit, end_unit, file);

	file->tag.set_title("/TRACK");
	file->append_tag();
	file->append_newline();
	file->append_newline();
	file->append_newline();
	file->append_newline();

	return 0;
}
Пример #15
0
Plugin* Track::insert_effect(const char *title, 
		SharedLocation *shared_location, 
		KeyFrame *default_keyframe,
		PluginSet *plugin_set,
		double start,
		double length,
		int plugin_type)
{
	if(!plugin_set)
	{
		plugin_set = new PluginSet(edl, this);
		this->plugin_set.append(plugin_set);
	}

	Plugin *plugin = 0;

// Position is identical to source plugin
	if(plugin_type == PLUGIN_SHAREDPLUGIN)
	{
		Track *source_track = tracks->get_item_number(shared_location->module);
		if(source_track)
		{
			Plugin *source_plugin = source_track->get_current_plugin(
				edl->local_session->get_selectionstart(), 
				shared_location->plugin, 
				PLAY_FORWARD, 
				1,
				0);

// From an attach operation
			if(source_plugin)
			{
				plugin = plugin_set->insert_plugin(title, 
					source_plugin->startproject, 
					source_plugin->length,
					plugin_type, 
					shared_location,
					default_keyframe,
					1);
			}
			else
// From a drag operation
			{
				plugin = plugin_set->insert_plugin(title, 
					to_units(start, 0), 
					to_units(length, 0),
					plugin_type, 
					shared_location,
					default_keyframe,
					1);
			}
		}
	}
	else
	{
// This should be done in the caller
		if(EQUIV(length, 0))
		{
			if(edl->local_session->get_selectionend() > 
				edl->local_session->get_selectionstart())
			{
				start = edl->local_session->get_selectionstart();
				length = edl->local_session->get_selectionend() - start;
			}
			else
			{
				start = 0;
				length = get_length();
			}
		}
//printf("Track::insert_effect %f %f %d %d\n", start, length, to_units(start, 0), 
//			to_units(length, 0));

		plugin = plugin_set->insert_plugin(title, 
			to_units(start, 0), 
			to_units(length, 0),
			plugin_type, 
			shared_location,
			default_keyframe,
			1);
	}
//printf("Track::insert_effect 2 %f %f\n", start, length);

	expand_view = 1;
	return plugin;
}
Пример #16
0
void Track::shuffle_edits(double start, double end, int first_track)
{
	ArrayList<Edit*> new_edits;
	ArrayList<Label*> new_labels;
	int64_t start_units = to_units(start, 0);
	int64_t end_units = to_units(end, 0);
// Sample range of all edits selected
	//int64_t total_start_units = 0;
	//int64_t total_end_units = 0;
// Edit before range
	Edit *start_edit = 0;
	int have_start_edit = 0;

// Move all edit pointers to list
	for(Edit *current = edits->first; 
		current; )
	{
		if(current->startproject >= start_units &&
			current->startproject + current->length <= end_units)
		{
			if(!have_start_edit) start_edit = current->previous;
			have_start_edit = 1;
			//total_start_units = current->startproject;
			//total_end_units = current->startproject + current->length;
			new_edits.append(current);

// Move label pointers
			if(first_track && edl->session->labels_follow_edits)
			{
				double start_seconds = from_units(current->startproject);
				double end_seconds = from_units(current->startproject +
					current->length);
				for(Label *label = edl->labels->first;
					label;
					label = label->next)
				{
					if(label->position >= start_seconds &&
						label->position < end_seconds)
					{
						new_labels.append(label);
						edl->labels->remove_pointer(label);
					}
				}
			}

// Remove edit pointer
			Edit *previous = current;
			current = NEXT;
			edits->remove_pointer(previous);
		}
		else
		{
			current = NEXT;
		}
	}

// Insert pointers in random order
	while(new_edits.size())
	{
		int index = rand() % new_edits.size();
		Edit *edit = new_edits.get(index);
		new_edits.remove_number(index);
		edits->insert_after(start_edit, edit);
		start_edit = edit;

// Recalculate start position
// Save old position for moving labels
		int64_t startproject1 = edit->startproject;
		int64_t startproject2 = 0;
		if(edit->previous)
		{
			edit->startproject = 
				startproject2 =
				edit->previous->startproject + edit->previous->length;
		}
		else
		{
			edit->startproject = startproject2 = 0;
		}


// Insert label pointers
		if(first_track && edl->session->labels_follow_edits)
		{
			double start_seconds1 = from_units(startproject1);
			double start_seconds2 = from_units(startproject2);
			//double end_seconds1 = from_units(edit->startproject +
			//	edit->length);
			for(int i = new_labels.size() - 1; i >= 0; i--)
			{
				Label *label = new_labels.get(i);
// Was in old edit position
				if(label->position >= start_seconds1 &&
					label->position < start_seconds2)
				{
// Move to new edit position
					double position = label->position - 
						start_seconds1 + 
						start_seconds2;
					edl->labels->insert_label(position);
					new_labels.remove_object_number(i);
				}
			}
		}


	}
	
	optimize();
	
	if(first_track && edl->session->labels_follow_edits)
	{
		edl->labels->optimize();
	}
}
Пример #17
0
void Track::align_edits(double start, 
	double end, 
	ArrayList<double> *times)
{
	int64_t start_units = to_units(start, 0);
	int64_t end_units = to_units(end, 0);

// If 1st track with data, times is empty & we need to collect the edit times.
	if(!times->size())
	{
		for(Edit *current = edits->first; current; current = NEXT)
		{
			if(current->startproject >= start_units &&
				current->startproject + current->length <= end_units)
			{
				times->append(from_units(current->startproject));
			}
		}
	}
	else
// All other tracks get silence or cut to align the edits on the times.
	{
		int current_time = 0;
		for(Edit *current = edits->first; 
			current && current_time < times->size(); )
		{
			if(current->startproject >= start_units &&
				current->startproject + current->length <= end_units)
			{
				int64_t desired_startunits = to_units(times->get(current_time), 0);
				int64_t current_startunits = current->startproject;
				current = NEXT;


				if(current_startunits < desired_startunits)
				{
//printf("Track::align_edits %d\n", __LINE__);
					edits->paste_silence(current_startunits,
						desired_startunits);
					shift_keyframes(current_startunits,
						desired_startunits - current_startunits);
				}
				else
				if(current_startunits > desired_startunits)
				{
					edits->clear(desired_startunits,
						current_startunits);
					if(edl->session->autos_follow_edits)
						shift_keyframes(desired_startunits,
							current_startunits - desired_startunits);
				}

				current_time++;
			}
			else
			{
				current = NEXT;
			}
		}
	}

	optimize();
}