The following is a patch so that when loading and pasting / dragging onto timeline, etc.. the length of the inserted material is the minimum of all the the tracks rounded to the nearest frame. This fixes issues I (and others) have when working with mpeg files that audio and video of different lengths.

It introduces an annoyance (that is resolve by turning off "align cursor to frame" ) where a clip having tracks of intentionally different frame length (that is already cut properly) will be pasted incorrectly..

Can people test before committing?

pierre

diff --git a/cinelerra/asset.C b/cinelerra/asset.C
index 1610374..2fc4772 100644
--- a/cinelerra/asset.C
+++ b/cinelerra/asset.C
@@ -3,6 +3,7 @@ #include "asset.h"
 #include "assets.h"
 #include "bchash.h"
 #include "bcsignals.h"
+#include "clip.h"
 #include "edl.h"
 #include "file.h"
 #include "filesystem.h"
@@ -1200,6 +1201,21 @@ int Asset::update_path(char *new_path)
 	return 0;
 }
 
+double Asset::total_length_framealigned(double fps) 
+{
+	if (video_data && audio_data) {
+		double aud = floor(( (double)audio_length / sample_rate) * fps) / fps;
+		double vid = floor(( (double)video_length / frame_rate) * fps) / fps;
+		return MIN(aud,vid);
+	}
+	
+	if (audio_data)
+		return (double)audio_length / sample_rate;
+	
+	if (video_data)
+		return (double)video_length / frame_rate;
+}
+
 void Asset::update_index(Asset *asset)
 {
 //printf("Asset::update_index 1 %d\n", index_status);
diff --git a/cinelerra/asset.h b/cinelerra/asset.h
index ee289fa..8e3fd49 100644
--- a/cinelerra/asset.h
+++ b/cinelerra/asset.h
@@ -101,6 +101,8 @@ public:
 	int write_index(FileXML *xml);
 	int update_path(char *new_path);
 
+	double total_length_framealigned(double fps);
+
 // Path to file
 	char path[BCTEXTLEN];
 
diff --git a/cinelerra/edits.C b/cinelerra/edits.C
index 35956ac..f9d6fb7 100644
--- a/cinelerra/edits.C
+++ b/cinelerra/edits.C
@@ -701,6 +701,8 @@ void Edits::clear(int64_t start, int64_t
 	}
 
 	optimize();
+// Reset the loaded_length value. (the last edit should always be a silence going to infinityish)
+	loaded_length = last->startproject;
 }
 
 // Used by edit handle and plugin handle movement but plugin handle movement
diff --git a/cinelerra/mwindowedit.C b/cinelerra/mwindowedit.C
index bf5e2e0..c5b341a 100644
--- a/cinelerra/mwindowedit.C
+++ b/cinelerra/mwindowedit.C
@@ -1421,6 +1421,12 @@ SET_TRACE
 			edl->session->frame_rate, 
 			TRACK_VIDEO);
 
+// Align cursor on frames:: clip the new edl to paste to the last joint frame.
+		if (edl->session->cursor_on_frames)
+		{
+			edl_length = new_edl->tracks->total_length_framealigned(edl->session->frame_rate);
+			new_edl->tracks->clear(edl_length, new_edl->tracks->total_length() + 100, 1);
+		}
 SET_TRACE
 
 
diff --git a/cinelerra/track.C b/cinelerra/track.C
index 00e893f..4d8333b 100644
--- a/cinelerra/track.C
+++ b/cinelerra/track.C
@@ -1148,6 +1148,7 @@ int Track::clear(double start, 
 
 	if(edit_edits)
 		edits->clear((int64_t)start, (int64_t)end);
+
 	return 0;
 }
 
diff --git a/cinelerra/trackcanvas.C b/cinelerra/trackcanvas.C
index 04dad9a..56277df 100644
--- a/cinelerra/trackcanvas.C
+++ b/cinelerra/trackcanvas.C
@@ -1097,6 +1097,67 @@ void TrackCanvas::draw_paste_destination
 			mwindow->session->drag_clips->total)
 			clip = mwindow->session->drag_clips->values[0];
 
+// 'Align cursor of frame' lengths calculations
+		double paste_audio_length, paste_video_length;
+		int64_t asset_length;
+		double desta_position = 0;
+		double destv_position = 0;
+
+		if (asset)
+		{
+			double asset_length_ac = asset->total_length_framealigned(mwindow->edl->session->frame_rate);
+			if (mwindow->edl->session->cursor_on_frames)
+			{
+				paste_video_length = paste_audio_length = asset_length_ac;
+			} 
+			else 
+			{
+				paste_audio_length = (double)asset->audio_length / asset->sample_rate;
+				paste_video_length = (double)asset->video_length / asset->frame_rate;
+			}
+
+			// Images have length -1 (they are a single image!!)
+			if (asset->video_data && asset->video_length < 0)
+			{
+				if(mwindow->edl->session->si_useduration)
+					paste_video_length = mwindow->edl->session->si_duration / asset->frame_rate;
+				else	
+					paste_video_length = 1.0 / asset->frame_rate;  // bit confused!! (this is 1 frame)
+			}
+
+			int64_t asset_length = 0;
+
+			if(asset->audio_data)
+			{
+				// we use video if we are over video and audio if we are over audio
+				if(asset->video_data && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)
+					asset_length = mwindow->session->track_highlighted->to_units(paste_video_length, 1);
+				else
+					asset_length = mwindow->session->track_highlighted->to_units(paste_audio_length, 1);
+
+				desta_position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+			}
+
+			if(asset->video_data)
+			{
+				asset_length = mwindow->session->track_highlighted->to_units((double)paste_video_length, 1);
+				destv_position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+			}
+		}
+
+		if(clip)
+		{
+			if(mwindow->edl->session->cursor_on_frames)
+				paste_audio_length = paste_video_length = clip->tracks->total_length_framealigned(mwindow->edl->session->frame_rate);
+			else
+				paste_audio_length = paste_video_length = clip->tracks->total_length();
+
+			int64_t asset_length;
+
+			asset_length   = mwindow->session->track_highlighted->to_units((double)clip->tracks->total_length(), 1);
+			desta_position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+		}
+
 // Get destination track
 		for(Track *dest = mwindow->session->track_highlighted; 
 			dest; 
@@ -1119,51 +1180,14 @@ void TrackCanvas::draw_paste_destination
 
 				if(dest->data_type == TRACK_AUDIO)
 				{
-					if(asset && current_atrack < asset->channels)
-					{
-						w = Units::to_int64((double)asset->audio_length /
-							asset->sample_rate *
-							mwindow->edl->session->sample_rate / 
-							mwindow->edl->local_session->zoom_sample);
-
-					// FIXME: more obvious, get_drop_position should be called only ONCE - for highlighted track
-						int64_t asset_length;
-						// we use video if we are over video and audio if we are over audio
-						if (asset->video_data && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)
-						{
-							// Images have length -1
-							double video_length = asset->video_length;
-							if (video_length < 0)
-							{
-								if(mwindow->edl->session->si_useduration)
-									video_length = mwindow->edl->session->si_duration;
-								else	
-									video_length = 1.0 / mwindow->edl->session->frame_rate ; 
-							}
-							asset_length = mwindow->session->track_highlighted->to_units(video_length / asset->frame_rate, 1);
-						}
-						else
-							asset_length = mwindow->session->track_highlighted->to_units(asset->audio_length / asset->sample_rate, 1);
-
-						position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
-						if (position < 0) 
-							w = -1;
-						else
-						{
-							current_atrack++;
-							draw_box = 1;
-						}
-					}
-					else
-					if(clip && current_atrack < clip->tracks->total_audio_tracks())
+					if( (asset && current_atrack < asset->channels)
+				|| (clip  && current_atrack < clip->tracks->total_audio_tracks()) )
 					{
-						w = Units::to_int64((double)clip->tracks->total_length() *
+						w = Units::to_int64(paste_audio_length *
 							mwindow->edl->session->sample_rate / 
 							mwindow->edl->local_session->zoom_sample);
-//printf("draw_paste_destination %d\n", x);
-						int64_t asset_length = mwindow->session->track_highlighted->to_units((double)clip->tracks->total_length(), 1);
 
-						position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+						position = desta_position;
 						if (position < 0) 
 							w = -1;
 						else
@@ -1201,42 +1225,15 @@ void TrackCanvas::draw_paste_destination
 				if(dest->data_type == TRACK_VIDEO)
 				{
 //printf("draw_paste_destination 1\n");
-					if(asset && current_vtrack < asset->layers)
+					if( (asset && current_vtrack < asset->layers)
+					|| (clip && current_vtrack < clip->tracks->total_video_tracks()) )
 					{
 						// Images have length -1
-						double video_length = asset->video_length;
-						if (video_length < 0)
-						{
-							if(mwindow->edl->session->si_useduration)
-								video_length = mwindow->edl->session->si_duration;
-							else	
-								video_length = 1.0 / mwindow->edl->session->frame_rate ; 
-						}
-						w = Units::to_int64((double)video_length / 
-							asset->frame_rate *
+						w = Units::to_int64((double)paste_video_length *
 							mwindow->edl->session->sample_rate /
 							mwindow->edl->local_session->zoom_sample);
-						int64_t asset_length = mwindow->session->track_highlighted->to_units((double)video_length / 
-							asset->frame_rate, 1);
-
-						position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
-						if (position < 0) 
-							w = -1;
-						else
-						{
-							current_vtrack++;
-							draw_box = 1;
-						}
-					}
-					else
-					if(clip && current_vtrack < clip->tracks->total_video_tracks())
-					{
-						w = Units::to_int64(clip->tracks->total_length() *
-							mwindow->edl->session->sample_rate / 
-							mwindow->edl->local_session->zoom_sample);
-						int64_t asset_length = mwindow->session->track_highlighted->to_units((double)clip->tracks->total_length(), 1);
 
-						position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+						position = destv_position;
 						if (position < 0) 
 							w = -1;
 						else
diff --git a/cinelerra/tracks.C b/cinelerra/tracks.C
index bf4d619..c9a8326 100644
--- a/cinelerra/tracks.C
+++ b/cinelerra/tracks.C
@@ -1,6 +1,7 @@
 #include "atrack.h"
 #include "automation.h"
 #include "cursor.h"
+#include "clip.h"
 #include "bchash.h"
 #include "edit.h"
 #include "edits.h"
@@ -442,6 +443,17 @@ double Tracks::total_length() 
 	return total; 
 }
 
+double Tracks::total_audio_length() 
+{
+	double total = 0;
+	for(Track *current = first; current; current = NEXT)
+	{
+		if(current->data_type == TRACK_AUDIO &&
+			current->get_length() > total) total = current->get_length();
+	}
+	return total; 
+}
+
 double Tracks::total_video_length() 
 {
 	double total = 0;
@@ -453,6 +465,19 @@ double Tracks::total_video_length() 
 	return total; 
 }
 
+double Tracks::total_length_framealigned(double fps)
+{
+	if (total_audio_tracks() && total_video_tracks())
+		return MIN(floor(total_audio_length()*fps), floor(total_video_length()*fps))/ fps;
+
+	if (total_audio_tracks())
+		return floor(total_audio_length()*fps) / fps;
+
+	if (total_video_tracks())
+		return floor(total_video_length()*fps) / fps;
+
+	return 0;
+}
 
 void Tracks::translate_camera(float offset_x, float offset_y)
 {
diff --git a/cinelerra/tracks.h b/cinelerra/tracks.h
index 876140b..5c2abba 100644
--- a/cinelerra/tracks.h
+++ b/cinelerra/tracks.h
@@ -67,7 +67,9 @@ public:
 	int total_video_tracks();
 // return the longest track in all the tracks in seconds
  	double total_length();
+ 	double total_audio_length();
  	double total_video_length();
+	double total_length_framealigned(double fps);
 // Update y pixels after a zoom
 	void update_y_pixels(Theme *theme);
 // Total number of tracks where the following toggles are selected

Reply via email to