From c9c0e07706fad701a70ee0d1ffb0fcb6304f138c Mon Sep 17 00:00:00 2001
From: Good Guy <good1.2guy@gmail.com>
Date: Sun, 19 Jul 2020 18:09:46 -0600
Subject: [PATCH] add timecode units/alignment/probe, add prefs auto_rotate,
 ffmpeg ssse3 patchB for flip/rotate, fix assetpopup deadlocks, renderfarm
 1frm render fix, resampleRT segv, info tweaks, plugin.opts vaapi tweaks

---
 cinelerra-5.1/cinelerra/appearanceprefs.C     |  33 ++
 cinelerra-5.1/cinelerra/appearanceprefs.h     |  18 +
 cinelerra-5.1/cinelerra/appearanceprefs.inc   |   2 +
 cinelerra-5.1/cinelerra/asset.C               |  16 +-
 cinelerra-5.1/cinelerra/asset.h               |  10 +-
 cinelerra-5.1/cinelerra/assetedit.C           |  45 +-
 cinelerra-5.1/cinelerra/assetedit.h           |   2 +
 cinelerra-5.1/cinelerra/assetpopup.C          |  18 +-
 cinelerra-5.1/cinelerra/batchrender.C         |   4 +-
 cinelerra-5.1/cinelerra/cwindowgui.C          |   3 +-
 cinelerra-5.1/cinelerra/editpanel.C           | 206 ++++++++-
 cinelerra-5.1/cinelerra/editpanel.h           |  70 ++-
 cinelerra-5.1/cinelerra/editpanel.inc         |   5 +-
 cinelerra-5.1/cinelerra/editpopup.C           |  29 ++
 cinelerra-5.1/cinelerra/editpopup.h           |   9 +
 cinelerra-5.1/cinelerra/editpopup.inc         |   1 +
 cinelerra-5.1/cinelerra/edits.C               |  56 +++
 cinelerra-5.1/cinelerra/edits.h               |   2 +
 cinelerra-5.1/cinelerra/edlsession.C          |   6 +
 cinelerra-5.1/cinelerra/edlsession.h          |   4 +-
 cinelerra-5.1/cinelerra/ffmpeg.C              | 399 +++++++++++++++---
 cinelerra-5.1/cinelerra/ffmpeg.h              |  44 +-
 cinelerra-5.1/cinelerra/mainclock.C           |   6 +-
 cinelerra-5.1/cinelerra/mainmenu.C            |  14 +
 cinelerra-5.1/cinelerra/mainmenu.h            |   9 +
 cinelerra-5.1/cinelerra/mainmenu.inc          |   1 +
 cinelerra-5.1/cinelerra/mbuttons.C            |   3 +-
 cinelerra-5.1/cinelerra/menueffects.C         |   4 +-
 cinelerra-5.1/cinelerra/mtimebar.C            |  19 +-
 cinelerra-5.1/cinelerra/mwindow.C             |  43 +-
 cinelerra-5.1/cinelerra/mwindow.h             |   3 +
 cinelerra-5.1/cinelerra/mwindowedit.C         |  12 +
 cinelerra-5.1/cinelerra/mwindowmove.C         |  38 +-
 cinelerra-5.1/cinelerra/pluginclient.h        |  36 +-
 cinelerra-5.1/cinelerra/preferences.C         |   4 +
 cinelerra-5.1/cinelerra/preferences.h         |   2 +
 cinelerra-5.1/cinelerra/render.C              |  11 +-
 cinelerra-5.1/cinelerra/render.h              |   2 +-
 cinelerra-5.1/cinelerra/tracks.C              |  18 +
 cinelerra-5.1/cinelerra/tracks.h              |   1 +
 cinelerra-5.1/cinelerra/vwindowgui.C          |   3 +-
 cinelerra-5.1/cinelerra/zoombar.C             |   6 +-
 cinelerra-5.1/cinelerra/zoompanel.C           |   3 +-
 cinelerra-5.1/doc/shortcuts.html              |   2 +-
 cinelerra-5.1/ffmpeg/plugin.opts              |   2 +
 cinelerra-5.1/guicast/bccmodels.C             |   2 +-
 cinelerra-5.1/guicast/bccmodels.h             |   2 +-
 cinelerra-5.1/guicast/units.C                 |  25 +-
 cinelerra-5.1/guicast/units.h                 |  18 +-
 cinelerra-5.1/guicast/vframe.C                |   2 +-
 cinelerra-5.1/info/plugins.txt                |  21 +
 cinelerra-5.1/plugins/resamplert/resamplert.C |   3 +-
 cinelerra-5.1/plugins/resamplert/resamplert.h |   2 +-
 .../plugins/theme_blond/blondtheme.C          |   1 +
 .../plugins/theme_blond/data/clapper.png      | Bin 0 -> 1382 bytes
 .../plugins/theme_blond_cv/blondcvtheme.C     |   1 +
 .../plugins/theme_blond_cv/data/clapper.png   | Bin 0 -> 1382 bytes
 cinelerra-5.1/plugins/theme_blue/bluetheme.C  |   1 +
 .../plugins/theme_blue/data/clapper.png       | Bin 0 -> 1382 bytes
 .../plugins/theme_blue_dot/bluedottheme.C     |   1 +
 .../plugins/theme_blue_dot/data/clapper.png   | Bin 0 -> 1382 bytes
 .../plugins/theme_bright/brighttheme.C        |   1 +
 .../plugins/theme_bright/data/clapper.png     | Bin 0 -> 1382 bytes
 .../plugins/theme_cakewalk/cakewalk.C         |   3 +
 .../plugins/theme_cakewalk/data/clapper.png   | Bin 0 -> 1382 bytes
 .../plugins/theme_hulk/data/clapper.png       | Bin 0 -> 1382 bytes
 cinelerra-5.1/plugins/theme_hulk/hulktheme.C  |   1 +
 .../plugins/theme_neophyte/data/clapper.png   | Bin 0 -> 1382 bytes
 .../plugins/theme_neophyte/neophyte.C         |   3 +
 .../plugins/theme_pinklady/data/clapper.png   | Bin 0 -> 1382 bytes
 .../plugins/theme_pinklady/pinkladytheme.C    |   1 +
 .../plugins/theme_suv/data/clapper.png        | Bin 0 -> 1382 bytes
 cinelerra-5.1/plugins/theme_suv/suv.C         |   1 +
 .../plugins/theme_unflat/data/clapper.png     | Bin 0 -> 1382 bytes
 .../plugins/theme_unflat/unflattheme.C        |   1 +
 .../thirdparty/src/ffmpeg-4.3.patchB          |  43 ++
 76 files changed, 1183 insertions(+), 174 deletions(-)
 create mode 100755 cinelerra-5.1/plugins/theme_blond/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_blond_cv/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_blue/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_blue_dot/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_bright/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_cakewalk/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_hulk/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_neophyte/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_pinklady/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_suv/data/clapper.png
 create mode 100755 cinelerra-5.1/plugins/theme_unflat/data/clapper.png
 create mode 100644 cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patchB

diff --git a/cinelerra-5.1/cinelerra/appearanceprefs.C b/cinelerra-5.1/cinelerra/appearanceprefs.C
index 1c6be931..94327471 100644
--- a/cinelerra-5.1/cinelerra/appearanceprefs.C
+++ b/cinelerra-5.1/cinelerra/appearanceprefs.C
@@ -38,6 +38,7 @@ AppearancePrefs::AppearancePrefs(MWindow *mwindow, PreferencesWindow *pwindow)
 {
 	hms = 0;
 	hmsf = 0;
+	timecode = 0;
 	samples = 0;
 	frames = 0;
 	hex = 0;
@@ -52,6 +53,7 @@ AppearancePrefs::~AppearancePrefs()
 {
 	delete hms;
 	delete hmsf;
+	delete timecode;
 	delete samples;
 	delete frames;
 	delete hex;
@@ -131,6 +133,10 @@ void AppearancePrefs::create_objects()
 		pwindow->thread->edl->session->time_format == TIME_HMSF,
 		x, y));
 	y += ys20;
+	add_subwindow(timecode = new TimeFormatTimecode(pwindow, this,
+		pwindow->thread->edl->session->time_format == TIME_TIMECODE,
+		x, y));
+	y += ys20;
 	add_subwindow(samples = new TimeFormatSamples(pwindow, this,
 		pwindow->thread->edl->session->time_format == TIME_SAMPLES,
 		x, y));
@@ -258,6 +264,9 @@ void AppearancePrefs::create_objects()
 	DeactivateFocusPolicy *focus_deactivate = new DeactivateFocusPolicy(pwindow, x, y);
 	add_subwindow(focus_deactivate);
 	y += focus_deactivate->get_h() + ys5;
+	AutoRotate *auto_rotate = new AutoRotate(pwindow, x, y);
+	add_subwindow(auto_rotate);
+	y += auto_rotate->get_h() + ys5;
 }
 
 int AppearancePrefs::update(int new_value)
@@ -266,6 +275,7 @@ int AppearancePrefs::update(int new_value)
 	pwindow->thread->edl->session->time_format = new_value;
 	hms->update(new_value == TIME_HMS);
 	hmsf->update(new_value == TIME_HMSF);
+	timecode->update(new_value == TIME_TIMECODE);
 	samples->update(new_value == TIME_SAMPLES);
 	hex->update(new_value == TIME_SAMPLES_HEX);
 	frames->update(new_value == TIME_FRAMES);
@@ -295,6 +305,16 @@ int TimeFormatHMSF::handle_event()
 	return 1;
 }
 
+TimeFormatTimecode::TimeFormatTimecode(PreferencesWindow *pwindow, AppearancePrefs *tfwindow, int value, int x, int y)
+ : BC_Radial(x, y, value, TIME_TIMECODE_TEXT)
+{ this->pwindow = pwindow; this->tfwindow = tfwindow; }
+
+int TimeFormatTimecode::handle_event()
+{
+	tfwindow->update(TIME_TIMECODE);
+	return 1;
+}
+
 TimeFormatSamples::TimeFormatSamples(PreferencesWindow *pwindow, AppearancePrefs *tfwindow, int value, int x, int y)
  : BC_Radial(x, y, value, TIME_SAMPLES_TEXT)
 { this->pwindow = pwindow; this->tfwindow = tfwindow; }
@@ -702,6 +722,19 @@ int DeactivateFocusPolicy::handle_event()
 	return 1;
 }
 
+AutoRotate::AutoRotate(PreferencesWindow *pwindow, int x, int y)
+ : BC_CheckBox(x, y, pwindow->thread->preferences->auto_rotate != 0,
+	_("Auto rotate ffmpeg media"))
+{
+	this->pwindow = pwindow;
+}
+
+int AutoRotate::handle_event()
+{
+	pwindow->thread->preferences->auto_rotate = get_value();
+	return 1;
+}
+
 ForwardRenderDisplacement::ForwardRenderDisplacement(PreferencesWindow *pwindow, int x, int y)
  : BC_CheckBox(x, y, pwindow->thread->preferences->forward_render_displacement,
 	_("Always show next frame"))
diff --git a/cinelerra-5.1/cinelerra/appearanceprefs.h b/cinelerra-5.1/cinelerra/appearanceprefs.h
index e7ef3426..96a6a41e 100644
--- a/cinelerra-5.1/cinelerra/appearanceprefs.h
+++ b/cinelerra-5.1/cinelerra/appearanceprefs.h
@@ -42,6 +42,7 @@ public:
 	int update(int new_value);
 	TimeFormatHMS *hms;
 	TimeFormatHMSF *hmsf;
+	TimeFormatTimecode *timecode;
 	TimeFormatSamples *samples;
 	TimeFormatHex *hex;
 	TimeFormatFrames *frames;
@@ -76,6 +77,15 @@ public:
 	AppearancePrefs *tfwindow;
 };
 
+class TimeFormatTimecode : public BC_Radial
+{
+public:
+	TimeFormatTimecode(PreferencesWindow *pwindow, AppearancePrefs *tfwindow, int value, int x, int y);
+	int handle_event();
+	PreferencesWindow *pwindow;
+	AppearancePrefs *tfwindow;
+};
+
 class TimeFormatSamples : public BC_Radial
 {
 public:
@@ -311,6 +321,14 @@ public:
 	PreferencesWindow *pwindow;
 };
 
+class AutoRotate: public BC_CheckBox
+{
+public:
+	AutoRotate(PreferencesWindow *pwindow, int x, int y);
+	int handle_event();
+	PreferencesWindow *pwindow;
+};
+
 class ForwardRenderDisplacement : public BC_CheckBox
 {
 public:
diff --git a/cinelerra-5.1/cinelerra/appearanceprefs.inc b/cinelerra-5.1/cinelerra/appearanceprefs.inc
index 6b117a93..5515b3fd 100644
--- a/cinelerra-5.1/cinelerra/appearanceprefs.inc
+++ b/cinelerra-5.1/cinelerra/appearanceprefs.inc
@@ -25,6 +25,7 @@
 class AppearancePrefs;
 class TimeFormatHMS;
 class TimeFormatHMSF;
+class TimeFormatTimecode;
 class TimeFormatSamples;
 class TimeFormatFrames;
 class TimeFormatHex;
@@ -50,6 +51,7 @@ class PopupMenuBtnup;
 class GrabFocusPolicy;
 class ActivateFocusPolicy;
 class DeactivateFocusPolicy;
+class AutoRotate;
 class ForwardRenderDisplacement;
 class HighlightInverseColor;
 class YuvColorSpace;
diff --git a/cinelerra-5.1/cinelerra/asset.C b/cinelerra-5.1/cinelerra/asset.C
index 751660ad..fab58403 100644
--- a/cinelerra-5.1/cinelerra/asset.C
+++ b/cinelerra-5.1/cinelerra/asset.C
@@ -167,6 +167,7 @@ void Asset::reset_video()
 	proxy_scale = 0; // not a proxy
 	proxy_edl = 0; // not proxy from edl
 	video_length = 0;
+	timecode = -2; // unknown
 	single_frame = 0;
 	vmpeg_cmodel = BC_YUV420P;
 	frame_rate = 0;
@@ -217,6 +218,7 @@ void Asset::copy_format(Asset *asset, int do_index)
 	use_header = asset->use_header;
 	aspect_ratio = asset->aspect_ratio;
 	interlace_mode = asset->interlace_mode;
+	timecode = asset->timecode;
 
 	video_data = asset->video_data;
 	layers = asset->layers;
@@ -378,7 +380,8 @@ int Asset::equivalent(Asset &asset, int test_audio, int test_video, EDL *edl)
 		result = (layers == asset.layers &&
 			program == asset.program &&
 			frame_rate == asset.frame_rate &&
-			asset.interlace_mode    == interlace_mode &&
+			asset.interlace_mode == interlace_mode &&
+			asset.timecode == timecode &&
 			width == asset.width &&
 			height == asset.height &&
 			!strcmp(vcodec, asset.vcodec) &&
@@ -482,6 +485,7 @@ int Asset::read_video(FileXML *file)
 	file->tag.get_property("VCODEC", vcodec);
 
 	video_length = file->tag.get_property("VIDEO_LENGTH", (int64_t)0);
+	timecode = file->tag.get_property("TIMECODE", -2);
 	mov_sphere = file->tag.get_property("MOV_SPHERE", 0);
 	jpeg_sphere = file->tag.get_property("JPEG_SPHERE", 0);
 	single_frame = file->tag.get_property("SINGLE_FRAME", (int64_t)0);
@@ -649,6 +653,7 @@ int Asset::write_video(FileXML *file)
 		file->tag.set_property("VCODEC", vcodec);
 
 	file->tag.set_property("VIDEO_LENGTH", video_length);
+	file->tag.set_property("TIMECODE", timecode);
 	file->tag.set_property("MOV_SPHERE", mov_sphere);
 	file->tag.set_property("JPEG_SPHERE", jpeg_sphere);
 	file->tag.set_property("SINGLE_FRAME", single_frame);
@@ -995,11 +1000,10 @@ int Asset::dump(FILE *fp)
 		" height %d vcodec %s aspect_ratio %f ilace_mode %s\n",
 		video_data, layers, program, frame_rate, width, height,
 		vcodec, aspect_ratio,string);
-	fprintf(fp,"   actual_width %d actual_height %d proxy_scale %d proxy_edl %d"
-		" video_length %jd repeat %d\n",
-		actual_width, actual_height, proxy_scale, proxy_edl, video_length,
-		single_frame);
-	fprintf(fp,"   video_length %jd repeat %d\n", video_length, single_frame);
+	fprintf(fp,"   actual_width %d actual_height %d proxy_scale %d proxy_edl %d\n",
+		actual_width, actual_height, proxy_scale, proxy_edl);
+	fprintf(fp,"   video_length %jd repeat %d timecode %f\n",
+		video_length, single_frame, timecode);
 	fprintf(fp,"   mov_sphere=%d jpeg_sphere=%d\n", mov_sphere, jpeg_sphere);
 	return 0;
 }
diff --git a/cinelerra-5.1/cinelerra/asset.h b/cinelerra-5.1/cinelerra/asset.h
index ce922c22..bb40ed4a 100644
--- a/cinelerra-5.1/cinelerra/asset.h
+++ b/cinelerra-5.1/cinelerra/asset.h
@@ -36,12 +36,6 @@
 #include "pluginserver.inc"
 
 
-// Time code formats
-#define TC_DROPFRAME 0
-#define TC_NONDROPFRAME 1
-#define TC_PAL 2
-#define TC_FILM 3
-
 class Asset : public Indexable, public ListItem<Asset>
 {
 public:
@@ -155,8 +149,8 @@ public:
 // Length in frames
 // -1 means a still photo
 	int64_t video_length;
-
-
+// timecode, unknown=-2, no timecode=-1, timecode>=0 
+	double timecode;
 
 // mp3 compression
 	int mp3_bitrate;
diff --git a/cinelerra-5.1/cinelerra/assetedit.C b/cinelerra-5.1/cinelerra/assetedit.C
index 6222f1c6..e603ad8c 100644
--- a/cinelerra-5.1/cinelerra/assetedit.C
+++ b/cinelerra-5.1/cinelerra/assetedit.C
@@ -104,6 +104,14 @@ void AssetEdit::edit_asset(Indexable *indexable, int x, int y)
 
 void AssetEdit::handle_done_event(int result)
 {
+	if( !result && changed_params->timecode >= 0 ) {
+		double rate = indexable->get_frame_rate();
+		changed_params->timecode =
+			atoi(window->tc_hrs->get_text()) * 3600 +
+			atoi(window->tc_mins->get_text()) * 60 +
+			atoi(window->tc_secs->get_text()) +
+			atoi(window->tc_rest->get_text()) / rate;
+	}
 }
 
 void AssetEdit::handle_close_event(int result)
@@ -187,14 +195,16 @@ BC_Window* AssetEdit::new_gui()
 
 int AssetEdit::window_height()
 {
-	int h = 128 + 64;
-	if( indexable->have_audio() ) h += 200;
+	int h = yS(128 + 64);
+	if( indexable->have_audio() ) h += yS(200);
 	if( indexable->have_video() ) {
-		h += 160;
+		h += yS(160);
 		if( indexable->is_asset ) {
 			Asset *asset = (Asset *)indexable;
 			if( File::can_scale_input(asset) )
-				h += 42;
+				h += yS(42);
+			if( asset->timecode >= 0 )
+				h += yS(32);
 		}
 	}
 	return yS(h);
@@ -516,8 +526,35 @@ void AssetEditWindow::create_objects()
 				&asset_edit->changed_params->interlace_mode,
 				(ArrayList<BC_ListBoxItem*>*)&mwindow->interlace_asset_modes,
 				x2 + edit_ilace_mode->get_w(), y));
+			y += title->get_h() + yS(15);
 		}
 	}
+	if( asset && asset->timecode >= 0 ) {
+		char text[BCSTRLEN], *tc = text;
+		Units::totext(tc, asset->timecode, TIME_HMSF,
+			asset->sample_rate, asset->frame_rate);
+		const char *hrs  = tc;  tc = strchr(tc, ':');  *tc++ = 0;
+		const char *mins = tc;  tc = strchr(tc, ':');  *tc++ = 0;
+		const char *secs = tc;  tc = strchr(tc, ':');  *tc++ = 0;
+		const char *rest = tc;
+		int padw = BC_Title::calculate_w(this, ":", MEDIUMFONT);
+		int fldw = BC_Title::calculate_w(this, "00", MEDIUMFONT) + 5;
+		int hdrw = fldw + padw;  x = x2;
+		add_subwindow(title = new BC_Title(x, y, _("hour"), SMALLFONT));  x += hdrw;
+		add_subwindow(title = new BC_Title(x, y, _("min"),  SMALLFONT));  x += hdrw;
+		add_subwindow(title = new BC_Title(x, y, _("sec"),  SMALLFONT));  x += hdrw;
+		add_subwindow(title = new BC_Title(x, y, _("frms"), SMALLFONT));
+		y += title->get_h() + xS(3);
+		add_subwindow(title = new BC_Title(x1, y, _("Time Code Start:")));
+		add_subwindow(tc_hrs = new BC_TextBox(x=x2, y, fldw, 1, hrs));
+		add_subwindow(new BC_Title(x += tc_hrs->get_w(), y, ":"));
+		add_subwindow(tc_mins = new BC_TextBox(x += padw, y, fldw, 1, mins));
+		add_subwindow(new BC_Title(x += tc_mins->get_w(), y, ":"));
+		add_subwindow(tc_secs = new BC_TextBox(x += padw, y , fldw, 1, secs));
+		add_subwindow(new BC_Title(x += tc_secs->get_w(), y, ":"));
+		add_subwindow(tc_rest = new BC_TextBox(x += 10, y, fldw, 1, rest));
+		y += title->get_h() + ypad5;
+	}
 
 	add_subwindow(new BC_OKButton(this));
 	add_subwindow(new BC_CancelButton(this));
diff --git a/cinelerra-5.1/cinelerra/assetedit.h b/cinelerra-5.1/cinelerra/assetedit.h
index d7426293..24e0166f 100644
--- a/cinelerra-5.1/cinelerra/assetedit.h
+++ b/cinelerra-5.1/cinelerra/assetedit.h
@@ -80,6 +80,8 @@ public:
 	AssetEdit *asset_edit;
 	BC_Title *win_width;
 	BC_Title *win_height;
+	BC_TextBox *tc_hrs, *tc_mins;
+	BC_TextBox *tc_secs, *tc_rest;
 	DetailAssetDialog *detail_dialog;
 	void show_info_detail();
 
diff --git a/cinelerra-5.1/cinelerra/assetpopup.C b/cinelerra-5.1/cinelerra/assetpopup.C
index bc428164..9eda28d7 100644
--- a/cinelerra-5.1/cinelerra/assetpopup.C
+++ b/cinelerra-5.1/cinelerra/assetpopup.C
@@ -99,19 +99,15 @@ void AssetPopup::create_objects()
 
 void AssetPopup::paste_assets()
 {
-// Collect items into the drag vectors for temporary storage
-	gui->lock_window("AssetPopup::paste_assets");
-	mwindow->gui->lock_window("AssetPopup::paste_assets");
-	mwindow->cwindow->gui->lock_window("AssetPopup::paste_assets");
-
 	int proxy = mwindow->edl->session->awindow_folder == AW_PROXY_FOLDER ? 1 : 0;
 	gui->collect_assets(proxy);
+// Collect items into the drag vectors for temporary storage
+	gui->unlock_window();
+	mwindow->gui->lock_window("AssetPopup::paste_assets");
 	mwindow->paste_assets(mwindow->edl->local_session->get_selectionstart(1),
 		mwindow->edl->tracks->first, 0);   // do not overwrite
-
-	gui->unlock_window();
 	mwindow->gui->unlock_window();
-	mwindow->cwindow->gui->unlock_window();
+	gui->lock_window("AssetPopup::paste_assets");
 }
 
 void AssetPopup::match_size()
@@ -302,8 +298,10 @@ AssetPopupBuildIndex::~AssetPopupBuildIndex()
 
 int AssetPopupBuildIndex::handle_event()
 {
+	popup->unlock_window();
 //printf("AssetPopupBuildIndex::handle_event 1\n");
 	mwindow->rebuild_indices();
+	popup->lock_window("AssetPopupBuildIndex::handle_event");
 	return 1;
 }
 
@@ -394,9 +392,11 @@ AssetPopupOpenMixer::~AssetPopupOpenMixer()
 
 int AssetPopupOpenMixer::handle_event()
 {
+	popup->unlock_window();
 	mwindow->gui->lock_window("AssetPopupOpenMixer::handle_event");
 	mwindow->create_mixers();
 	mwindow->gui->unlock_window();
+	popup->lock_window("AssetPopupOpenMixer::handle_event");
 	return 1;
 }
 
@@ -413,9 +413,11 @@ AssetPopupInsertMixer::~AssetPopupInsertMixer()
 
 int AssetPopupInsertMixer::handle_event()
 {
+	popup->unlock_window();
 	mwindow->gui->lock_window("AssetPopupInsertMixer::handle_event");
 	mwindow->create_mixers(-1);
 	mwindow->gui->unlock_window();
+	popup->lock_window("AssetPopupInsertMixer::handle_event");
 	return 1;
 }
 
diff --git a/cinelerra-5.1/cinelerra/batchrender.C b/cinelerra-5.1/cinelerra/batchrender.C
index 0694cc2f..6dcdbc62 100644
--- a/cinelerra-5.1/cinelerra/batchrender.C
+++ b/cinelerra-5.1/cinelerra/batchrender.C
@@ -181,7 +181,9 @@ char *BatchRenderJob::create_script(EDL *edl, ArrayList<Indexable *> *idxbls)
 
 int BatchRenderJob::get_strategy()
 {
-	return Render::get_strategy(farmed, labeled);
+	int range = File::is_image_render(asset->format) ?
+		RANGE_1FRAME : RANGE_SELECTION;
+	return Render::get_strategy(farmed, labeled, range);
 }
 
 
diff --git a/cinelerra-5.1/cinelerra/cwindowgui.C b/cinelerra-5.1/cinelerra/cwindowgui.C
index 7f5ddf5f..6ac2035c 100644
--- a/cinelerra-5.1/cinelerra/cwindowgui.C
+++ b/cinelerra-5.1/cinelerra/cwindowgui.C
@@ -761,7 +761,8 @@ CWindowEditing::CWindowEditing(MWindow *mwindow, CWindow *cwindow)
 		0, // use_goto
 		1, // use_clk2play
 		1, // use_scope
-		0) // use_gang_tracks
+		0, // use_gang_tracks
+		0) // use_timecode
 {
 	this->mwindow = mwindow;
 	this->cwindow = cwindow;
diff --git a/cinelerra-5.1/cinelerra/editpanel.C b/cinelerra-5.1/cinelerra/editpanel.C
index 41394277..1f75414f 100644
--- a/cinelerra-5.1/cinelerra/editpanel.C
+++ b/cinelerra-5.1/cinelerra/editpanel.C
@@ -76,7 +76,8 @@ EditPanel::EditPanel(MWindow *mwindow,
 	int use_goto,
 	int use_clk2play,
 	int use_scope,
-	int use_gang_tracks)
+	int use_gang_tracks,
+	int use_timecode)
 {
 	this->window_id = window_id;
 	this->editing_mode = editing_mode;
@@ -100,6 +101,7 @@ EditPanel::EditPanel(MWindow *mwindow,
 	this->use_clk2play = use_clk2play;
 	this->use_scope = use_scope;
 	this->use_gang_tracks = use_gang_tracks;
+	this->use_timecode = use_timecode;
 
 	this->x = x;
 	this->y = y;
@@ -322,6 +324,12 @@ void EditPanel::create_buttons()
 		scope_dialog = new EditPanelScopeDialog(mwindow, this);
 	}
 
+	if( use_timecode ) {
+		timecode = new EditPanelTimecode(mwindow, this, x1, y1);
+		subwindow->add_subwindow(timecode);
+		x1 += timecode->get_w();
+	}
+
 	if( use_gang_tracks ) {
 		gang_tracks = new EditPanelGangTracks(mwindow, this, x1, y1-yS(1));
 		subwindow->add_subwindow(gang_tracks);
@@ -448,6 +456,10 @@ void EditPanel::reposition_buttons(int x, int y)
 		scope->reposition_window(x1, y1-yS(1));
 		x1 += scope->get_w();
 	}
+	if( use_timecode ) {
+		timecode->reposition_window(x1, y1);
+		x1 += timecode->get_w();
+	}
 
 	if( use_meters ) {
 		meters->reposition_window(x1, y1);
@@ -1366,3 +1378,195 @@ int EditPanelGangTracks::handle_event()
 	return 1;
 }
 
+
+EditPanelTimecode::EditPanelTimecode(MWindow *mwindow,
+	EditPanel *panel, int x, int y)
+ : BC_Button(x, y, mwindow->theme->get_image_set("clapperbutton"))
+{
+	this->mwindow = mwindow;
+	this->panel = panel;
+	tc_dialog = 0;
+	set_tooltip(_("Set Timecode"));
+}
+
+EditPanelTimecode::~EditPanelTimecode()
+{
+	delete tc_dialog;
+}
+
+int EditPanelTimecode::handle_event()
+{
+	if( !tc_dialog )
+		tc_dialog = new EditPanelTcDialog(mwindow, panel);
+	int px, py;
+	get_pop_cursor(px, py, 0);
+	tc_dialog->start_dialog(px, py);
+	return 1;
+}
+
+EditPanelTcDialog::EditPanelTcDialog(MWindow *mwindow, EditPanel *panel)
+ : BC_DialogThread()
+{
+	this->mwindow = mwindow;
+	this->panel = panel;
+	tc_gui = 0;
+	px = py = 0;
+}
+
+EditPanelTcDialog::~EditPanelTcDialog()
+{
+	close_window();
+}
+
+#define TCW_W xS(200)
+#define TCW_H yS(120)
+
+void EditPanelTcDialog::start_dialog(int px, int py)
+{
+	this->px = px - TCW_W/2;
+	this->py = py - TCW_H/2;
+	start();
+}
+
+BC_Window *EditPanelTcDialog::new_gui()
+{
+	tc_gui = new EditPanelTcWindow(this, px, py);
+	tc_gui->create_objects();
+	double timecode = mwindow->get_timecode_offset();
+	tc_gui->update(timecode);
+	tc_gui->show_window();
+	return tc_gui;
+}
+
+void EditPanelTcDialog::handle_done_event(int result)
+{
+	if( result ) return;
+	double ofs = tc_gui->get_timecode();
+	mwindow->set_timecode_offset(ofs);
+}
+
+EditPanelTcWindow::EditPanelTcWindow(EditPanelTcDialog *tc_dialog, int x, int y)
+ : BC_Window(_(PROGRAM_NAME ": Timecode"), x, y,
+	TCW_W, TCW_H, TCW_W, TCW_H, 0, 0, 1)
+{
+	this->tc_dialog = tc_dialog;
+}
+
+EditPanelTcWindow::~EditPanelTcWindow()
+{
+}
+
+double EditPanelTcWindow::get_timecode()
+{
+	int hrs = atoi(hours->get_text());
+	int mins = atoi(minutes->get_text());
+	int secs = atoi(seconds->get_text());
+	int frms = atoi(frames->get_text());
+	double frame_rate = tc_dialog->mwindow->edl->session->frame_rate;
+	double timecode = hrs*3600 + mins*60 + secs + frms/frame_rate;
+	return timecode;
+}
+
+void EditPanelTcWindow::update(double timecode)
+{
+	if( timecode < 0 ) timecode = 0;
+	int64_t pos = timecode;
+	int hrs = pos/3600;
+	int mins = pos/60 - hrs*60;
+	int secs = pos - hrs*3600 - mins*60;
+	double frame_rate = tc_dialog->mwindow->edl->session->frame_rate;
+	int frms = (timecode-pos) * frame_rate;
+	hours->update(hrs);
+	minutes->update(mins);
+	seconds->update(secs);
+	frames->update(frms);
+}
+
+void EditPanelTcWindow::create_objects()
+{
+	lock_window("EditPanelTcWindow::create_objects");
+	int x = xS(20), y = yS(5);
+	BC_Title *title = new BC_Title(x - 2, y, _("hour  min   sec   frms"), SMALLFONT);
+	add_subwindow(title);  y += title->get_h() + xS(3);
+	hours = new EditPanelTcInt(this, x, y, xS(26), 99, "%02i");
+	add_subwindow(hours);    x += hours->get_w() + xS(4);
+	minutes = new EditPanelTcInt(this, x, y, xS(26), 59, "%02i");
+	add_subwindow(minutes);  x += minutes->get_w() + xS(4);
+	seconds = new EditPanelTcInt(this, x, y, xS(26), 60, "%02i");
+	add_subwindow(seconds);  x += seconds->get_w() + xS(4);
+	frames = new EditPanelTcInt(this, x, y, xS(34), 999, "%03i");
+	add_subwindow(frames);   x += frames->get_w() + xS(16);
+	add_subwindow(new EditPanelTcReset(this, x, y));
+	double timecode = tc_dialog->mwindow->get_timecode_offset();
+	update(timecode);
+	add_subwindow(new BC_OKButton(this));
+	add_subwindow(new BC_CancelButton(this));
+	unlock_window();
+}
+
+EditPanelTcReset::EditPanelTcReset(EditPanelTcWindow *window, int x, int y)
+ : BC_Button(x, y, window->tc_dialog->mwindow->theme->get_image_set("reset_button"))
+{
+	this->window = window;
+}
+
+int EditPanelTcReset::handle_event()
+{
+	window->update(0);
+	return 1;
+}
+
+
+EditPanelTcInt::EditPanelTcInt(EditPanelTcWindow *window, int x, int y, int w,
+	int max, const char *format)
+ : BC_TextBox(x, y, w, 1, "")
+{
+	this->window = window;
+	this->max = max;
+	this->format = format;
+	digits = 1;
+	for( int m=max; (m/=10)>0; ++digits );
+}
+
+EditPanelTcInt::~EditPanelTcInt()
+{
+}
+
+int EditPanelTcInt::handle_event()
+{
+	int v = atoi(get_text());
+	if( v > max ) {
+		v = v % (max+1);
+		char string[BCSTRLEN];
+		sprintf(string, format, v);
+		BC_TextBox::update(string);
+	}
+	return 1;
+}
+
+void EditPanelTcInt::update(int v)
+{
+	char text[BCTEXTLEN];
+	if( v > max ) v = max;
+	sprintf(text, format, v);
+	BC_TextBox::update(text);
+}
+
+int EditPanelTcInt::keypress_event()
+{
+	if( (int)strlen(get_text()) >= digits )
+		BC_TextBox::update("");
+	int key = get_keypress();
+	switch( key ) {
+	case TAB:   case LEFTTAB:
+	case LEFT:  case RIGHT:
+	case HOME:  case END:
+	case BACKSPACE:
+	case DELETE:
+	case '0': case '1': case '2': case '3': case '4':
+	case '5': case '6': case '7': case '8': case '9':
+		return BC_TextBox::keypress_event();
+	}
+	return 1;
+}
+
diff --git a/cinelerra-5.1/cinelerra/editpanel.h b/cinelerra-5.1/cinelerra/editpanel.h
index 9adbaf62..5a2bafe4 100644
--- a/cinelerra-5.1/cinelerra/editpanel.h
+++ b/cinelerra-5.1/cinelerra/editpanel.h
@@ -404,6 +404,71 @@ public:
 	MWindow *mwindow;
 };
 
+class EditPanelTimecode : public BC_Button
+{
+public:
+	EditPanelTimecode(MWindow *mwindow, EditPanel *panel, int x, int y);
+	~EditPanelTimecode();
+	int handle_event();
+	MWindow *mwindow;
+	EditPanel *panel;
+	EditPanelTcDialog *tc_dialog;
+};
+
+class EditPanelTcDialog : public BC_DialogThread
+{
+public:
+	EditPanelTcDialog(MWindow *mwindow, EditPanel *panel);
+	~EditPanelTcDialog();
+	BC_Window *new_gui();
+	void start_dialog(int px, int py);
+	void handle_done_event(int result);
+
+	MWindow *mwindow;
+	EditPanel *panel;
+	EditPanelTcWindow *tc_gui;
+	int px, py;
+};
+
+class EditPanelTcWindow : public BC_Window
+{
+public:
+	EditPanelTcWindow(EditPanelTcDialog *tc_dialog, int x, int y);
+	~EditPanelTcWindow();
+	void create_objects();
+	double get_timecode();
+	void update(double timecode);
+
+	EditPanelTcDialog *tc_dialog;
+	EditPanelTcInt *hours;
+	EditPanelTcInt *minutes;
+	EditPanelTcInt *seconds;
+	EditPanelTcInt *frames;
+};
+
+class EditPanelTcInt : public BC_TextBox
+{
+public:
+	EditPanelTcInt(EditPanelTcWindow *window, int x, int y, int w,
+		int max, const char *format);
+	~EditPanelTcInt();
+	int handle_event();
+	int keypress_event();
+	void update(int v);
+
+	EditPanelTcWindow *window;
+	int max, digits;
+	const char *format;
+};
+
+class EditPanelTcReset : public BC_Button
+{
+public:
+	EditPanelTcReset(EditPanelTcWindow *window, int x, int y);
+	int handle_event();
+
+	EditPanelTcWindow *window;
+};
 
 class EditPanel
 {
@@ -428,7 +493,8 @@ public:
 		int use_goto,
 		int use_clk2play,
 		int use_scope,
-		int use_gang_tracks);
+		int use_gang_tracks,
+		int use_timecode);
 	~EditPanel();
 
 	void set_meters(MeterPanel *meter_panel);
@@ -493,6 +559,7 @@ public:
 	int use_clk2play;
 	int use_scope;
 	int use_gang_tracks;
+	int use_timecode;
 
 	EditFit *fit;
 	EditFitAutos *fit_autos;
@@ -508,6 +575,7 @@ public:
 	EditManualGoto *mangoto;
 	EditClick2Play *click2play;
 	EditPanelScope *scope;
+	EditPanelTimecode *timecode;
 	EditPanelScopeDialog *scope_dialog;
 	EditCopy *copy;
 	EditPaste *paste;
diff --git a/cinelerra-5.1/cinelerra/editpanel.inc b/cinelerra-5.1/cinelerra/editpanel.inc
index 5b24a831..e6db6bf4 100644
--- a/cinelerra-5.1/cinelerra/editpanel.inc
+++ b/cinelerra-5.1/cinelerra/editpanel.inc
@@ -57,6 +57,9 @@ class LockLabelsButton;
 class EditPanelScopeGUI;
 class EditPanelScopeDialog;
 class EditPanelScope;
-class EditPanelMashMixers;
+class EditPanelTimecode;
+class EditPanelTcDialog;
+class EditPanelTcWindow;
+class EditPanelTcInt;
 
 #endif
diff --git a/cinelerra-5.1/cinelerra/editpopup.C b/cinelerra-5.1/cinelerra/editpopup.C
index 45d7d87a..ff66a88b 100644
--- a/cinelerra-5.1/cinelerra/editpopup.C
+++ b/cinelerra-5.1/cinelerra/editpopup.C
@@ -79,6 +79,7 @@ void EditPopup::create_objects()
 	add_item(new EditPopupOverwritePlugins(mwindow, this));
 	add_item(new EditCollectEffects(mwindow, this));
 	add_item(new EditPasteEffects(mwindow, this));
+	add_item(new EditPopupTimecode(mwindow, this));
 }
 
 int EditPopup::activate_menu(Track *track, Edit *edit,
@@ -339,4 +340,32 @@ int EditPasteEffects::handle_event()
 	return 1;
 }
 
+EditPopupTimecode::EditPopupTimecode(MWindow *mwindow, EditPopup *popup)
+ : BC_MenuItem(_("Timecode"),_("Ctrl-!"),'!')
+{
+	this->mwindow = mwindow;
+	this->popup = popup;
+	set_ctrl(1);
+}
+
+int EditPopupTimecode::handle_event()
+{
+	if( mwindow->session->current_operation != NO_OPERATION ) return 1;
+	Edit *edit = popup->edit;
+	if( !edit || !edit->asset ) return 1;
+	Asset *asset = edit->asset;
+	double timecode = asset->timecode != -2 ? asset->timecode :
+		FFMPEG::get_timecode(asset->path,
+			edit->track->data_type, edit->channel,
+			mwindow->edl->session->frame_rate);
+	asset->timecode = timecode;
+	if( timecode >= 0 ) {
+		int64_t pos = edit->startproject + edit->startsource;
+		double position = edit->track->from_units(pos);
+		mwindow->set_timecode_offset(timecode - position);
+	}
+	else
+		mwindow->set_timecode_offset(0);
+	return 1;
+}
 
diff --git a/cinelerra-5.1/cinelerra/editpopup.h b/cinelerra-5.1/cinelerra/editpopup.h
index 4c19b717..2c34be62 100644
--- a/cinelerra-5.1/cinelerra/editpopup.h
+++ b/cinelerra-5.1/cinelerra/editpopup.h
@@ -181,4 +181,13 @@ public:
 	EditPopup *popup;
 };
 
+class EditPopupTimecode : public BC_MenuItem
+{
+public:
+	EditPopupTimecode(MWindow *mwindow, EditPopup *popup);
+	int handle_event();
+	MWindow *mwindow;
+	EditPopup *popup;
+};
+
 #endif
diff --git a/cinelerra-5.1/cinelerra/editpopup.inc b/cinelerra-5.1/cinelerra/editpopup.inc
index 142afb96..6620ce3c 100644
--- a/cinelerra-5.1/cinelerra/editpopup.inc
+++ b/cinelerra-5.1/cinelerra/editpopup.inc
@@ -36,5 +36,6 @@ class EditPopupOverwrite;
 class EditPopupOverwritePlugins;
 class EditCollectEffects;
 class EditPasteEffects;
+class EditPopupTimecode;
 
 #endif
diff --git a/cinelerra-5.1/cinelerra/edits.C b/cinelerra-5.1/cinelerra/edits.C
index de93e583..b2bcaf98 100644
--- a/cinelerra-5.1/cinelerra/edits.C
+++ b/cinelerra-5.1/cinelerra/edits.C
@@ -31,6 +31,7 @@
 #include "edits.h"
 #include "edl.h"
 #include "edlsession.h"
+#include "ffmpeg.h"
 #include "file.h"
 #include "filexml.h"
 #include "filesystem.h"
@@ -838,3 +839,58 @@ void Edits::shift_effects_recursive(int64_t position, int64_t length, int edit_a
 	track->shift_effects(position, length, edit_autos, 0);
 }
 
+double Edits::early_timecode()
+{
+	double result = -1;
+	for( Edit *edit=first; edit; edit=edit->next ) {
+		Asset *asset = edit->asset;
+		if( !asset ) continue;
+		if( asset->timecode < -1 )
+			asset->timecode = FFMPEG::get_timecode(asset->path,
+				track->data_type, edit->channel,
+				edl->session->frame_rate);
+		if( asset->timecode < 0 ) continue;
+		if( result < 0 ||  result > asset->timecode )
+			result = asset->timecode;
+	}
+	return result;
+}
+
+void Edits::align_timecodes(double offset)
+{
+	for( Edit *edit=first, *next=0; edit; edit=next ) {
+		next = edit->next;
+		if( edit->silence() ) delete edit;
+	}
+	for( Edit *edit=first, *next=0; edit; edit=next ) {
+		next = edit->next;
+		Asset *asset = edit->asset;
+		if( !asset && asset->timecode < 0 ) continue;
+		double position = asset->timecode - offset;
+		edit->startproject = track->to_units(position, 1) + edit->startsource;
+	}
+	int result = 1;
+	while( result ) {
+		result = 0;
+		for( Edit *edit=first, *next=0; edit; edit=next ) {
+			next = edit->next;
+			if( !next || next->startproject >= edit->startproject ) continue;
+			swap(next, edit);
+			next = edit;
+			result = 1;
+		}
+	}
+	int64_t startproject = 0;
+	for( Edit *edit=first; edit; edit=edit->next ) {
+		int64_t length = edit->startproject - startproject;
+		if( length > 0 ) {
+			Edit *new_edit = create_edit();
+			insert_before(edit, new_edit);
+			new_edit->startproject = startproject;
+			new_edit->length = length;
+			startproject = edit->startproject;
+		}
+		startproject += edit->length;
+	}
+}
+
diff --git a/cinelerra-5.1/cinelerra/edits.h b/cinelerra-5.1/cinelerra/edits.h
index 76c0171d..f38b0767 100644
--- a/cinelerra-5.1/cinelerra/edits.h
+++ b/cinelerra-5.1/cinelerra/edits.h
@@ -84,6 +84,8 @@ public:
 	void paste_silence(int64_t start, int64_t end);
 // Returns the newly created edit
 	Edit *create_silence(int64_t start, int64_t end);
+	double early_timecode();
+	void align_timecodes(double offset);
 
 	void resample(double old_rate, double new_rate);
 // Shift edits on or after position by distance
diff --git a/cinelerra-5.1/cinelerra/edlsession.C b/cinelerra-5.1/cinelerra/edlsession.C
index 74eb3471..673ec070 100644
--- a/cinelerra-5.1/cinelerra/edlsession.C
+++ b/cinelerra-5.1/cinelerra/edlsession.C
@@ -134,6 +134,7 @@ EDLSession::EDLSession(EDL *edl)
 	si_duration = 3;
 	test_playback_edits = 1;
 	time_format = TIME_HMSF;
+	timecode_offset = 0;
 	nudge_format = 1;
 	tool_window = 0;
 	for(int i = 0; i < MAXCHANNELS; i++) {
@@ -328,6 +329,7 @@ int EDLSession::load_defaults(BC_Hash *defaults)
 	gang_tracks = defaults->get("GANG_TRACKS", GANG_NONE);
 //	test_playback_edits = defaults->get("TEST_PLAYBACK_EDITS", 1);
 	time_format = defaults->get("TIME_FORMAT", TIME_HMSF);
+	timecode_offset = defaults->get("TIMECODE_OFFSET", timecode_offset);
 	nudge_format = defaults->get("NUDGE_FORMAT", 1);
 	tool_window = defaults->get("TOOL_WINDOW", 0);
 	vconfig_in->load_defaults(defaults);
@@ -467,6 +469,7 @@ int EDLSession::save_defaults(BC_Hash *defaults)
 	defaults->update("GANG_TRACKS", gang_tracks);
 //	defaults->update("TEST_PLAYBACK_EDITS", test_playback_edits);
 	defaults->update("TIME_FORMAT", time_format);
+	defaults->update("TIMECODE_OFFSET", timecode_offset);
 	defaults->update("NUDGE_FORMAT", nudge_format);
 	defaults->update("TOOL_WINDOW", tool_window);
 	vconfig_in->save_defaults(defaults);
@@ -652,6 +655,7 @@ int EDLSession::load_xml(FileXML *file,
 		gang_tracks = file->tag.get_property("GANG_TRACKS", GANG_NONE);
 //		test_playback_edits = file->tag.get_property("TEST_PLAYBACK_EDITS", test_playback_edits);
 		time_format = file->tag.get_property("TIME_FORMAT", time_format);
+		timecode_offset = file->tag.get_property("TIMECODE_OFFSET", timecode_offset);
 		nudge_format = file->tag.get_property("NUDGE_FORMAT", nudge_format);
 		tool_window = file->tag.get_property("TOOL_WINDOW", tool_window);
 		vwindow_meter = file->tag.get_property("VWINDOW_METER", vwindow_meter);
@@ -722,6 +726,7 @@ int EDLSession::save_xml(FileXML *file)
 	file->tag.set_property("GANG_TRACKS", gang_tracks);
 	file->tag.set_property("TEST_PLAYBACK_EDITS", test_playback_edits);
 	file->tag.set_property("TIME_FORMAT", time_format);
+	file->tag.set_property("TIMECODE_OFFSET", timecode_offset);
 	file->tag.set_property("NUDGE_FORMAT", nudge_format);
 	file->tag.set_property("TOOL_WINDOW", tool_window);
 	file->tag.set_property("VWINDOW_METER", vwindow_meter);
@@ -899,6 +904,7 @@ int EDLSession::copy(EDLSession *session)
 	gang_tracks = session->gang_tracks;
 	test_playback_edits = session->test_playback_edits;
 	time_format = session->time_format;
+	timecode_offset = session->timecode_offset;
 	nudge_format = session->nudge_format;
 	tool_window = session->tool_window;
 	for(int i = 0; i < MAXCHANNELS; i++) {
diff --git a/cinelerra-5.1/cinelerra/edlsession.h b/cinelerra-5.1/cinelerra/edlsession.h
index b2994f18..eebe71f2 100644
--- a/cinelerra-5.1/cinelerra/edlsession.h
+++ b/cinelerra-5.1/cinelerra/edlsession.h
@@ -208,8 +208,8 @@ public:
 	int test_playback_edits;
 // Format to display times in
 	int time_format;
-// Offset for timecode
-	int timecode_offset[4];
+// Offset for timecode units
+	double timecode_offset;
 // Format to display nudge in, either seconds or track units.
 	int nudge_format;
 // Show tool window in CWindow
diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C
index 5ff87abc..ba0e0a34 100644
--- a/cinelerra-5.1/cinelerra/ffmpeg.C
+++ b/cinelerra-5.1/cinelerra/ffmpeg.C
@@ -1051,6 +1051,7 @@ FFVideoStream::FFVideoStream(FFMPEG *ffmpeg, AVStream *strm, int idx, int fidx)
 {
 	this->idx = idx;
 	width = height = 0;
+	transpose = 0;
 	frame_rate = 0;
 	aspect_ratio = 0;
 	length = 0;
@@ -1659,6 +1660,44 @@ IndexMarks *FFVideoStream::get_markers()
 	return !index_state ? 0 : index_state->video_markers[idx];
 }
 
+double FFVideoStream::get_rotation_angle()
+{
+	int size = 0;
+	int *matrix = (int*)av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, &size);
+	int len = size/sizeof(*matrix);
+	if( !matrix || len < 5 ) return 0;
+	const double s = 1/65536.;
+	double theta = (!matrix[0] && !matrix[3]) || (!matrix[1] && !matrix[4]) ? 0 :
+		 atan2( s*matrix[1] / hypot(s*matrix[1], s*matrix[4]),
+			s*matrix[0] / hypot(s*matrix[0], s*matrix[3])) * 180/M_PI;
+	return theta;
+}
+
+void FFVideoStream::flip()
+{
+	transpose = 0;
+	if( !ffmpeg->file_base ) return;
+	double theta = get_rotation_angle(), tolerance = 1;
+	if( fabs(theta-0) < tolerance ) return;
+        if( fabs(theta-90) < tolerance ) {
+		create_filter("transpose=clock", st->codecpar);
+		transpose = 1;
+        }
+	else if( fabs(theta-180) < tolerance ) {
+		create_filter("hflip", st->codecpar);
+		create_filter("vflip", st->codecpar);
+        }
+	else if (fabs(theta-270) < tolerance ) {
+		create_filter("transpose=cclock", st->codecpar);
+		transpose = 1;
+        }
+	else {
+		char rotate[BCSTRLEN];
+		sprintf(rotate, "rotate=%f", theta*M_PI/180.);
+		create_filter(rotate, st->codecpar);
+        }
+}
+
 
 FFMPEG::FFMPEG(FileBase *file_base)
 {
@@ -1722,9 +1761,8 @@ static inline AVRational std_frame_rate(int i)
 	return (AVRational) { freq, 1001*12 };
 }
 
-AVRational FFMPEG::check_frame_rate(AVCodec *codec, double frame_rate)
+AVRational FFMPEG::check_frame_rate(const AVRational *p, double frame_rate)
 {
-	const AVRational *p = codec->supported_framerates;
 	AVRational rate, best_rate = (AVRational) { 0, 0 };
 	double max_err = 1.;  int i = 0;
 	while( ((p ? (rate=*p++) : (rate=std_frame_rate(i++))), rate.num) != 0 ) {
@@ -2307,6 +2345,9 @@ int FFMPEG::info(char *text, int len)
 		int hrs = secs/3600;  secs -= hrs*3600;
 		int mins = secs/60;  secs -= mins*60;
 		report("  %d:%02d:%05.2f\n", hrs, mins, secs);
+		double theta = vid->get_rotation_angle();
+		if( fabs(theta) > 1 ) 
+			report("    rotation angle: %0.1f\n", theta);
 	}
 	if( ffaudio.size() > 0 )
 		report("\n%d audio stream%s\n",ffaudio.size(), ffaudio.size()!=1 ? "s" : "");
@@ -2494,6 +2535,8 @@ int FFMPEG::open_decoder()
 			vid->reading = -1;
 			if( opt_video_filter )
 				ret = vid->create_filter(opt_video_filter, avpar);
+			if( file_base && file_base->file->preferences->auto_rotate )
+				vid->flip();
 			break; }
 		case AVMEDIA_TYPE_AUDIO: {
 			if( avpar->channels < 1 ) continue;
@@ -2753,7 +2796,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
 			int mask_h = (1<<desc->log2_chroma_h)-1;
 			ctx->height = (vid->height+mask_h) & ~mask_h;
 			ctx->sample_aspect_ratio = to_sample_aspect_ratio(asset);
-			AVRational frame_rate = check_frame_rate(codec, vid->frame_rate);
+			AVRational frame_rate = check_frame_rate(codec->supported_framerates, vid->frame_rate);
 			if( !frame_rate.num || !frame_rate.den ) {
 				eprintf(_("check_frame_rate failed %s\n"), filename);
 				ret = 1;
@@ -3310,25 +3353,29 @@ int FFMPEG::ff_total_vstreams()
 
 int FFMPEG::ff_video_width(int stream)
 {
-	return ffvideo[stream]->width;
+	FFVideoStream *vst = ffvideo[stream];
+	return !vst->transpose ? vst->width : vst->height;
 }
 
 int FFMPEG::ff_video_height(int stream)
 {
-	return ffvideo[stream]->height;
+	FFVideoStream *vst = ffvideo[stream];
+	return !vst->transpose ? vst->height : vst->width;
 }
 
 int FFMPEG::ff_set_video_width(int stream, int width)
 {
-	int w = ffvideo[stream]->width;
-	ffvideo[stream]->width = width;
+	FFVideoStream *vst = ffvideo[stream];
+	int *vw = !vst->transpose ? &vst->width : &vst->height, w = *vw;
+	*vw = width;
 	return w;
 }
 
 int FFMPEG::ff_set_video_height(int stream, int height)
 {
-	int h = ffvideo[stream]->height;
-	ffvideo[stream]->height = height;
+	FFVideoStream *vst = ffvideo[stream];
+	int *vh = !vst->transpose ? &vst->height : &vst->width, h = *vh;
+	*vh = height;
 	return h;
 }
 
@@ -3387,7 +3434,7 @@ int FFMPEG::ff_video_mpeg_color_range(int stream)
 
 int FFMPEG::ff_cpus()
 {
-	return file_base->file->cpus;
+	return !file_base ? 1 : file_base->file->cpus;
 }
 
 const char *FFMPEG::ff_hw_dev()
@@ -3416,14 +3463,17 @@ int FFVideoStream::create_filter(const char *filter_spec, AVCodecParameters *avp
 	filter_graph = avfilter_graph_alloc();
 	const AVFilter *buffersrc = avfilter_get_by_name("buffer");
 	const AVFilter *buffersink = avfilter_get_by_name("buffersink");
+	int sa_num = avpar->sample_aspect_ratio.num;
+	if( !sa_num ) sa_num = 1;
+	int sa_den = avpar->sample_aspect_ratio.den;
+	if( !sa_den ) sa_num = 1;
 
 	int ret = 0;  char args[BCTEXTLEN];
 	AVPixelFormat pix_fmt = (AVPixelFormat)avpar->format;
 	snprintf(args, sizeof(args),
 		"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
 		avpar->width, avpar->height, (int)pix_fmt,
-		st->time_base.num, st->time_base.den,
-		avpar->sample_aspect_ratio.num, avpar->sample_aspect_ratio.den);
+		st->time_base.num, st->time_base.den, sa_num, sa_den);
 	if( ret >= 0 )
 		ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
 			args, NULL, filter_graph);
@@ -3520,6 +3570,50 @@ int FFStream::create_filter(const char *filter_spec)
 	return ret;
 }
 
+
+AVCodecContext *FFMPEG::activate_decoder(AVStream *st)
+{
+	AVDictionary *copts = 0;
+	av_dict_copy(&copts, opts, 0);
+	AVCodecID codec_id = st->codecpar->codec_id;
+	AVCodec *decoder = 0;
+	switch( st->codecpar->codec_type ) {
+	case AVMEDIA_TYPE_VIDEO:
+		if( opt_video_decoder )
+			decoder = avcodec_find_decoder_by_name(opt_video_decoder);
+		else
+			video_codec_remaps.update(codec_id, decoder);
+		break;
+	case AVMEDIA_TYPE_AUDIO:
+		if( opt_audio_decoder )
+			decoder = avcodec_find_decoder_by_name(opt_audio_decoder);
+		else
+			audio_codec_remaps.update(codec_id, decoder);
+		break;
+	default:
+		return 0;
+	}
+	if( !decoder && !(decoder = avcodec_find_decoder(codec_id)) ) {
+		eprintf(_("cant find decoder codec %d\n"), (int)codec_id);
+		return 0;
+	}
+	AVCodecContext *avctx = avcodec_alloc_context3(decoder);
+	if( !avctx ) {
+		eprintf(_("cant allocate codec context\n"));
+		return 0;
+	}
+	avcodec_parameters_to_context(avctx, st->codecpar);
+	if( !av_dict_get(copts, "threads", NULL, 0) )
+		avctx->thread_count = ff_cpus();
+	int ret = avcodec_open2(avctx, decoder, &copts);
+	av_dict_free(&copts);
+	if( ret < 0 ) {
+		avcodec_free_context(&avctx);
+		avctx = 0;
+	}
+	return avctx;
+}
+
 int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled)
 {
 	AVPacket pkt;
@@ -3536,43 +3630,9 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled)
 	index_state->add_audio_markers(ffaudio.size());
 
 	for( int i=0; i<(int)fmt_ctx->nb_streams; ++i ) {
-		int ret = 0;
-		AVDictionary *copts = 0;
-		av_dict_copy(&copts, opts, 0);
 		AVStream *st = fmt_ctx->streams[i];
-		AVCodecID codec_id = st->codecpar->codec_id;
-		AVCodec *decoder = 0;
-		switch( st->codecpar->codec_type ) {
-		case AVMEDIA_TYPE_VIDEO:
-			if( opt_video_decoder )
-				decoder = avcodec_find_decoder_by_name(opt_video_decoder);
-			else
-				video_codec_remaps.update(codec_id, decoder);
-			break;
-		case AVMEDIA_TYPE_AUDIO:
-			if( opt_audio_decoder )
-				decoder = avcodec_find_decoder_by_name(opt_audio_decoder);
-			else
-				audio_codec_remaps.update(codec_id, decoder);
-			break;
-		default:
-			continue;
-		}
-		if( !decoder && !(decoder = avcodec_find_decoder(codec_id)) )
-			continue;
-		AVCodecContext *avctx = avcodec_alloc_context3(decoder);
-		if( !avctx ) {
-			eprintf(_("cant allocate codec context\n"));
-			ret = AVERROR(ENOMEM);
-		}
-		if( ret >= 0 ) {
-			avcodec_parameters_to_context(avctx, st->codecpar);
-			if( !av_dict_get(copts, "threads", NULL, 0) )
-				avctx->thread_count = ff_cpus();
-			ret = avcodec_open2(avctx, decoder, &copts);
-		}
-		av_dict_free(&copts);
-		if( ret >= 0 ) {
+		AVCodecContext *avctx = activate_decoder(st);
+		if( avctx ) {
 			AVCodecParameters *avpar = st->codecpar;
 			switch( avpar->codec_type ) {
 			case AVMEDIA_TYPE_VIDEO: {
@@ -3731,3 +3791,246 @@ void FFStream::load_markers(IndexMarks &marks, double rate)
 	}
 }
 
+
+/*
+ * 1) if the format context has a timecode
+ *   return fmt_ctx->timecode - 0
+ * 2) if the layer/channel has a timecode
+ *   return st->timecode - (start_time-nudge)
+ * 3) find the 1st program with stream, find 1st program video stream,
+ *   if video stream has a timecode, return st->timecode - (start_time-nudge)
+ * 4) find timecode in any stream, return st->timecode
+ * 5) read 100 packets, save ofs=pkt.pts*st->time_base - st->nudge:
+ *   decode frame for video stream of 1st program
+ *   if frame->timecode has a timecode, return frame->timecode - ofs
+ *   if side_data has gop timecode, return gop->timecode - ofs
+ *   if side_data has smpte timecode, return smpte->timecode - ofs
+ * 6) if the filename/url scans *date_time.ext, return date_time
+ * 7) if stat works on the filename/url, return mtime
+ * 8) return -1 failure
+*/
+double FFMPEG::get_initial_timecode(int data_type, int channel, double frame_rate)
+{
+	AVRational rate = check_frame_rate(0, frame_rate);
+	if( !rate.num ) return -1;
+// format context timecode
+	AVDictionaryEntry *tc = av_dict_get(fmt_ctx->metadata, "timecode", 0, 0);
+	if( tc ) return ff_get_timecode(tc->value, rate, 0);
+// stream timecode
+	if( open_decoder() ) return -1;
+	AVStream *st = 0;
+	int64_t nudge = 0;
+	int codec_type = -1, fidx = -1;
+	switch( data_type ) {
+	case TRACK_AUDIO: {
+		codec_type = AVMEDIA_TYPE_AUDIO;
+		int aidx = astrm_index[channel].st_idx;
+		FFAudioStream *aud = ffaudio[aidx];
+		fidx = aud->fidx;
+		nudge = aud->nudge;
+		st = aud->st;
+		break; }
+	case TRACK_VIDEO: {
+		codec_type = AVMEDIA_TYPE_VIDEO;
+		int vidx = vstrm_index[channel].st_idx;
+		FFVideoStream *vid = ffvideo[vidx];
+		fidx = vid->fidx;
+		nudge = vid->nudge;
+		st = vid->st;
+		break; }
+	}
+	if( codec_type < 0 ) return -1;
+	if( st )
+		tc = av_dict_get(st->metadata, "timecode", 0, 0);
+	if( !tc ) {
+		st = 0;
+// find first program which references this stream
+		int pidx = -1;
+		for( int i=0, m=fmt_ctx->nb_programs; pidx<0 && i<m; ++i ) {
+			AVProgram *pgrm = fmt_ctx->programs[i];
+			for( int j=0, n=pgrm->nb_stream_indexes; j<n; ++j ) {
+				int st_idx = pgrm->stream_index[j];
+				if( st_idx == fidx ) { pidx = i;  break; }
+			}
+		}
+		fidx = -1;
+		if( pidx >= 0 ) {
+			AVProgram *pgrm = fmt_ctx->programs[pidx];
+			for( int j=0, n=pgrm->nb_stream_indexes; j<n; ++j ) {
+				int st_idx = pgrm->stream_index[j];
+				AVStream *tst = fmt_ctx->streams[st_idx];
+				if( !tst ) continue;
+				if( tst->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ) {
+					st = tst;  fidx = st_idx;
+					break;
+				}
+			}
+		}
+		else {
+			for( int i=0, n=fmt_ctx->nb_streams; i<n; ++i ) {
+				AVStream *tst = fmt_ctx->streams[i];
+				if( !tst ) continue;
+				if( tst->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ) {
+					st = tst;  fidx = i;
+					break;
+				}
+			}
+		}
+		if( st )
+			tc = av_dict_get(st->metadata, "timecode", 0, 0);
+	}
+
+	if( !tc ) {
+		// any timecode, includes -data- streams
+		for( int i=0, n=fmt_ctx->nb_streams; i<n; ++i ) {
+			AVStream *tst = fmt_ctx->streams[i];
+			if( !tst ) continue;
+			if( (tc = av_dict_get(tst->metadata, "timecode", 0, 0)) ) {
+				st = tst;  fidx = i;
+				break;
+			}
+		}
+	}
+
+	if( st && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ) {
+		if( st->r_frame_rate.num && st->r_frame_rate.den )
+			rate = st->r_frame_rate;
+		nudge = st->start_time;
+		for( int i=0; i<ffvideo.size(); ++i ) {
+			if( ffvideo[i]->st == st ) {
+				nudge = ffvideo[i]->nudge;
+				break;
+			}
+		}
+	}
+
+	if( tc ) { // return timecode
+		double secs = st->start_time == AV_NOPTS_VALUE ? 0 :
+			to_secs(st->start_time - nudge, st->time_base);
+		return ff_get_timecode(tc->value, rate, secs);
+	}
+	
+	if( !st || fidx < 0 ) return -1;
+
+	decode_activate();
+	AVCodecContext *av_ctx = activate_decoder(st);
+	if( !av_ctx ) {
+		fprintf(stderr,"activate_decoder failed\n");
+		return -1;
+	}
+	avCodecContext avctx(av_ctx); // auto deletes
+	if( avctx->codec_type == AVMEDIA_TYPE_VIDEO &&
+	    avctx->framerate.num && avctx->framerate.den )
+		rate = avctx->framerate;
+
+	avPacket pkt;	// auto deletes
+	avFrame frame;  // auto deletes
+	if( !frame ) {
+		fprintf(stderr,"av_frame_alloc failed\n");
+		return -1;
+	}
+	int errs = 0;
+	int64_t max_packets = 100;
+	char tcbuf[AV_TIMECODE_STR_SIZE];
+
+	for( int64_t count=0; count<max_packets; ++count ) {
+		av_packet_unref(pkt);
+		pkt->data = 0; pkt->size = 0;
+
+		int ret = av_read_frame(fmt_ctx, pkt);
+		if( ret < 0 ) {
+			if( ret == AVERROR_EOF ) break;
+			if( ++errs > 100 ) {
+				fprintf(stderr,"over 100 read_frame errs\n");
+				break;
+			}
+			continue;
+		}
+		if( !pkt->data ) continue;
+		int i = pkt->stream_index;
+		if( i != fidx ) continue;
+		int64_t tstmp = pkt->pts;
+		if( tstmp == AV_NOPTS_VALUE ) tstmp = pkt->dts;
+		double secs = to_secs(tstmp - nudge, st->time_base);
+		ret = avcodec_send_packet(avctx, pkt);
+		if( ret < 0 ) return -1;
+
+		while( (ret = avcodec_receive_frame(avctx, frame)) >= 0 ) {
+			if( (tc = av_dict_get(frame->metadata, "timecode", 0, 0)) )
+				return ff_get_timecode(tc->value, rate, secs);
+			int k = frame->nb_side_data;
+			AVFrameSideData *side_data = 0;
+			while( --k >= 0 ) {
+				side_data = frame->side_data[k];
+				switch( side_data->type ) {
+				case AV_FRAME_DATA_GOP_TIMECODE: {
+					int64_t data = *(int64_t *)side_data->data;
+					int sz = sizeof(data);
+					if( side_data->size >= sz ) {
+						av_timecode_make_mpeg_tc_string(tcbuf, data);
+						return ff_get_timecode(tcbuf, rate, secs);
+					}
+					break; }
+				case AV_FRAME_DATA_S12M_TIMECODE: {
+					uint32_t *data = (uint32_t *)side_data->data;
+					int n = data[0], sz = (n+1)*sizeof(*data);
+					if( side_data->size >= sz ) {
+						av_timecode_make_smpte_tc_string(tcbuf, data[n], 0);
+						return ff_get_timecode(tcbuf, rate, secs);
+					}
+					break; }
+				default:
+					break;
+				}
+			}
+		}
+	}
+	char *path = fmt_ctx->url;
+	char *bp = strrchr(path, '/');
+	if( !bp ) bp = path; else ++bp;
+	char *cp = strrchr(bp, '.');
+	if( cp && (cp-=(8+1+6)) >= bp ) {
+		char sep[BCSTRLEN];
+		int year,mon,day, hour,min,sec, frm=0;
+		if( sscanf(cp,"%4d%2d%2d%[_-]%2d%2d%2d",
+				&year,&mon,&day, sep, &hour,&min,&sec) == 7 ) {
+			int ch = sep[0];
+			// year>=1970,mon=1..12,day=1..31, hour=0..23,min=0..59,sec=0..60
+			if( (ch=='_' || ch=='-' ) &&
+			    year >= 1970 && mon>=1 && mon<=12 && day>=1 && day<=31 &&
+			    hour>=0 && hour<24 && min>=0 && min<60 && sec>=0 && sec<=60 ) {
+				sprintf(tcbuf,"%d:%02d:%02d:%02d", hour,min,sec, frm);
+				return ff_get_timecode(tcbuf, rate, 0);
+			}
+		}
+	}
+	struct stat tst;
+	if( stat(path, &tst) >= 0 ) {
+		time_t t = (time_t)tst.st_mtim.tv_sec;
+		struct tm tm;
+		localtime_r(&t, &tm);
+		int64_t us = tst.st_mtim.tv_nsec / 1000;
+		int frm = us/1000000. * frame_rate;
+		sprintf(tcbuf,"%d:%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec, frm);
+		return ff_get_timecode(tcbuf, rate, 0);
+	}
+	return -1;
+}
+
+double FFMPEG::ff_get_timecode(char *str, AVRational rate, double pos)
+{
+	AVTimecode tc;
+	if( av_timecode_init_from_string(&tc, rate, str, fmt_ctx) )
+		return -1;
+	double secs = (double)tc.start / tc.fps - pos;
+	if( secs < 0 ) secs = 0;
+	return secs;
+}
+
+double FFMPEG::get_timecode(const char *path, int data_type, int channel, double rate)
+{
+	FFMPEG ffmpeg(0);
+	if( ffmpeg.init_decoder(path) ) return -1;
+	return ffmpeg.get_initial_timecode(data_type, channel, rate);
+}
+
diff --git a/cinelerra-5.1/cinelerra/ffmpeg.h b/cinelerra-5.1/cinelerra/ffmpeg.h
index 56ce4e5b..18516d36 100644
--- a/cinelerra-5.1/cinelerra/ffmpeg.h
+++ b/cinelerra-5.1/cinelerra/ffmpeg.h
@@ -37,6 +37,8 @@ extern "C" {
 #include "libavutil/pixdesc.h"
 #include "libswresample/swresample.h"
 #include "libswscale/swscale.h"
+#include "libavutil/parseutils.h"
+#include "libavutil/timecode.h"
 }
 
 class FFPacket  {
@@ -254,10 +256,12 @@ public:
 	int video_seek(int64_t pos);
 	int encode(VFrame *vframe);
 	int drain();
+	double get_rotation_angle();
+	void flip();
 
 	int idx;
 	double frame_rate;
-	int width, height;
+	int width, height, transpose;
 	int64_t length;
 	float aspect_ratio;
 
@@ -282,6 +286,38 @@ public:
 	int update(AVCodecID &codec_id, AVCodec *&decoder);
 };
 
+// for get_initial_timecode auto deletes
+class avFrame {
+	AVFrame *frm;
+public:
+	avFrame() { frm = av_frame_alloc(); }
+	~avFrame() { av_frame_free(&frm); }
+	operator AVFrame *() { return frm; }
+	AVFrame *operator ->() { return frm; }
+};
+
+class avPacket {
+	AVPacket pkt;
+public:
+	avPacket() {
+		av_init_packet(&pkt);
+		pkt.data = 0; pkt.size = 0;
+	}
+	~avPacket() { av_packet_unref(&pkt); }
+	operator AVPacket *() { return &pkt; }
+	AVPacket *operator ->() { return &pkt; }
+};
+
+class avCodecContext {
+	AVCodecContext *avctx;
+public:
+	avCodecContext(AVCodecContext *ctx) { avctx = ctx; }
+	~avCodecContext() { avcodec_free_context(&avctx); }
+	operator AVCodecContext *() { return avctx; }
+	AVCodecContext *operator ->() { return avctx; }
+};
+
+
 class FFMPEG : public Thread {
 public:
 	static Mutex fflock;
@@ -289,7 +325,7 @@ public:
 	static void ff_unlock() { fflock.unlock(); }
 
 	int check_sample_rate(AVCodec *codec, int sample_rate);
-	AVRational check_frame_rate(AVCodec *codec, double frame_rate);
+	AVRational check_frame_rate(const AVRational *p, double frame_rate);
 	AVRational to_sample_aspect_ratio(Asset *asset);
 	AVRational to_time_base(int sample_rate);
 	static int get_fmt_score(AVSampleFormat dst_fmt, AVSampleFormat src_fmt);
@@ -334,6 +370,7 @@ public:
 
 	int total_audio_channels();
 	int total_video_channels();
+	double get_initial_timecode(int data_type, int channel, double frame_rate);
 
 	int audio_seek(int ch, int64_t pos);
 	int video_seek(int layer, int64_t pos);
@@ -390,6 +427,7 @@ public:
 
 	FFMPEG(FileBase *file_base=0);
 	~FFMPEG();
+	AVCodecContext *activate_decoder(AVStream *st);
 	int scan(IndexState *index_state, int64_t *scan_position, int *canceled);
 
 	int ff_audio_stream(int channel) { return astrm_index[channel].st_idx; }
@@ -420,6 +458,8 @@ public:
 	int64_t ff_video_frames(int stream);
 	int ff_video_pid(int stream);
 	int ff_video_mpeg_color_range(int stream);
+	double ff_get_timecode(char *str, AVRational rate, double pos);
+	static double get_timecode(const char *path, int data_type, int channel, double rate);
 
 	int ff_cpus();
 	const char *ff_hw_dev();
diff --git a/cinelerra-5.1/cinelerra/mainclock.C b/cinelerra-5.1/cinelerra/mainclock.C
index ddee51a2..06e23d2b 100644
--- a/cinelerra-5.1/cinelerra/mainclock.C
+++ b/cinelerra-5.1/cinelerra/mainclock.C
@@ -49,11 +49,15 @@ void MainClock::update(double position)
 	lock_window("MainClock::update");
 	char string[BCTEXTLEN];
 	position += position_offset;
+	double timecode_offset =
+		mwindow->edl->session->time_format == TIME_TIMECODE ?
+			mwindow->get_timecode_offset() : 0 ;
 	Units::totext(string, position,
 		mwindow->edl->session->time_format,
 		mwindow->edl->session->sample_rate,
 		mwindow->edl->session->frame_rate,
-		mwindow->edl->session->frames_per_foot);
+		mwindow->edl->session->frames_per_foot,
+		timecode_offset);
 	BC_Title::update(string);
 	unlock_window();
 }
diff --git a/cinelerra-5.1/cinelerra/mainmenu.C b/cinelerra-5.1/cinelerra/mainmenu.C
index 64e90885..061dd8c1 100644
--- a/cinelerra-5.1/cinelerra/mainmenu.C
+++ b/cinelerra-5.1/cinelerra/mainmenu.C
@@ -282,6 +282,7 @@ void MainMenu::create_objects()
 	windowmenu->add_item(split_x = new SplitX(mwindow));
 	windowmenu->add_item(split_y = new SplitY(mwindow));
 	windowmenu->add_item(mixer_items = new MixerItems(mwindow));
+	windowmenu->add_item(align_timecodes = new AlignTimecodes(mwindow));
 	mixer_items->create_objects();
 	windowmenu->add_item(new TileWindows(mwindow,_("Tile left"),0));
 	windowmenu->add_item(new TileWindows(mwindow,_("Tile right"),1));
@@ -1769,6 +1770,19 @@ int AlignMixers::handle_event()
 }
 
 
+AlignTimecodes::AlignTimecodes(MWindow *mwindow)
+ : BC_MenuItem(_("Align Timecodes"))
+{
+	this->mwindow = mwindow;
+}
+
+int AlignTimecodes::handle_event()
+{
+	mwindow->align_timecodes();
+	return 1;
+}
+
+
 LoadLayoutItem::LoadLayoutItem(LoadLayout *load_layout, const char *text, int idx, int hotkey)
  : BC_MenuItem(text, "", hotkey)
 {
diff --git a/cinelerra-5.1/cinelerra/mainmenu.h b/cinelerra-5.1/cinelerra/mainmenu.h
index bf14888f..f0c493b2 100644
--- a/cinelerra-5.1/cinelerra/mainmenu.h
+++ b/cinelerra-5.1/cinelerra/mainmenu.h
@@ -172,6 +172,7 @@ public:
 	SplitX *split_x;
 	SplitY *split_y;
 	MixerItems *mixer_items;
+	AlignTimecodes *align_timecodes;
 	LoadLayout *load_layout;
 	LoadLayout *save_layout;
 };
@@ -538,6 +539,14 @@ public:
 	int handle_event();
 };
 
+class AlignTimecodes : public BC_MenuItem
+{
+public:
+	AlignTimecodes(MWindow *mwindow);
+	int handle_event();
+	MWindow *mwindow;
+};
+
 // ======================================== audio
 
 class AddAudioTrack : public BC_MenuItem
diff --git a/cinelerra-5.1/cinelerra/mainmenu.inc b/cinelerra-5.1/cinelerra/mainmenu.inc
index dbe51384..426ab487 100644
--- a/cinelerra-5.1/cinelerra/mainmenu.inc
+++ b/cinelerra-5.1/cinelerra/mainmenu.inc
@@ -70,6 +70,7 @@ class MixerItems;
 class MixerViewer;
 class TileMixers;
 class AlignMixers;
+class AlignTimecodes;
 class AddAudioTrack;
 class DeleteAudioTrack;
 class DefaultATransition;
diff --git a/cinelerra-5.1/cinelerra/mbuttons.C b/cinelerra-5.1/cinelerra/mbuttons.C
index d40b726d..8c3b8a2d 100644
--- a/cinelerra-5.1/cinelerra/mbuttons.C
+++ b/cinelerra-5.1/cinelerra/mbuttons.C
@@ -144,7 +144,8 @@ MainEditing::MainEditing(MWindow *mwindow, MButtons *mbuttons, int x, int y)
 		1, // use_goto
 		0, // use_clk2play
 		0, // use_scope
-		1) // use_gang_tracks
+		1, // use_gang_tracks
+		1) // use_timecode
 {
 	this->mwindow = mwindow;
 	this->mbuttons = mbuttons;
diff --git a/cinelerra-5.1/cinelerra/menueffects.C b/cinelerra-5.1/cinelerra/menueffects.C
index 1dcbe8a7..b58d770c 100644
--- a/cinelerra-5.1/cinelerra/menueffects.C
+++ b/cinelerra-5.1/cinelerra/menueffects.C
@@ -360,7 +360,9 @@ void MenuEffectThread::run()
 		default_asset->height = mwindow->edl->session->output_h;
 	}
 
-	int strategy = Render::get_strategy(mwindow->preferences->use_renderfarm, use_labels);
+	int range = File::is_image_render(default_asset->format) ?
+		RANGE_1FRAME : RANGE_SELECTION;
+	int strategy = Render::get_strategy(mwindow->preferences->use_renderfarm, use_labels, range);
 // Process the total length in fragments
 	ArrayList<MenuEffectPacket*> packets;
 	if(!result)
diff --git a/cinelerra-5.1/cinelerra/mtimebar.C b/cinelerra-5.1/cinelerra/mtimebar.C
index 7eec4d34..60d71da1 100644
--- a/cinelerra-5.1/cinelerra/mtimebar.C
+++ b/cinelerra-5.1/cinelerra/mtimebar.C
@@ -308,6 +308,7 @@ void MTimeBar::draw_time()
 		}
 
 		case TIME_FRAMES:
+		case TIME_TIMECODE:
 		case TIME_HMSF:
 // One frame per text mark
 			if(frame_seconds >= min_time)
@@ -363,11 +364,14 @@ void MTimeBar::draw_time()
 
 // Set tick interval
 	tick_interval = text_interval;
+	double timecode_offset = 0;
 
 	switch(mwindow->edl->session->time_format)
 	{
-		case TIME_HMSF:
+		case TIME_TIMECODE:
+			timecode_offset = mwindow->get_timecode_offset(); // fall thru
 		case TIME_FEET_FRAMES:
+		case TIME_HMSF:
 		case TIME_FRAMES:
 			if(frame_seconds / time_per_pixel > TICK_SPACING)
 				tick_interval = frame_seconds;
@@ -395,7 +399,8 @@ void MTimeBar::draw_time()
 			mwindow->edl->session->time_format,
 			sample_rate,
 			mwindow->edl->session->frame_rate,
-			mwindow->edl->session->frames_per_foot);
+			mwindow->edl->session->frames_per_foot,
+			timecode_offset);
 	 	set_color(get_resources()->default_text_color);
 		set_font(MEDIUMFONT);
 
@@ -697,14 +702,16 @@ void TimeBarPopup::create_objects()
 	add_item(items[1] = new TimeBarPopupItem(mwindow,
 		this, TIME_HMSF_TEXT, TIME_HMSF));
 	add_item(items[2] = new TimeBarPopupItem(mwindow,
-		this, TIME_FRAMES_TEXT, TIME_FRAMES));
+		this, TIME_TIMECODE_TEXT, TIME_TIMECODE));
 	add_item(items[3] = new TimeBarPopupItem(mwindow,
-		this, TIME_SAMPLES_TEXT, TIME_SAMPLES));
+		this, TIME_FRAMES_TEXT, TIME_FRAMES));
 	add_item(items[4] = new TimeBarPopupItem(mwindow,
-		this, TIME_SAMPLES_HEX_TEXT, TIME_SAMPLES_HEX));
+		this, TIME_SAMPLES_TEXT, TIME_SAMPLES));
 	add_item(items[5] = new TimeBarPopupItem(mwindow,
-		this, TIME_SECONDS_TEXT, TIME_SECONDS));
+		this, TIME_SAMPLES_HEX_TEXT, TIME_SAMPLES_HEX));
 	add_item(items[6] = new TimeBarPopupItem(mwindow,
+		this, TIME_SECONDS_TEXT, TIME_SECONDS));
+	add_item(items[7] = new TimeBarPopupItem(mwindow,
 		this, TIME_FEET_FRAMES_TEXT, TIME_FEET_FRAMES));
 }
 
diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C
index 1466b445..7d0c140f 100644
--- a/cinelerra-5.1/cinelerra/mwindow.C
+++ b/cinelerra-5.1/cinelerra/mwindow.C
@@ -3731,6 +3731,7 @@ void MWindow::update_project(int load_mode)
 
 	if( load_mode == LOADMODE_REPLACE ||
 	    load_mode == LOADMODE_REPLACE_CONCATENATE ) {
+		edl->session->timecode_offset = 0;
 		delete gui->keyvalue_popup;
 		gui->keyvalue_popup = 0;
 		gui->load_panes();
@@ -3952,6 +3953,7 @@ int MWindow::save(int save_as)
 	for( int i=stack.size(); --i>=0;  ) {
 		StackItem &item = stack[i];
 		Indexable *idxbl = item.idxbl;
+		if( !idxbl ) continue;
 		if( idxbl->is_asset ) {
 			Asset *asset = (Asset *)idxbl;
 			if( asset->format == FILE_REF ) {
@@ -3959,8 +3961,8 @@ int MWindow::save(int save_as)
 					return 1;
 			}
 		}
-		else if( item.new_edl != item.idxbl )
-			item.new_edl->overwrite_clip((EDL*)item.idxbl);
+		else if( item.new_edl != idxbl )
+			item.new_edl->overwrite_clip((EDL*)idxbl);
 	}
 	EDL *new_edl = stack.size() ? stack[0].edl : edl;
 	save(new_edl, path, 1);
@@ -4779,31 +4781,30 @@ int MWindow::interrupt_indexes()
 
 void MWindow::next_time_format()
 {
-	switch(edl->session->time_format)
-	{
-		case TIME_HMS: edl->session->time_format = TIME_HMSF; break;
-		case TIME_HMSF: edl->session->time_format = TIME_SAMPLES; break;
-		case TIME_SAMPLES: edl->session->time_format = TIME_SAMPLES_HEX; break;
-		case TIME_SAMPLES_HEX: edl->session->time_format = TIME_FRAMES; break;
-		case TIME_FRAMES: edl->session->time_format = TIME_FEET_FRAMES; break;
-		case TIME_FEET_FRAMES: edl->session->time_format = TIME_SECONDS; break;
-		case TIME_SECONDS: edl->session->time_format = TIME_HMS; break;
+	switch( edl->session->time_format ) {
+	case TIME_HMS:          edl->session->time_format = TIME_HMSF;         break;
+	case TIME_HMSF:         edl->session->time_format = TIME_TIMECODE;     break;
+	case TIME_TIMECODE:     edl->session->time_format = TIME_FRAMES;       break;
+	case TIME_FRAMES:       edl->session->time_format = TIME_SAMPLES;      break;
+	case TIME_SAMPLES:      edl->session->time_format = TIME_SAMPLES_HEX;  break;
+	case TIME_SAMPLES_HEX:  edl->session->time_format = TIME_SECONDS;      break;
+	case TIME_SECONDS:      edl->session->time_format = TIME_FEET_FRAMES;  break;
+	case TIME_FEET_FRAMES:  edl->session->time_format = TIME_HMS;          break;
 	}
-
 	time_format_common();
 }
 
 void MWindow::prev_time_format()
 {
-	switch(edl->session->time_format)
-	{
-		case TIME_HMS: edl->session->time_format = TIME_SECONDS; break;
-		case TIME_SECONDS: edl->session->time_format = TIME_FEET_FRAMES; break;
-		case TIME_FEET_FRAMES: edl->session->time_format = TIME_FRAMES; break;
-		case TIME_FRAMES: edl->session->time_format = TIME_SAMPLES_HEX; break;
-		case TIME_SAMPLES_HEX: edl->session->time_format = TIME_SAMPLES; break;
-		case TIME_SAMPLES: edl->session->time_format = TIME_HMSF; break;
-		case TIME_HMSF: edl->session->time_format = TIME_HMS; break;
+	switch( edl->session->time_format ) {
+	case TIME_HMS:          edl->session->time_format = TIME_FEET_FRAMES;  break;
+	case TIME_HMSF:         edl->session->time_format = TIME_HMS;          break;
+	case TIME_TIMECODE:     edl->session->time_format = TIME_HMSF;         break;
+	case TIME_FRAMES:       edl->session->time_format = TIME_TIMECODE;     break;
+	case TIME_SAMPLES:      edl->session->time_format = TIME_FRAMES;       break;
+	case TIME_SAMPLES_HEX:  edl->session->time_format = TIME_SAMPLES;      break;
+	case TIME_SECONDS:      edl->session->time_format = TIME_SAMPLES_HEX;  break;
+	case TIME_FEET_FRAMES:  edl->session->time_format = TIME_SECONDS;      break;
 	}
 
 	time_format_common();
diff --git a/cinelerra-5.1/cinelerra/mwindow.h b/cinelerra-5.1/cinelerra/mwindow.h
index 8f80280f..cbe17277 100644
--- a/cinelerra-5.1/cinelerra/mwindow.h
+++ b/cinelerra-5.1/cinelerra/mwindow.h
@@ -332,6 +332,9 @@ public:
 	void toggle_projector_xyz();
 	double get_position();
 	void set_position(double position);
+	double get_timecode_offset();
+	void set_timecode_offset(double offset);
+	void align_timecodes();
 
 // seek to labels
 // shift_down must be passed by the caller because different windows call
diff --git a/cinelerra-5.1/cinelerra/mwindowedit.C b/cinelerra-5.1/cinelerra/mwindowedit.C
index 6242b788..26aa4cb2 100644
--- a/cinelerra-5.1/cinelerra/mwindowedit.C
+++ b/cinelerra-5.1/cinelerra/mwindowedit.C
@@ -2710,3 +2710,15 @@ void MWindow::paste_effects()
 	group->remove_user();
 }
 
+void MWindow::align_timecodes()
+{
+	undo_before();
+	double offset = edl->tracks->align_timecodes();
+	set_timecode_offset(offset);
+	save_backup();
+	undo_after(_("align timecodes"), LOAD_ALL);
+	restart_brender();
+	cwindow->refresh_frame(CHANGE_EDL);
+	update_plugin_guis();
+}
+
diff --git a/cinelerra-5.1/cinelerra/mwindowmove.C b/cinelerra-5.1/cinelerra/mwindowmove.C
index 2c0479bb..89aaaee1 100644
--- a/cinelerra-5.1/cinelerra/mwindowmove.C
+++ b/cinelerra-5.1/cinelerra/mwindowmove.C
@@ -756,21 +756,37 @@ int MWindow::find_selection(double position, int scroll_display)
 
 double MWindow::get_position()
 {
-        return edl->local_session->get_selectionstart(1);
+	return edl->local_session->get_selectionstart(1);
 }
 
 void MWindow::set_position(double position)
 {
-        if( position != get_position() ) {
-                if( position < 0 ) position = 0;
-                edl->local_session->set_selectionstart(position);
-                edl->local_session->set_selectionend(position);
-                gui->lock_window();
-                find_cursor();
-                gui->update(1, NORMAL_DRAW, 1, 1, 1, 1, 0);
-                gui->unlock_window();
-                cwindow->update(1, 0, 0, 0, 0);
-        }
+	if( position != get_position() ) {
+		if( position < 0 ) position = 0;
+		edl->local_session->set_selectionstart(position);
+		edl->local_session->set_selectionend(position);
+		gui->lock_window();
+		find_cursor();
+		gui->update(1, NORMAL_DRAW, 1, 1, 1, 1, 0);
+		gui->unlock_window();
+		cwindow->update(1, 0, 0, 0, 0);
+	}
+}
+
+
+double MWindow::get_timecode_offset()
+{
+	return edl->session->timecode_offset;
+}
+
+void MWindow::set_timecode_offset(double offset)
+{
+	edl->session->time_format = TIME_TIMECODE;
+	edl->session->timecode_offset = offset;
+	gui->lock_window();
+	gui->update(1, NORMAL_DRAW, 1, 1, 1, 1, 0);
+	gui->unlock_window();
+	cwindow->update(1, 0, 0, 0, 0);
 }
 
 
diff --git a/cinelerra-5.1/cinelerra/pluginclient.h b/cinelerra-5.1/cinelerra/pluginclient.h
index b338deba..50d50608 100644
--- a/cinelerra-5.1/cinelerra/pluginclient.h
+++ b/cinelerra-5.1/cinelerra/pluginclient.h
@@ -107,34 +107,26 @@ PluginClientWindow* plugin_class::new_window() \
 #define LOAD_CONFIGURATION_MACRO(plugin_class, config_class) \
 int plugin_class::load_configuration() \
 { \
-	KeyFrame *prev_keyframe, *next_keyframe; \
-	prev_keyframe = get_prev_keyframe(get_source_position()); \
-	next_keyframe = get_next_keyframe(get_source_position()); \
- \
- 	int64_t next_position = edl_to_local(next_keyframe->position); \
+	KeyFrame * prev_keyframe = get_prev_keyframe(get_source_position()); \
  	int64_t prev_position = edl_to_local(prev_keyframe->position); \
- \
 	config_class old_config, prev_config, next_config; \
 	old_config.copy_from(config); \
 	read_data(prev_keyframe); \
 	prev_config.copy_from(config); \
-	read_data(next_keyframe); \
-	next_config.copy_from(config); \
- \
-	config.interpolate(prev_config,  \
-		next_config,  \
-		(next_position == prev_position) ? \
-			get_source_position() : \
-			prev_position, \
-		(next_position == prev_position) ? \
-			get_source_position() + 1 : \
-			next_position, \
-		get_source_position()); \
+	KeyFrame * next_keyframe = get_next_keyframe(get_source_position()); \
+	if( next_keyframe ) { \
+ 		int64_t next_position = edl_to_local(next_keyframe->position); \
+		read_data(next_keyframe); \
+		next_config.copy_from(config); \
  \
-	if(!config.equivalent(old_config)) \
-		return 1; \
-	else \
-		return 0; \
+		config.interpolate(prev_config, next_config,  \
+			(next_position == prev_position) ? \
+				get_source_position() : prev_position, \
+			(next_position == prev_position) ? \
+				get_source_position() + 1 : next_position, \
+			get_source_position()); \
+	} \
+	return !config.equivalent(old_config) ? 1 : 0; \
 }
 
 
diff --git a/cinelerra-5.1/cinelerra/preferences.C b/cinelerra-5.1/cinelerra/preferences.C
index dbf14c49..d7dbf4d6 100644
--- a/cinelerra-5.1/cinelerra/preferences.C
+++ b/cinelerra-5.1/cinelerra/preferences.C
@@ -98,6 +98,7 @@ Preferences::Preferences()
 	popupmenu_btnup = 1;
 	grab_input_focus = 1;
 	textbox_focus_policy = 0;
+	auto_rotate = 1;
 	forward_render_displacement = 0;
 	dvd_yuv420p_interlace = 0;
 	highlight_inverse = 0xffffff;
@@ -223,6 +224,7 @@ void Preferences::copy_from(Preferences *that)
 	popupmenu_btnup = that->popupmenu_btnup;
 	grab_input_focus = that->grab_input_focus;
 	textbox_focus_policy = that->textbox_focus_policy;
+	auto_rotate = that->auto_rotate;
 	forward_render_displacement = that->forward_render_displacement;
 	dvd_yuv420p_interlace = that->dvd_yuv420p_interlace;
 	highlight_inverse = that->highlight_inverse;
@@ -372,6 +374,7 @@ int Preferences::load_defaults(BC_Hash *defaults)
 	popupmenu_btnup = defaults->get("POPUPMENU_BTNUP", popupmenu_btnup);
 	grab_input_focus = defaults->get("GRAB_FOCUS", grab_input_focus);
 	textbox_focus_policy = defaults->get("TEXTBOX_FOCUS_POLICY", textbox_focus_policy);
+	auto_rotate = defaults->get("AUTO_ROTATE", auto_rotate);
 	forward_render_displacement = defaults->get("FORWARD_RENDER_DISPLACEMENT", forward_render_displacement);
 	dvd_yuv420p_interlace = defaults->get("DVD_YUV420P_INTERLACE", dvd_yuv420p_interlace);
 	highlight_inverse = defaults->get("HIGHLIGHT_INVERSE", highlight_inverse);
@@ -519,6 +522,7 @@ int Preferences::save_defaults(BC_Hash *defaults)
 	defaults->update("POPUPMENU_BTNUP", popupmenu_btnup);
 	defaults->update("GRAB_FOCUS", grab_input_focus);
 	defaults->update("TEXTBOX_FOCUS_POLICY", textbox_focus_policy);
+	defaults->update("AUTO_ROTATE", auto_rotate);
 	defaults->update("FORWARD_RENDER_DISPLACEMENT", forward_render_displacement);
 	defaults->update("DVD_YUV420P_INTERLACE", dvd_yuv420p_interlace);
 	defaults->update("HIGHLIGHT_INVERSE", highlight_inverse);
diff --git a/cinelerra-5.1/cinelerra/preferences.h b/cinelerra-5.1/cinelerra/preferences.h
index e0764574..fd230469 100644
--- a/cinelerra-5.1/cinelerra/preferences.h
+++ b/cinelerra-5.1/cinelerra/preferences.h
@@ -127,6 +127,8 @@ public:
 	int popupmenu_btnup;
 // textbox focus policy: click, leave
 	int textbox_focus_policy;
+// apply display_matrix rotation, ffmpeg only
+	int auto_rotate;
 // forward playback starts next frame, not this frame
 	int forward_render_displacement;
 // use dvd yuv420p interlace format
diff --git a/cinelerra-5.1/cinelerra/render.C b/cinelerra-5.1/cinelerra/render.C
index 741d6ff3..323bebf3 100644
--- a/cinelerra-5.1/cinelerra/render.C
+++ b/cinelerra-5.1/cinelerra/render.C
@@ -446,15 +446,16 @@ int Render::check_asset(EDL *edl, Asset &asset)
 	return 0;
 }
 
-int Render::get_strategy(int use_renderfarm, int use_labels)
+int Render::get_strategy(int use_renderfarm, int use_labels, int range_type)
 {
-	return use_renderfarm ?
-		(use_labels ? FILE_PER_LABEL_FARM : SINGLE_PASS_FARM) :
-		(use_labels ? FILE_PER_LABEL      : SINGLE_PASS     ) ;
+	return range_type == RANGE_1FRAME ? SINGLE_PASS :
+		 use_renderfarm ?
+			(use_labels ? FILE_PER_LABEL_FARM : SINGLE_PASS_FARM) :
+			(use_labels ? FILE_PER_LABEL      : SINGLE_PASS     ) ;
 }
 int Render::get_strategy()
 {
-	return get_strategy(preferences->use_renderfarm, use_labels);
+	return get_strategy(preferences->use_renderfarm, use_labels, range_type);
 }
 
 void Render::start_progress()
diff --git a/cinelerra-5.1/cinelerra/render.h b/cinelerra-5.1/cinelerra/render.h
index eddbf7c5..ad954335 100644
--- a/cinelerra-5.1/cinelerra/render.h
+++ b/cinelerra-5.1/cinelerra/render.h
@@ -137,7 +137,7 @@ public:
 // This should be integrated into the Asset Class.
 	static int check_asset(EDL *edl, Asset &asset);
 // strategy to conform with using renderfarm.
-	static int get_strategy(int use_renderfarm, int use_labels);
+	static int get_strategy(int use_renderfarm, int use_labels, int range_type);
 	int get_strategy();
 // Force filename to have a 0 padded number if rendering to a list.
 	int check_numbering(Asset &asset);
diff --git a/cinelerra-5.1/cinelerra/tracks.C b/cinelerra-5.1/cinelerra/tracks.C
index d904d5d6..170f2931 100644
--- a/cinelerra-5.1/cinelerra/tracks.C
+++ b/cinelerra-5.1/cinelerra/tracks.C
@@ -787,3 +787,21 @@ void Tracks::move_tracks(Track *src, Track *dst, int n)
 	}
 }
 
+double Tracks::align_timecodes()
+{
+	double offset = -1;
+	for( Track *track=edl->tracks->first; track; track=track->next ) {
+		if( !track->is_armed() ) continue;
+		double early_offset = track->edits->early_timecode();
+		if( offset < 0 || offset > early_offset )
+			offset = early_offset;
+	}
+	if( offset >= 0 ) {
+		for( Track *track=edl->tracks->first; track; track=track->next ) {
+			if( !track->is_armed() ) continue;
+			track->edits->align_timecodes(offset);
+		}
+	}
+	return offset;
+}
+
diff --git a/cinelerra-5.1/cinelerra/tracks.h b/cinelerra-5.1/cinelerra/tracks.h
index dd1a92f6..449fd6ad 100644
--- a/cinelerra-5.1/cinelerra/tracks.h
+++ b/cinelerra-5.1/cinelerra/tracks.h
@@ -112,6 +112,7 @@ public:
 	void translate_camera(float dx, float dy, int all=0);
 	void crop_resize(float x, float y, float z);
 	void crop_shrink(float x, float y, float z);
+	double align_timecodes();
 
 	int total_of(int type);
 	Track* get_track_by_id(int id);
diff --git a/cinelerra-5.1/cinelerra/vwindowgui.C b/cinelerra-5.1/cinelerra/vwindowgui.C
index 09d3e6f5..e789d1f0 100644
--- a/cinelerra-5.1/cinelerra/vwindowgui.C
+++ b/cinelerra-5.1/cinelerra/vwindowgui.C
@@ -560,7 +560,8 @@ VWindowEditing::VWindowEditing(MWindow *mwindow, VWindow *vwindow)
 		0, // use_goto
 		1, // use_clk2play
 		1, // use_scope
-		0) // use_gang_tracks
+		0, // use_gang_tracks
+		0) // use_timecode
 {
 	this->mwindow = mwindow;
 	this->vwindow = vwindow;
diff --git a/cinelerra-5.1/cinelerra/zoombar.C b/cinelerra-5.1/cinelerra/zoombar.C
index 5171469d..d8d3ccc3 100644
--- a/cinelerra-5.1/cinelerra/zoombar.C
+++ b/cinelerra-5.1/cinelerra/zoombar.C
@@ -612,7 +612,8 @@ int FromTextBox::update_position(double new_position)
 		mwindow->edl->session->time_format,
 		mwindow->edl->session->sample_rate,
 		mwindow->edl->session->frame_rate,
-		mwindow->edl->session->frames_per_foot);
+		mwindow->edl->session->frames_per_foot,
+		mwindow->get_timecode_offset());
 //printf("FromTextBox::update_position %f %s\n", new_position, string);
 	update(string);
 	return 0;
@@ -681,7 +682,8 @@ int ToTextBox::update_position(double new_position)
 		mwindow->edl->session->time_format,
 		mwindow->edl->session->sample_rate,
 		mwindow->edl->session->frame_rate,
-		mwindow->edl->session->frames_per_foot);
+		mwindow->edl->session->frames_per_foot,
+		mwindow->get_timecode_offset());
 	update(string);
 	return 0;
 }
diff --git a/cinelerra-5.1/cinelerra/zoompanel.C b/cinelerra-5.1/cinelerra/zoompanel.C
index 94077469..5e9dcd5b 100644
--- a/cinelerra-5.1/cinelerra/zoompanel.C
+++ b/cinelerra-5.1/cinelerra/zoompanel.C
@@ -244,7 +244,8 @@ double ZoomPanel::text_to_zoom(char *text, int use_table)
 				mwindow->edl->session->sample_rate,
 				mwindow->edl->session->time_format,
 				mwindow->edl->session->frame_rate,
-				mwindow->edl->session->frames_per_foot);
+				mwindow->edl->session->frames_per_foot,
+				mwindow->get_timecode_offset());
 			total_samples /= mwindow->theme->mcanvas_w -
 				mwindow->theme->patchbay_w -
 				BC_ScrollBar::get_span(SCROLL_VERT);
diff --git a/cinelerra-5.1/doc/shortcuts.html b/cinelerra-5.1/doc/shortcuts.html
index 343f7f5c..9f54f568 100644
--- a/cinelerra-5.1/doc/shortcuts.html
+++ b/cinelerra-5.1/doc/shortcuts.html
@@ -1150,7 +1150,7 @@
                 <td height="26" align="left"><b><font face="Liberation Serif" size=4>  Drag/Drop</font></b></td>
                 <td align="left"><font face="Liberation Serif" size=4>Clear Select</font></td>
                 <td align="left"><font face="Liberation Serif" size=4>Ctrl-Shift-A</font></td>
-                <td align="left"><font face="Liberation Serif" size=4>Delselect all selected edits</font></td>
+                <td align="left"><font face="Liberation Serif" size=4>De-select all selected edits</font></td>
         </tr>
         <tr>
                 <td height="26" align="left"><b><font face="Liberation Serif" size=4>     Edits </font></b></td>
diff --git a/cinelerra-5.1/ffmpeg/plugin.opts b/cinelerra-5.1/ffmpeg/plugin.opts
index ae5822d8..7c1176eb 100644
--- a/cinelerra-5.1/ffmpeg/plugin.opts
+++ b/cinelerra-5.1/ffmpeg/plugin.opts
@@ -387,6 +387,8 @@ vibrance
 #xfade ###Input/output error
 #arnndn ###Invalid argument
 #dnn_processing ###Invalid argument
+#tonemap_vaapi ###Operation not permitted
+#afirsrc ###Operation not permitted
 #; the ffmpeg system library on Arch has these errors:
 #ladspa
 #ass
diff --git a/cinelerra-5.1/guicast/bccmodels.C b/cinelerra-5.1/guicast/bccmodels.C
index 13df1c31..38c2c4b0 100644
--- a/cinelerra-5.1/guicast/bccmodels.C
+++ b/cinelerra-5.1/guicast/bccmodels.C
@@ -183,7 +183,7 @@ int BC_CModels::calculate_datasize(int w, int h, int bytes_per_line, int color_m
 	}
 	if( bytes_per_line < 0 )
 		bytes_per_line = w * calculate_pixelsize(color_model);
-	return h * bytes_per_line + 4;
+	return h * bytes_per_line + BC_COLOR_ALIGN;
 }
 
 int BC_CModels::bc_to_x(int color_model)
diff --git a/cinelerra-5.1/guicast/bccmodels.h b/cinelerra-5.1/guicast/bccmodels.h
index 28b58459..30dd1902 100644
--- a/cinelerra-5.1/guicast/bccmodels.h
+++ b/cinelerra-5.1/guicast/bccmodels.h
@@ -81,7 +81,7 @@ enum BC_CModel {
 #define FOURCC_YUV2 0x32595559  /* YUV2   YUV422 */
 #define FOURCC_UYVY 0x59565955  /* UYVY   UVY422 */
 #define FOURCC_I420 0x30323449  /* I420   Intel Indeo 4 */
-
+#define BC_COLOR_ALIGN 64	/* overwrite padding, ssse3 */
 
 #endif // !BC_TRANSPARENCY
 
diff --git a/cinelerra-5.1/guicast/units.C b/cinelerra-5.1/guicast/units.C
index e0a170dc..cf48af17 100644
--- a/cinelerra-5.1/guicast/units.C
+++ b/cinelerra-5.1/guicast/units.C
@@ -166,7 +166,8 @@ void Units::finit()
 
 // give text representation as time
 char* Units::totext(char *text, double seconds, int time_format,
-			int sample_rate, float frame_rate, float frames_per_foot)
+			int sample_rate, float frame_rate, float frames_per_foot,
+			double timecode_offset)
 {
 	int64_t hour, feet, frame;
 	int minute, second, thousandths;
@@ -208,6 +209,8 @@ char* Units::totext(char *text, double seconds, int time_format,
 		sprintf(text, "%02d:%02d:%02d", (int)hour, minute, second);
 		break; }
 
+	case TIME_TIMECODE:
+		seconds += timecode_offset; // fall thru
 	case TIME_HMSF: {
 		seconds = fabs(seconds) + 1.0e-6;
 		hour = seconds/3600;
@@ -263,10 +266,11 @@ char* Units::totext(char *text, double seconds, int time_format,
 
 // give text representation as time
 char* Units::totext(char *text, int64_t samples, int samplerate,
-		int time_format, float frame_rate, float frames_per_foot)
+		int time_format, float frame_rate, float frames_per_foot,
+		double timecode_offset)
 {
 	return totext(text, (double)samples/samplerate, time_format,
-			samplerate, frame_rate, frames_per_foot);
+		samplerate, frame_rate, frames_per_foot, timecode_offset);
 }
 
 int64_t Units::get_int64(const char *&bp)
@@ -299,7 +303,8 @@ void Units::skip_seperators(const char *&bp)
 }
 
 int64_t Units::fromtext(const char *text, int samplerate, int time_format,
-			float frame_rate, float frames_per_foot)
+			float frame_rate, float frames_per_foot,
+			double timecode_offset)
 {
 	int64_t hours, total_samples;
 	int minutes, frames, feet;
@@ -320,12 +325,15 @@ int64_t Units::fromtext(const char *text, int samplerate, int time_format,
 		total_seconds = seconds + minutes*60 + hours*3600;
 		break; }
 
+	case TIME_TIMECODE:
 	case TIME_HMSF: {
 		hours = get_int64(text);    skip_seperators(text);
 		minutes = get_int64(text);  skip_seperators(text);
 		seconds = get_int64(text);  skip_seperators(text);
 		frames = get_int64(text);
 		total_seconds = frames/frame_rate + seconds + minutes*60 + hours*3600;
+		if( time_format == TIME_TIMECODE )
+			total_seconds -= timecode_offset;
 		break; }
 
 	case TIME_SAMPLES: {
@@ -365,10 +373,11 @@ int64_t Units::fromtext(const char *text, int samplerate, int time_format,
 }
 
 double Units::text_to_seconds(const char *text, int samplerate, int time_format,
-				float frame_rate, float frames_per_foot)
+				float frame_rate, float frames_per_foot,
+				double timecode_offset)
 {
 	return (double)fromtext(text, samplerate, time_format,
-				frame_rate, frames_per_foot) / samplerate;
+		frame_rate, frames_per_foot, timecode_offset) / samplerate;
 }
 
 
@@ -381,6 +390,7 @@ int Units::timeformat_totype(char *tcf)
 	if (!strcmp(tcf,TIME_HMS2__STR)) return(TIME_HMS2);
 	if (!strcmp(tcf,TIME_HMS3__STR)) return(TIME_HMS3);
 	if (!strcmp(tcf,TIME_HMSF__STR)) return(TIME_HMSF);
+	if (!strcmp(tcf,TIME_TIMECODE__STR)) return(TIME_TIMECODE);
 	if (!strcmp(tcf,TIME_SAMPLES__STR)) return(TIME_SAMPLES);
 	if (!strcmp(tcf,TIME_SAMPLES_HEX__STR)) return(TIME_SAMPLES_HEX);
 	if (!strcmp(tcf,TIME_FRAMES__STR)) return(TIME_FRAMES);
@@ -498,6 +508,7 @@ const char* Units::print_time_format(int time_format, char *string)
 	case TIME_SECONDS:     fmt = TIME_SECONDS_TEXT;               break;
 	case TIME_MS1:
 	case TIME_MS2:         fmt = TIME_MS2_TEXT;                   break;
+	case TIME_TIMECODE:    fmt = TIME_TIMECODE_TEXT;              break;
 	}
 	return strcpy(string,fmt);
 }
@@ -513,6 +524,7 @@ int Units::text_to_format(const char *string)
 	if(!strcmp(string, TIME_HMS3_TEXT)) return TIME_HMS3;
 	if(!strcmp(string, TIME_SECONDS_TEXT)) return TIME_SECONDS;
 	if(!strcmp(string, TIME_MS2_TEXT)) return TIME_MS2;
+	if(!strcmp(string, TIME_TIMECODE_TEXT)) return TIME_TIMECODE;
 	return TIME_HMS;
 }
 
@@ -617,6 +629,7 @@ const char* Units::format_to_separators(int time_format)
 		case TIME_HMS:         return "0:00:00.000";
 		case TIME_HMS2:        return "0:00:00";
 		case TIME_HMS3:        return "00:00:00";
+		case TIME_TIMECODE:
 		case TIME_HMSF:        return "0:00:00:00";
 		case TIME_SAMPLES:     return 0;
 		case TIME_SAMPLES_HEX: return 0;
diff --git a/cinelerra-5.1/guicast/units.h b/cinelerra-5.1/guicast/units.h
index 7e2243ef..6de33118 100644
--- a/cinelerra-5.1/guicast/units.h
+++ b/cinelerra-5.1/guicast/units.h
@@ -34,7 +34,7 @@
 #define TOTALFREQS 1024
 // slots per octave
 #define OCTAVE 105
-#define TOTAL_TIMEFORMATS 7
+#define TOTAL_TIMEFORMATS 8
 
 // h:mm:ss.sss
 #define TIME_HMS 0
@@ -55,6 +55,7 @@
 #define TIME_HMS2__STR         "h:mm:ss"
 #define TIME_HMS3__STR         "hh:mm:ss"
 #define TIME_HMSF__STR         "h:mm:ss:ff"
+#define TIME_TIMECODE__STR     "timecode"
 #define TIME_SAMPLES__STR      "audio samples"
 #define TIME_SAMPLES_HEX__STR  "audio samples (hex)"
 #define TIME_FRAMES__STR       "video frames"
@@ -77,6 +78,9 @@
 #define TIME_MS2 10
 #define TIME_MS2_TEXT _("Minutes:Seconds")
 
+#define TIME_TIMECODE 11
+#define TIME_TIMECODE_TEXT _("Timecode")
+
 class Units;
 
 class DB
@@ -178,16 +182,20 @@ public:
 	static int64_t tosamples(double frames, int sample_rate, float framerate);
 // give text representation as time
 	static char* totext(char *text, int64_t samples, int time_format,
-		int samplerate, float frame_rate = 0, float frames_per_foot = 0);
+		int samplerate, float frame_rate = 0, float frames_per_foot = 0,
+			double timecode_offset = 0);
 // give text representation as time
 	static char* totext(char *text, double seconds, int time_format,
-		int sample_rate = 0, float frame_rate = 0, float frames_per_foot = 0);
+		int sample_rate = 0, float frame_rate = 0, float frames_per_foot = 0,
+			double timecode_offset = 0);
 // convert time to samples
 	static int64_t fromtext(const char *text, int samplerate,
-		int time_format, float frame_rate, float frames_per_foot);
+		int time_format, float frame_rate, float frames_per_foot,
+		double timecode_offset);
 // Convert text to seconds
 	static double text_to_seconds(const char *text, int samplerate,
-		int time_format, float frame_rate = 0, float frames_per_foot = 0);
+		int time_format, float frame_rate = 0, float frames_per_foot = 0,
+			double timecode_offset = 0);
 	static char* size_totext(int64_t bytes, char *text);
 
 	static float xy_to_polar(int x, int y);
diff --git a/cinelerra-5.1/guicast/vframe.C b/cinelerra-5.1/guicast/vframe.C
index c1ff0523..d85245bd 100644
--- a/cinelerra-5.1/guicast/vframe.C
+++ b/cinelerra-5.1/guicast/vframe.C
@@ -416,7 +416,7 @@ long VFrame::get_bytes_per_line()
 
 long VFrame::get_data_size()
 {
-	return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
+	return calculate_data_size(w, h, bytes_per_line, color_model) - BC_COLOR_ALIGN;
 }
 
 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
diff --git a/cinelerra-5.1/info/plugins.txt b/cinelerra-5.1/info/plugins.txt
index c8cabb8b..9c5e8a1b 100644
--- a/cinelerra-5.1/info/plugins.txt
+++ b/cinelerra-5.1/info/plugins.txt
@@ -243,11 +243,14 @@ Zoom Blur:	Blur the video and use a zoom effect.
 #
 #  Description of FFmpeg Video Plugins
 #
+F_addroi:	Mark a region of interest in a video frame.
 F_amplify:	Amplify changes between successive video frames.
 F_atadenoise:	Apply an Adaptive Temporal Averaging Denoiser.
 F_avgblur:	Apply average blur filter.
 F_bbox:		Compute bounding box for each frame.
 F_bench:	Benchmarks part of a filtergraph.
+F_bilateral:	Apply bilateral filter, spatial smoothing while
+		preserving edges.
 F_bitplanenoise: Measure bit plane noise.
 F_blackdetect:	Detect video intervals that are (almost) black.
 F_blackframe:	Detect frames that are (almost) black.
@@ -255,6 +258,7 @@ F_boxblur:	Blurs the input video. Through the settings you are
 		able to change the power and the radius of the
 		boxblur applied to luma, chroma and alpha.
 F_bwdif:	Deinterlaces the input image.
+F_cas:		Apply Contrast Adaptive Sharpen filter to video. 
 F_chromahold:	Turns a certain color range into gray.
 F_chromakey:	Turns a certain color into transparency. Operates on
 		YUV colors.
@@ -273,6 +277,7 @@ F_crop:		Crops the input video.
 F_cropdetect:	Auto-detect crop size.
 F_curves:	Adjust components curves.
 F_datascope:	Video data analysis.
+F_dblur:	Apply Directional blur filter.
 F_dctdnoiz:	Denoise frames using 2D DCT.
 F_deband:	Debands video.
 F_deblock:	Deblock video.
@@ -323,6 +328,7 @@ F_framestep:	Select one frame every N frames.
 F_fspp:		Applies Fast Simple Post-processing filter.
 F_gblur:	Apply Gaussian Blur filter.
 F_gradfun:	Debands video quickly using gradients.
+F_gradients:	Draws a transparent gradient.
 F_graphmonitor:	Show various filtergraph stats.
 F_greyedge:	Estimates scene illumination by grey edge
 		assumption.
@@ -354,6 +360,7 @@ F_lutyuv:	Compute and apply a lookup table to YUV input.
 F_mandelbrot:	Render a Mandelbrot fractal.
 F_maskfun:	Create Mask.
 F_mcdeint:	Applies motion compensating deinterlacing.
+F_median:	Pick median pixel from rectangle defined by radius.
 F_mestimate:	Generate motion vectors.
 F_metadata:	Manipulate video frame metadata.
 F_mpdecimate:	Remove near-duplicate frames.
@@ -377,6 +384,8 @@ F_pal75bars:	Generate PAL 75% color bars. This only works with
 F_perms:	Set permissions for the output video frame.
 F_perspective:	Corrects the perspective of video.
 F_phase:	Phase shift fields.
+F_photosensitivity:	 Filter out photosensitive epilepsy seizure-inducing
+		flashes.
 F_pixscope:	Pixel data analysis for checking color and levels.
 		It will display sample values of color channels.
 F_pp:		Filters video using libpostproc.
@@ -402,6 +411,9 @@ F_sab:		Applies shape adaptive blur.
 F_scale:	Scale the input video size and/or convert the image
 		format.
 F_scale_cuda:	GPU accelerated video resizer.
+F_scdet:	Detect video scene change.
+F_scroll:	Scroll input video horizontally and/or vertically
+		by constant speed.
 F_separatefields: Split input video frames into fields.
 F_setparams:	Force field, or color property for the output video
 		frame.
@@ -410,6 +422,8 @@ F_showinfo:	Show textual information for each video frame.
 F_showpalette:	Display frame palette.
 F_shuffleframes: Shuffles video frames.
 F_shuffleplanes: Shuffles video planes.
+F_sierpinski:	Generate a Sierpinski carpet/triangle fractal, and
+		randomly pan around.
 F_signalstats:	Separates statistics from video analysis.
 F_smartblur:	Blurs the input video without impacting the outlines.
 		Through the settings you can select the radius, the
@@ -427,15 +441,20 @@ F_tpad:		Temporarily pad video frames.
 F_tblend:	Blend successive frames.
 F_testsrc:	Generate test pattern.
 F_testsrc2:	Generate another test pattern.
+F_thistogram:	Compute and draw a color distribution histogram for
+		the input video across time.
 F_tile:		Tile several successive frames together.
 F_tinterlace:	Performs temporal field interlacing.
 F_tlut2:	Compute and apply a lookup table from two
 		successive frames.
+F_tmedian:	Pick median pixels from successive frames.
 F_tmix:		Mix successive video frames.
 F_transpose:	Transposes input video.
 F_transpose_vaapi: VAAPI VPP for transpose.
 F_unsharp:	Sharpen or blur the input video.
+F_untile:	Untile a frame into a sequence of frames.
 F_uspp:		Applies Ultra Simple/Slow Post-processing filter.
+F_v360:		Convert 360 videos between various formats.
 F_vaguedenoiser: Applies a Wavelet based Denoiser.
 F_vectorscope:	Video vectorscope.
 F_vflip:	Flips the input video vertically.
@@ -451,6 +470,7 @@ F_weave:	Weaves input video fields into frames.
 F_xbr:		Scales the input using xBR algorithm.
 F_yadif:	Deinterlaces the input image.
 F_yadif_cuda:	Deinterlace CUDA frames.
+F_yaepblur:	Yet another edge preserving blur filter.
 F_yuvtestsrc:	Generate YUV test pattern.
 F_zoompan:	Applies Zoom & Pan effect.
 #
@@ -488,6 +508,7 @@ F_asoftclip:	Apply audio soft clipping - a type of distortion effect
 		where signal amplitude is saturated along a smooth
 		curve.
 F_astats:	Shows time domain statistics about audio frames.
+F_asubboost:	Boost subwoofer frequencies.
 F_atempo:	Adjusts audio tempo.
 F_atrim:	Pick one continuous section from the input and drop
 		the rest.
diff --git a/cinelerra-5.1/plugins/resamplert/resamplert.C b/cinelerra-5.1/plugins/resamplert/resamplert.C
index f0c75d8d..2b3b98d5 100644
--- a/cinelerra-5.1/plugins/resamplert/resamplert.C
+++ b/cinelerra-5.1/plugins/resamplert/resamplert.C
@@ -182,8 +182,7 @@ ResampleRTResample::ResampleRTResample(ResampleRT *plugin)
 // To get the keyframes to work, resampling is always done in the forward
 // direction with the plugin converting to reverse.
 int ResampleRTResample::read_samples(Samples *buffer,
-	int64_t start,
-	int64_t len)
+	int64_t start, int64_t len, int direction)
 {
 	int result = plugin->read_samples(buffer,
 		0,
diff --git a/cinelerra-5.1/plugins/resamplert/resamplert.h b/cinelerra-5.1/plugins/resamplert/resamplert.h
index 4bada326..63baf08d 100644
--- a/cinelerra-5.1/plugins/resamplert/resamplert.h
+++ b/cinelerra-5.1/plugins/resamplert/resamplert.h
@@ -89,7 +89,7 @@ class ResampleRTResample : public Resample
 {
 public:
 	ResampleRTResample(ResampleRT *plugin);
-	int read_samples(Samples *buffer, int64_t start, int64_t len);
+	int read_samples(Samples *buffer, int64_t start, int64_t len, int direction);
 	ResampleRT *plugin;
 };
 
diff --git a/cinelerra-5.1/plugins/theme_blond/blondtheme.C b/cinelerra-5.1/plugins/theme_blond/blondtheme.C
index 52434590..3619d439 100644
--- a/cinelerra-5.1/plugins/theme_blond/blondtheme.C
+++ b/cinelerra-5.1/plugins/theme_blond/blondtheme.C
@@ -841,6 +841,7 @@ void BlondTheme::initialize()
 	splice_data = new_button("splice.png", editpanel_up, editpanel_hi, editpanel_dn, "slicebutton");
 	new_button("toclip.png", editpanel_up, editpanel_hi, editpanel_dn, "toclip");
 	new_button("goto.png", editpanel_up, editpanel_hi, editpanel_dn, "goto");
+	new_button("clapper.png", editpanel_up, editpanel_hi, editpanel_dn, "clapperbutton");
 	new_button("top_justify.png", editpanel_up, editpanel_hi, editpanel_dn, "top_justify");
 	new_button("undo.png", editpanel_up, editpanel_hi, editpanel_dn, "undo");
 	new_button("wrench.png", editpanel_up, editpanel_hi, editpanel_dn, "wrench");
diff --git a/cinelerra-5.1/plugins/theme_blond/data/clapper.png b/cinelerra-5.1/plugins/theme_blond/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_blond_cv/blondcvtheme.C b/cinelerra-5.1/plugins/theme_blond_cv/blondcvtheme.C
index 6db8b722..993f75ad 100644
--- a/cinelerra-5.1/plugins/theme_blond_cv/blondcvtheme.C
+++ b/cinelerra-5.1/plugins/theme_blond_cv/blondcvtheme.C
@@ -854,6 +854,7 @@ void BlondCVTheme::initialize()
 	splice_data = new_button("splice.png", editpanel_up, editpanel_hi, editpanel_dn, "slicebutton");
 	new_button("toclip.png", editpanel_up, editpanel_hi, editpanel_dn, "toclip");
 	new_button("goto.png", editpanel_up, editpanel_hi, editpanel_dn, "goto");
+	new_button("clapper.png", editpanel_up, editpanel_hi, editpanel_dn, "clapperbutton");
 	new_button("top_justify.png", editpanel_up, editpanel_hi, editpanel_dn, "top_justify");
 	new_button("undo.png", editpanel_up, editpanel_hi, editpanel_dn, "undo");
 	//new_button("wrench.png", editpanel_up, editpanel_hi, editpanel_dn, "wrench");
diff --git a/cinelerra-5.1/plugins/theme_blond_cv/data/clapper.png b/cinelerra-5.1/plugins/theme_blond_cv/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_blue/bluetheme.C b/cinelerra-5.1/plugins/theme_blue/bluetheme.C
index b589e0e3..f83fc3a8 100644
--- a/cinelerra-5.1/plugins/theme_blue/bluetheme.C
+++ b/cinelerra-5.1/plugins/theme_blue/bluetheme.C
@@ -839,6 +839,7 @@ void BlueDotTheme::initialize()
 	splice_data = new_button("splice.png", editpanel_up, editpanel_hi, editpanel_dn, "slicebutton");
 	new_button("toclip.png", editpanel_up, editpanel_hi, editpanel_dn, "toclip");
 	new_button("goto.png", editpanel_up, editpanel_hi, editpanel_dn, "goto");
+	new_button("clapper.png", editpanel_up, editpanel_hi, editpanel_dn, "clapperbutton");
 	new_button("top_justify.png", editpanel_up, editpanel_hi, editpanel_dn, "top_justify");
 	new_button("undo.png", editpanel_up, editpanel_hi, editpanel_dn, "undo");
 	new_button("wrench.png", editpanel_up, editpanel_hi, editpanel_dn, "wrench");
diff --git a/cinelerra-5.1/plugins/theme_blue/data/clapper.png b/cinelerra-5.1/plugins/theme_blue/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_blue_dot/bluedottheme.C b/cinelerra-5.1/plugins/theme_blue_dot/bluedottheme.C
index 3d000749..dd42972e 100644
--- a/cinelerra-5.1/plugins/theme_blue_dot/bluedottheme.C
+++ b/cinelerra-5.1/plugins/theme_blue_dot/bluedottheme.C
@@ -872,6 +872,7 @@ void BlueDotTheme::initialize()
 	splice_data = new_button("splice.png", editpanel_up, editpanel_hi, editpanel_dn, "slicebutton");
 	new_button("toclip.png", editpanel_up, editpanel_hi, editpanel_dn, "toclip");
 	new_button("goto.png", editpanel_up, editpanel_hi, editpanel_dn, "goto");
+	new_button("clapper.png", editpanel_up, editpanel_hi, editpanel_dn, "clapperbutton");
 	new_button("top_justify.png", editpanel_up, editpanel_hi, editpanel_dn, "top_justify");
 	new_button("undo.png", editpanel_up, editpanel_hi, editpanel_dn, "undo");
 	new_button("wrench.png", "editpanelW_up.png", "editpanelW_hi.png", "editpanelW_dn.png", "wrench");
diff --git a/cinelerra-5.1/plugins/theme_blue_dot/data/clapper.png b/cinelerra-5.1/plugins/theme_blue_dot/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_bright/brighttheme.C b/cinelerra-5.1/plugins/theme_bright/brighttheme.C
index 6c8afa05..2ca4541d 100644
--- a/cinelerra-5.1/plugins/theme_bright/brighttheme.C
+++ b/cinelerra-5.1/plugins/theme_bright/brighttheme.C
@@ -843,6 +843,7 @@ void BrightTheme::initialize()
 	splice_data = new_button("splice.png", editpanel_up, editpanel_hi, editpanel_dn, "slicebutton");
 	new_button("toclip.png", editpanel_up, editpanel_hi, editpanel_dn, "toclip");
 	new_button("goto.png", editpanel_up, editpanel_hi, editpanel_dn, "goto");
+	new_button("clapper.png", editpanel_up, editpanel_hi, editpanel_dn, "clapperbutton");
 	new_button("top_justify.png", editpanel_up, editpanel_hi, editpanel_dn, "top_justify");
 	new_button("undo.png", editpanel_up, editpanel_hi, editpanel_dn, "undo");
 	new_button("wrench.png", editpanel_up, editpanel_hi, editpanel_dn, "wrench");
diff --git a/cinelerra-5.1/plugins/theme_bright/data/clapper.png b/cinelerra-5.1/plugins/theme_bright/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_cakewalk/cakewalk.C b/cinelerra-5.1/plugins/theme_cakewalk/cakewalk.C
index 22d2d554..9c0cdd97 100644
--- a/cinelerra-5.1/plugins/theme_cakewalk/cakewalk.C
+++ b/cinelerra-5.1/plugins/theme_cakewalk/cakewalk.C
@@ -898,6 +898,9 @@ void CAKEWALKTHEME::initialize()
  new_button("goto.png",
       editpanel_up, editpanel_hi, editpanel_dn,
       "goto");
+ new_button("clapper.png",
+      editpanel_up, editpanel_hi, editpanel_dn,
+      "clapperbutton");
  new_button("top_justify.png",
       editpanel_up, editpanel_hi, editpanel_dn,
       "top_justify");
diff --git a/cinelerra-5.1/plugins/theme_cakewalk/data/clapper.png b/cinelerra-5.1/plugins/theme_cakewalk/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_hulk/data/clapper.png b/cinelerra-5.1/plugins/theme_hulk/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_hulk/hulktheme.C b/cinelerra-5.1/plugins/theme_hulk/hulktheme.C
index e9b216fe..2a93f8ab 100644
--- a/cinelerra-5.1/plugins/theme_hulk/hulktheme.C
+++ b/cinelerra-5.1/plugins/theme_hulk/hulktheme.C
@@ -838,6 +838,7 @@ void HULKTHEME::initialize()
 	splice_data = new_button("splice.png", editpanel_up, editpanel_hi, editpanel_dn, "slicebutton");
 	new_button("toclip.png", editpanel_up, editpanel_hi, editpanel_dn, "toclip");
 	new_button("goto.png", editpanel_up, editpanel_hi, editpanel_dn, "goto");
+	new_button("clapper.png", editpanel_up, editpanel_hi, editpanel_dn, "clapperbutton");
 	new_button("top_justify.png", editpanel_up, editpanel_hi, editpanel_dn, "top_justify");
 	new_button("undo.png", editpanel_up, editpanel_hi, editpanel_dn, "undo");
 	new_button("wrench.png", editpanel_up, editpanel_hi, editpanel_dn, "wrench");
diff --git a/cinelerra-5.1/plugins/theme_neophyte/data/clapper.png b/cinelerra-5.1/plugins/theme_neophyte/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_neophyte/neophyte.C b/cinelerra-5.1/plugins/theme_neophyte/neophyte.C
index e58d2c04..744f5dcf 100644
--- a/cinelerra-5.1/plugins/theme_neophyte/neophyte.C
+++ b/cinelerra-5.1/plugins/theme_neophyte/neophyte.C
@@ -1042,6 +1042,9 @@ void NEOPHYTETHEME::initialize()
 	new_button("goto.png",
 			   editpanel_up, editpanel_hi, editpanel_dn,
 			   "goto");
+	new_button("clapper.png",
+			   editpanel_up, editpanel_hi, editpanel_dn,
+			   "clapperbutton");
 	new_button("top_justify.png",
 			   editpanel_up, editpanel_hi, editpanel_dn,
 			   "top_justify");
diff --git a/cinelerra-5.1/plugins/theme_pinklady/data/clapper.png b/cinelerra-5.1/plugins/theme_pinklady/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_pinklady/pinkladytheme.C b/cinelerra-5.1/plugins/theme_pinklady/pinkladytheme.C
index db4ed973..7de528a7 100644
--- a/cinelerra-5.1/plugins/theme_pinklady/pinkladytheme.C
+++ b/cinelerra-5.1/plugins/theme_pinklady/pinkladytheme.C
@@ -838,6 +838,7 @@ void PINKLADY::initialize()
 	splice_data = new_button("splice.png", editpanel_up, editpanel_hi, editpanel_dn, "slicebutton");
 	new_button("toclip.png", editpanel_up, editpanel_hi, editpanel_dn, "toclip");
 	new_button("goto.png", editpanel_up, editpanel_hi, editpanel_dn, "goto");
+	new_button("clapper.png", editpanel_up, editpanel_hi, editpanel_dn, "clapperbutton");
 	new_button("top_justify.png", editpanel_up, editpanel_hi, editpanel_dn, "top_justify");
 	new_button("undo.png", editpanel_up, editpanel_hi, editpanel_dn, "undo");
 	new_button("wrench.png", editpanel_up, editpanel_hi, editpanel_dn, "wrench");
diff --git a/cinelerra-5.1/plugins/theme_suv/data/clapper.png b/cinelerra-5.1/plugins/theme_suv/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_suv/suv.C b/cinelerra-5.1/plugins/theme_suv/suv.C
index 2b20a62e..8f0ed26a 100644
--- a/cinelerra-5.1/plugins/theme_suv/suv.C
+++ b/cinelerra-5.1/plugins/theme_suv/suv.C
@@ -825,6 +825,7 @@ void SUV::initialize()
 	splice_data = new_button("splice.png", editpanel_up, editpanel_hi, editpanel_dn, "slicebutton");
 	new_button("toclip.png", editpanel_up, editpanel_hi, editpanel_dn, "toclip");
 	new_button("goto.png", editpanel_up, editpanel_hi, editpanel_dn, "goto");
+	new_button("clapper.png", editpanel_up, editpanel_hi, editpanel_dn, "clapperbutton");
 	new_button("top_justify.png", editpanel_up, editpanel_hi, editpanel_dn, "top_justify");
 	new_button("undo.png", editpanel_up, editpanel_hi, editpanel_dn, "undo");
 	new_button("wrench.png", editpanel_up, editpanel_hi, editpanel_dn, "wrench");
diff --git a/cinelerra-5.1/plugins/theme_unflat/data/clapper.png b/cinelerra-5.1/plugins/theme_unflat/data/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec4656c6b54286e20be4268d4aeac1631ab7d7d7
GIT binary patch
literal 1382
zcmV-s1)2JZP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000FoNkl<ZNXOMy
zT}%{L7(I7p*qPY@0t=~2A%>r=!Ac@vK_saLTN-I<8WT~J;tLv$TcMhWh#@qjwQ1@L
zDNSrkVydyGQIm~}#%LRUn$VRWVHL#e0~Ab`MYc(I%ep@d_v?f10#Tdx(MfJ*?w#+R
z@67qmH#5MielP%NYHC7GP7WAj&js}L^<nku)yT-m002ZHk(B_?_7D+7QH0a!tP(|W
zMANi~r%#`Ln!s+i!|iq>6bgYc1|o`W^m@I}G!2TPKoA5}S63rBIXMP8KR*vq6k#+P
zP2Jty&7aiQR~<NT;G0dQrJrrsumKVP`2BvII&}(OulKnp5Cj241R{bYNvN!>Tyg)>
zrAsU+DQWA@ojbo8y??)8baV`!+1a<F1f^&o5xr1D&Ux%w*L5h0vTVNan$c)H7z_sM
zIp-+^KoA*>Mx!Z4@c$I7p`if=g8`g#aLzY!&M#iQdZpFjaHL3*1VIpR^yty<^z`(G
zC}ANggDlJcI;>VJT3TAr+S+R9>+Ad2>2%r{6W-<gsdSw4Kv`K?%h>(Vs`tvvyH+T2
z=gu8GdGZ8-K;WfA*L4uln#sw@E2X8S+~IJL*XyO~J$v|>GiUlZ=Udv^+A!mGgNV@I
z-@jA?K@gy->Pw~Z`FwH1!^67@3kyFDhr<?^%Y}r51c;*eXMSPfcWc+KZDWkh*45QL
zSGWICgY3I^hrYI2tsQ>9-x3ao0RTp$v0qV?k8*NynoK6s?2CHig)Um&IN@;k16h_^
zJ)YTuP$&pN5TI$AuerJThqSb`FGNxF?AWm*1{My7AqWCQQH<dTQ830>Y%vfBq?|v0
zzV*U|3zvwfAQ%jytZXY(RT<SZt;S}v)kh)`k0d?i=W@Al>((u7+qMlA6&2u|uY4=?
z_xHz|X<}kx%gM&Zn<kTqtcMR15s}Si``d1}w}->ww1tHQOixcQkB8N2g~eil*=$CA
zeLZwt$H2hAQi6ej0T7XT`}XY<B_$<~WLYKv)Oh?j5z&ax=d03nU3lhy5K-)W_Uu_~
z-n<#>)~&;_W5=Ryi@68@Ff=rTj*gDcQ&UqH01yCLpO+Wu?Ckt@ad9y#$~FqReBR#P
z&N4GI*{W5maPQu|*m^X9006;Y5K~iAxn8eVN;M_xHGB6CU$xn4+-~>5&d$zB&N=4h
z=Ai33IOm8&BG7dm08ml!K3%_loyy9}(A(RK(a}*b#$YfQmRuAF1fZ&_L6RhF-~QoW
z4JR7D7a02^6bij#Hk%C|k0)ri+oj#RcN<hy6?%GlV6j+`ot;gWFaIRE-81amxpRw(
zq6qu;)kuwvCqquB^Jf4N>6xb?%d*HhM^|r8;-l%Q=0GqQSG#||R9svv4Gs>5Y&M%z
zUS1xTmX;<s91b=yF@Zye4pDmg>+IS!I~y4pp^}mkwy~r{I&$R5+^)*XjR2+v0MIlI
zq9`)XIsHC4Y51k9EA2OjBenO}-XvYu<IQGss>9((dhp<ZCd;y#kdUDKc=4h_L~3Sc
zrt)xnTpk=8RES7^!?H#k9v+r9m6jS}5(R@nXqv_>IXM6k#fc)qi;GZI6@I^;GBPq)
zaZwRG9uF8}l%Jo^Zr-?o$B$=e{rUp-Zh1LoW@Zoyg{Y|LEtZ>`%g4vZmp+-bwY5l0
zOsw<yd~YuAY*kf}ot=&N_;`$sje&@emzRe?Ab|1lab#s>AtfaRE|&{_zaM#dc~Dgq
o&XJLM_sq<fHk)nkmH(;0Ka8BN{?)I3Jpcdz07*qoM6N<$f}u&57ytkO

literal 0
HcmV?d00001

diff --git a/cinelerra-5.1/plugins/theme_unflat/unflattheme.C b/cinelerra-5.1/plugins/theme_unflat/unflattheme.C
index 4a09eb82..7529c0de 100644
--- a/cinelerra-5.1/plugins/theme_unflat/unflattheme.C
+++ b/cinelerra-5.1/plugins/theme_unflat/unflattheme.C
@@ -839,6 +839,7 @@ void UNFLATTHEME::initialize()
 	splice_data = new_button("splice.png", editpanel_up, editpanel_hi, editpanel_dn,"splicebutton");
 	new_button("toclip.png", editpanel_up, editpanel_hi, editpanel_dn, "toclip");
 	new_button("goto.png", editpanel_up, editpanel_hi, editpanel_dn, "goto");
+	new_button("clapper.png", editpanel_up, editpanel_hi, editpanel_dn, "clapperbutton");
 	new_button("top_justify.png", editpanel_up, editpanel_hi, editpanel_dn, "top_justify");
 	new_button("undo.png", editpanel_up, editpanel_hi, editpanel_dn, "undo");
 	new_button("wrench.png", editpanel_up, editpanel_hi, editpanel_dn, "wrench");
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patchB b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patchB
new file mode 100644
index 00000000..cac742db
--- /dev/null
+++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patchB
@@ -0,0 +1,43 @@
+diff --git a/libswscale/x86/yuv_2_rgb.asm b/libswscale/x86/yuv_2_rgb.asm
+index 575a84d921..003dff1f25 100644
+--- a/libswscale/x86/yuv_2_rgb.asm
++++ b/libswscale/x86/yuv_2_rgb.asm
+@@ -268,9 +268,9 @@ cglobal %1_420_%2%3, GPR_num, GPR_num, reg_num, parameters
+     por    m2, m7
+     por    m1, m6          ; g5  b5  r6  g6  b6  r7  g7  b7  r8  g8  b8  r9  g9  b9  r10 g10
+     por    m2, m3          ; b10 r11 g11 b11 r12 g12 b12 r13 g13 b13 r14 g14 b14 r15 g15 b15
+-    mova [imageq], m0
+-    mova [imageq + 16], m1
+-    mova [imageq + 32], m2
++    movu [imageq], m0
++    movu [imageq + 16], m1
++    movu [imageq + 32], m2
+ %endif ; mmsize = 16
+ %else ; PACK RGB15/16/32
+     packuswb m0, m1
+@@ -300,10 +300,10 @@ cglobal %1_420_%2%3, GPR_num, GPR_num, reg_num, parameters
+     punpckhwd m_green, m_red
+     punpcklwd m5, m6
+     punpckhwd m_alpha, m6
+-    mova [imageq + 0], m_blue
+-    mova [imageq + 8  * time_num], m_green
+-    mova [imageq + 16 * time_num], m5
+-    mova [imageq + 24 * time_num], m_alpha
++    movu [imageq + 0], m_blue
++    movu [imageq + 8  * time_num], m_green
++    movu [imageq + 16 * time_num], m5
++    movu [imageq + 24 * time_num], m_alpha
+ %else ; PACK RGB15/16
+ %define depth 2
+ %if cpuflag(ssse3)
+@@ -342,8 +342,8 @@ cglobal %1_420_%2%3, GPR_num, GPR_num, reg_num, parameters
+     mova m2, m0
+     punpcklbw m0, m1
+     punpckhbw m2, m1
+-    mova [imageq], m0
+-    mova [imageq + 8 * time_num], m2
++    movu [imageq], m0
++    movu [imageq + 8 * time_num], m2
+ %endif ; PACK RGB15/16
+ %endif ; PACK RGB15/16/32
+ 
-- 
2.26.2