pluginclient cr=apply in option value textbox, add loop_mode for vwdw master
authorGood Guy <good1.2guy@gmail.com>
Sat, 4 Jul 2020 03:55:56 +0000 (21:55 -0600)
committerGood Guy <good1.2guy@gmail.com>
Sat, 4 Jul 2020 03:55:56 +0000 (21:55 -0600)
playback, add swap track up/dn, change reset_cache to use ref counts,
change gang_media,gang_chans pngs, add shift switch gang mode btn, tweak
mask_engine for high cpu count, change patchbay btn layout, fix track
redraw interrupted by index builder, fix scollable textbox resize
positioning, wsiwyg gang_master tweak.

257 files changed:
cinelerra-5.1/Cinelerra_factory
cinelerra-5.1/blds/PKGBUILD
cinelerra-5.1/blds/cinelerra.spec
cinelerra-5.1/blds/debian/changelog
cinelerra-5.1/blds/debian/control
cinelerra-5.1/cinelerra/aautomation.C
cinelerra-5.1/cinelerra/apatchgui.C
cinelerra-5.1/cinelerra/appearanceprefs.C
cinelerra-5.1/cinelerra/appearanceprefs.h
cinelerra-5.1/cinelerra/asset.C
cinelerra-5.1/cinelerra/asset.h
cinelerra-5.1/cinelerra/assetpopup.C
cinelerra-5.1/cinelerra/automation.h
cinelerra-5.1/cinelerra/automation.inc
cinelerra-5.1/cinelerra/awindowgui.C
cinelerra-5.1/cinelerra/awindowgui.h
cinelerra-5.1/cinelerra/batchrender.C
cinelerra-5.1/cinelerra/bdcreate.C
cinelerra-5.1/cinelerra/binfolder.C
cinelerra-5.1/cinelerra/cache.C
cinelerra-5.1/cinelerra/cache.h
cinelerra-5.1/cinelerra/commercials.C
cinelerra-5.1/cinelerra/cwindow.C
cinelerra-5.1/cinelerra/cwindowgui.C
cinelerra-5.1/cinelerra/cwindowgui.h
cinelerra-5.1/cinelerra/cwindowtool.C
cinelerra-5.1/cinelerra/dvdcreate.C
cinelerra-5.1/cinelerra/edit.C
cinelerra-5.1/cinelerra/edit.h
cinelerra-5.1/cinelerra/editlength.C
cinelerra-5.1/cinelerra/editpanel.C
cinelerra-5.1/cinelerra/editpanel.h
cinelerra-5.1/cinelerra/editpanel.inc
cinelerra-5.1/cinelerra/editpopup.C
cinelerra-5.1/cinelerra/edl.C
cinelerra-5.1/cinelerra/edl.h
cinelerra-5.1/cinelerra/edl.inc
cinelerra-5.1/cinelerra/edlsession.C
cinelerra-5.1/cinelerra/edlsession.h
cinelerra-5.1/cinelerra/edlsession.inc
cinelerra-5.1/cinelerra/ffmpeg.C
cinelerra-5.1/cinelerra/fileref.C
cinelerra-5.1/cinelerra/filexml.C
cinelerra-5.1/cinelerra/filexml.h
cinelerra-5.1/cinelerra/floatauto.C
cinelerra-5.1/cinelerra/floatautos.C
cinelerra-5.1/cinelerra/floatautos.h
cinelerra-5.1/cinelerra/indexfile.C
cinelerra-5.1/cinelerra/keyframe.C
cinelerra-5.1/cinelerra/keyframe.h
cinelerra-5.1/cinelerra/keyframegui.C
cinelerra-5.1/cinelerra/keyframepopup.C
cinelerra-5.1/cinelerra/keyframepopup.h
cinelerra-5.1/cinelerra/keyframes.C
cinelerra-5.1/cinelerra/keyframes.h
cinelerra-5.1/cinelerra/loadfile.C
cinelerra-5.1/cinelerra/localsession.C
cinelerra-5.1/cinelerra/mainmenu.C
cinelerra-5.1/cinelerra/mainmenu.h
cinelerra-5.1/cinelerra/maskengine.C
cinelerra-5.1/cinelerra/mbuttons.C
cinelerra-5.1/cinelerra/mbuttons.h
cinelerra-5.1/cinelerra/mixersalign.C
cinelerra-5.1/cinelerra/module.C
cinelerra-5.1/cinelerra/module.h
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/mwindow.h
cinelerra-5.1/cinelerra/mwindowedit.C
cinelerra-5.1/cinelerra/mwindowgui.C
cinelerra-5.1/cinelerra/mwindowmove.C
cinelerra-5.1/cinelerra/packagerenderer.C
cinelerra-5.1/cinelerra/patchbay.C
cinelerra-5.1/cinelerra/patchgui.C
cinelerra-5.1/cinelerra/patchgui.h
cinelerra-5.1/cinelerra/performanceprefs.h
cinelerra-5.1/cinelerra/playbackengine.C
cinelerra-5.1/cinelerra/playtransport.C
cinelerra-5.1/cinelerra/playtransport.h
cinelerra-5.1/cinelerra/plugin.C
cinelerra-5.1/cinelerra/pluginarray.C
cinelerra-5.1/cinelerra/pluginclient.C
cinelerra-5.1/cinelerra/pluginclient.h
cinelerra-5.1/cinelerra/plugindialog.C
cinelerra-5.1/cinelerra/pluginfclient.C
cinelerra-5.1/cinelerra/pluginlv2.C
cinelerra-5.1/cinelerra/pluginlv2.h
cinelerra-5.1/cinelerra/pluginserver.C
cinelerra-5.1/cinelerra/pluginserver.h
cinelerra-5.1/cinelerra/presets.C
cinelerra-5.1/cinelerra/proxy.C
cinelerra-5.1/cinelerra/proxy.h
cinelerra-5.1/cinelerra/recordableatracks.C
cinelerra-5.1/cinelerra/recordablevtracks.C
cinelerra-5.1/cinelerra/render.C
cinelerra-5.1/cinelerra/resourcethread.C
cinelerra-5.1/cinelerra/resourcethread.h
cinelerra-5.1/cinelerra/swindow.C
cinelerra-5.1/cinelerra/theme.C
cinelerra-5.1/cinelerra/theme.h
cinelerra-5.1/cinelerra/track.C
cinelerra-5.1/cinelerra/track.h
cinelerra-5.1/cinelerra/trackcanvas.C
cinelerra-5.1/cinelerra/tracklist.C
cinelerra-5.1/cinelerra/trackpopup.C
cinelerra-5.1/cinelerra/trackpopup.h
cinelerra-5.1/cinelerra/tracks.C
cinelerra-5.1/cinelerra/tracks.h
cinelerra-5.1/cinelerra/tracksedit.C
cinelerra-5.1/cinelerra/vautomation.C
cinelerra-5.1/cinelerra/vpatchgui.C
cinelerra-5.1/cinelerra/vwindowgui.C
cinelerra-5.1/cinelerra/vwindowgui.h
cinelerra-5.1/cinelerra/x10tv.C
cinelerra-5.1/cinelerra/zoombar.C
cinelerra-5.1/cinelerra/zoompanel.C
cinelerra-5.1/cinelerra/zwindow.C
cinelerra-5.1/cinelerra/zwindow.h
cinelerra-5.1/doc/shortcuts.html
cinelerra-5.1/guicast/bcmenuitem.C
cinelerra-5.1/guicast/bcmenuitem.h
cinelerra-5.1/guicast/bcresources.C
cinelerra-5.1/guicast/bcresources.h
cinelerra-5.1/guicast/bcsignals.C
cinelerra-5.1/guicast/bctextbox.C
cinelerra-5.1/guicast/filesystem.C
cinelerra-5.1/guicast/linklist.h
cinelerra-5.1/msg/txt
cinelerra-5.1/plugins/crikey/crikey.C
cinelerra-5.1/plugins/crikey/crikey.h
cinelerra-5.1/plugins/perspective/perspective.C
cinelerra-5.1/plugins/perspective/perspective.h
cinelerra-5.1/plugins/rotate/rotate.C
cinelerra-5.1/plugins/rotate/rotate.h
cinelerra-5.1/plugins/sketcher/sketcher.C
cinelerra-5.1/plugins/sketcher/sketcher.h
cinelerra-5.1/plugins/theme_blond/blondtheme.C
cinelerra-5.1/plugins/theme_blond/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_blond/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond_cv/blondcvtheme.C
cinelerra-5.1/plugins/theme_blond_cv/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond_cv/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond_cv/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond_cv/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond_cv/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_blond_cv/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond_cv/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond_cv/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blond_cv/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue/bluetheme.C
cinelerra-5.1/plugins/theme_blue/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_blue/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/bluedottheme.C
cinelerra-5.1/plugins/theme_blue_dot/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/patch_checked.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/patch_checkedhi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/patch_dn.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/patch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/patch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_blue_dot/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_blue_dot/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_bright/brighttheme.C
cinelerra-5.1/plugins/theme_bright/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_bright/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_bright/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_bright/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_bright/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_bright/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_bright/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_bright/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_bright/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_cakewalk/cakewalk.C
cinelerra-5.1/plugins/theme_cakewalk/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_cakewalk/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_cakewalk/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_cakewalk/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_cakewalk/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_cakewalk/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_cakewalk/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_cakewalk/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_cakewalk/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_hulk/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_hulk/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_hulk/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_hulk/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_hulk/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_hulk/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_hulk/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_hulk/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_hulk/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_hulk/hulktheme.C
cinelerra-5.1/plugins/theme_neophyte/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_neophyte/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_neophyte/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_neophyte/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_neophyte/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_neophyte/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_neophyte/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_neophyte/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_neophyte/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_neophyte/neophyte.C
cinelerra-5.1/plugins/theme_pinklady/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_pinklady/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_pinklady/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_pinklady/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_pinklady/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_pinklady/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_pinklady/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_pinklady/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_pinklady/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_pinklady/pinkladytheme.C
cinelerra-5.1/plugins/theme_suv/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_suv/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_suv/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_suv/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_suv/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_suv/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_suv/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_suv/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_suv/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_suv/suv.C
cinelerra-5.1/plugins/theme_unflat/data/gang0.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_unflat/data/gang1.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_unflat/data/gang2.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_unflat/data/masterpatch.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_unflat/data/patchbay_bg.png
cinelerra-5.1/plugins/theme_unflat/data/tumblepatch_bottom.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_unflat/data/tumblepatch_hi.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_unflat/data/tumblepatch_top.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_unflat/data/tumblepatch_up.png [new file with mode: 0644]
cinelerra-5.1/plugins/theme_unflat/unflattheme.C
cinelerra-5.1/plugins/titler/titler.C
cinelerra-5.1/plugins/tracer/tracer.C
cinelerra-5.1/plugins/tracer/tracer.h
cinelerra-5.1/po/es.po
cinelerra-5.1/po/fr.po
cinelerra-5.1/po/ru.po
cinelerra-5.1/tips/tips.es

index 4a4c0e5849c5e407d399d990291220de4ab27190..ee236e3479b72e05621d5c68f2dac14007520f3c 100644 (file)
@@ -94,5 +94,5 @@
 <KEYFRAME TITLE="gear360 sideways, 7k"><SPHERECAM ENABLED_0=1 FOV_0=194 CENTER_X_0=2.520000e+01 CENTER_Y_0=5.139998e+01 ROTATE_X_0=50 ROTATE_Y_0=50 ROTATE_Z_0=90 ENABLED_1=1 FOV_1=1.946000e+02 CENTER_X_1=7.499999e+01 CENTER_Y_1=5.079997e+01 ROTATE_X_1=0 ROTATE_Y_1=4.990000e+01 ROTATE_Z_1=-8.900002e+01 FEATHER=1 DRAW_GUIDES=0 MODE=1></KEYFRAME>
 </PLUGIN>
 <PLUGIN TITLE=F_drawgrid>
-<KEYFRAME TITLE=rule_of_3rds>&lt;F_DRAWGRID x=-1 y=-1 width=iw/3 w=iw/3 height=ih/3 h=ih/3 color=invert c=invert thickness=2 t=2&gt;</KEYFRAME>
+<KEYFRAME TITLE=rule_of_3rds><F_DRAWGRID x=-1 y=-1 width=iw/3 w=iw/3 height=ih/3 h=ih/3 color=invert c=invert thickness=2 t=2></KEYFRAME>
 </PLUGIN>
index a985c2de853d2a2d165a77ad6b129dfdde8cd215..74edc8fbf4ea41f01fd6806596e35d6deaae8425 100644 (file)
@@ -1,7 +1,7 @@
 # Maintainer: goodguy <lists.cinelerra-gg.org>
 pkgname=cin
 pkgver=5.1
-pkgrel=20200430
+pkgrel=20200630
 pkgdesc="Cinelerra git://git.cinelerra-gg.org/goodguy/cinelerra.git ($pkgrel)"
 arch=('x86_64')
 url="https://www.cinelerra-gg.org"
index 93061b9494fc398da0e90e991c9db1c453624b95..12f472e1725213bdf0483a718cba0844fa6dd650 100644 (file)
@@ -1,4 +1,4 @@
-%define ver 20200430
+%define ver 20200630
 %define cin cinelerra
 Summary: Multimedia Editing and construction
 
index 077a2fa0bb252d11ff096e38379240828a6081ec..9e3c47c055c935f5c2900bdaa4cea3f84bd6e726 100644 (file)
@@ -1,4 +1,4 @@
-cin (1:5.1.20200430) unstable; urgency=low
+cin (1:5.1.20200630) unstable; urgency=low
 
   [ guy goode ]
 
index ebb2fceff5a683dc96e84cf74be07feb724d038a..9067be592d61c424af56c45610bc1f52c14aa22d 100644 (file)
@@ -1,7 +1,7 @@
 Source: cin
 Section: video
 Priority: optional
-Standards-Version: 5.1.20200430
+Standards-Version: 5.1.20200630
 Maintainer: mailing list <cin@lists.cinelerra-gg.org>
 Homepage: https://www.cinelerra-gg.org/
 Build-Depends:
index 3b58cad65914515034410c0b2a08ee86822dc5a1..69c29a477fc3f0e739f3b04876cf0198ea2d7bb5 100644 (file)
@@ -48,6 +48,7 @@ void AAutomation::create_objects()
 
        autos[AUTOMATION_SPEED] = new FloatAutos(edl, track, 1.0);
        autos[AUTOMATION_SPEED]->create_objects();
+       ((FloatAutos*)autos[AUTOMATION_SPEED])->set_float_min(SPEED_MIN);
 
        autos[AUTOMATION_PAN] = new PanAutos(edl, track);
        autos[AUTOMATION_PAN]->create_objects();
index 0e8adca2f159ba7ce8b32a8ec473df6c8be9efa9..59d18244c34260c9f4d26a1874f86bc22234d112 100644 (file)
@@ -188,7 +188,7 @@ void APatchGUI::update_faders(float v)
        float change = v - current->get_value();
        current->set_value(v);
 
-       if( track->gang && track->record )
+       if( track->is_ganged() && track->is_armed() )
                patchbay->synchronize_faders(change, TRACK_AUDIO, track);
        mwindow->undo->update_undo_after(_("fade"), LOAD_AUTOMATION);
        change_source = 0;
index cb0279af049029c02861cfc183700e85052175e0..1c6be93189ed3c0467c92317da382b2d08c5e1fc 100644 (file)
@@ -178,18 +178,17 @@ void AppearancePrefs::create_objects()
                x2, y, xS(80), yS(24), clr_color, clr_alpha));
        draw_3d_border(x2-2,y-2, xS(80)+4,xS(24)+4, 1);
        cwdw_bg_color->create_objects();
+       x2 += cwdw_bg_color->get_w();
        y += ys35;
 
-       x = x1;
-       add_subwindow(title = new BC_Title(x, y, _("YUV color space:")));
-       x += title->get_w() + margin;
+       add_subwindow(title = new BC_Title(x1, y, _("YUV color space:")));
+       x = x2 - xS(120);
        add_subwindow(yuv_color_space = new YuvColorSpace(x, y, pwindow));
        yuv_color_space->create_objects();
        y += yuv_color_space->get_h() + ys5;
 
-       x = x1;
-       add_subwindow(title = new BC_Title(x, y, _("YUV color range:")));
-       x += title->get_w() + margin;
+       add_subwindow(title = new BC_Title(x1, y, _("YUV color range:")));
+       x = x2 - xS(100);
        add_subwindow(yuv_color_range = new YuvColorRange(x, y, pwindow));
        yuv_color_range->create_objects();
        y += yuv_color_range->get_h() + ys35;
index 8c3ddaecc6b596035ff0c7c1df83c31214af0190..e7ef3426f1a5d2071ed0872eeb5fc68dddbf1ad5 100644 (file)
@@ -337,8 +337,8 @@ public:
 
 class YuvColorSpace : public BC_PopupMenu
 {
-       static const char *color_space[3];
 public:
+       static const char *color_space[3];
        YuvColorSpace(int x, int y, PreferencesWindow *pwindow);
        ~YuvColorSpace();
 
@@ -359,8 +359,8 @@ public:
 
 class YuvColorRange : public BC_PopupMenu
 {
-       static const char *color_range[2];
 public:
+       static const char *color_range[2];
        YuvColorRange(int x, int y, PreferencesWindow *pwindow);
        ~YuvColorRange();
 
index fe169cbcd0d2623332b85f0135350ff39d72d388..751660ad9cc06aec8a70d82f890b2f258d2c59b2 100644 (file)
@@ -165,6 +165,7 @@ void Asset::reset_video()
        actual_width = width = 0;
        actual_height = height = 0;
        proxy_scale = 0; // not a proxy
+       proxy_edl = 0; // not proxy from edl
        video_length = 0;
        single_frame = 0;
        vmpeg_cmodel = BC_YUV420P;
@@ -226,6 +227,7 @@ void Asset::copy_format(Asset *asset, int do_index)
        actual_width = asset->actual_width;
        actual_height = asset->actual_height;
        proxy_scale = asset->proxy_scale;
+       proxy_edl = asset->proxy_edl;
        strcpy(vcodec, asset->vcodec);
        strcpy(acodec, asset->acodec);
 
@@ -470,6 +472,7 @@ int Asset::read_video(FileXML *file)
        height = file->tag.get_property("HEIGHT", height);
        width = file->tag.get_property("WIDTH", width);
        proxy_scale = file->tag.get_property("PROXY_SCALE", 0);
+       proxy_edl = file->tag.get_property("PROXY_EDL", 0);
        layers = file->tag.get_property("LAYERS", layers);
        program = file->tag.get_property("PROGRAM", program);
 // This is loaded from the index file after the EDL but this
@@ -638,6 +641,7 @@ int Asset::write_video(FileXML *file)
        file->tag.set_property("HEIGHT", height);
        file->tag.set_property("WIDTH", width);
        file->tag.set_property("PROXY_SCALE", proxy_scale);
+       file->tag.set_property("PROXY_EDL", proxy_edl);
        file->tag.set_property("LAYERS", layers);
        file->tag.set_property("PROGRAM", program);
        file->tag.set_property("FRAMERATE", frame_rate);
@@ -741,6 +745,7 @@ void Asset::load_defaults(BC_Hash *defaults,
                actual_height = GET_DEFAULT("ACTUAL_HEIGHT", actual_height);
                actual_width = GET_DEFAULT("ACTUAL_WIDTH", actual_width);
                proxy_scale = GET_DEFAULT("PROXY_SCALE", proxy_scale);
+               proxy_edl = GET_DEFAULT("PROXY_SCALE", proxy_edl);
                program = GET_DEFAULT("PROGRAM", program);
                layers = GET_DEFAULT("LAYERS", layers);
                if(EQUIV(frame_rate, 0)) frame_rate = GET_DEFAULT("FRAMERATE", frame_rate);
@@ -944,6 +949,7 @@ void Asset::save_defaults(BC_Hash *defaults,
                UPDATE_DEFAULT("ACTUAL_HEIGHT", actual_height);
                UPDATE_DEFAULT("ACTUAL_WIDTH", actual_width);
                UPDATE_DEFAULT("PROXY_SCALE", proxy_scale);
+               UPDATE_DEFAULT("PROXY_EDL", proxy_edl);
                UPDATE_DEFAULT("PROGRAM", program);
                UPDATE_DEFAULT("LAYERS", layers);
                UPDATE_DEFAULT("FRAMERATE", frame_rate);
@@ -989,9 +995,9 @@ 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"
+       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, video_length,
+               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,"   mov_sphere=%d jpeg_sphere=%d\n", mov_sphere, jpeg_sphere);
index 92b15794ced82f6f31a2144c87ad78c114564cf4..ce922c22c1e61aaed9c35a73f0a348d975b74527 100644 (file)
@@ -147,8 +147,8 @@ public:
 
        int actual_width, actual_height;
        int width, height;
-// scale factor or 0 if not proxy
-       int proxy_scale;
+// scale factor or 0 if not proxy, proxy_edl if proxyed from nested_edl
+       int proxy_scale, proxy_edl;
 // String or FourCC describing compression
        char vcodec[BCTEXTLEN];
 
index 56832ca9100e8e994cbf8e0f5446a2b0783b588e..bc4281642a3563acd1bfb4c671c72ae77d4a0849 100644 (file)
@@ -951,8 +951,8 @@ int SnapshotMenuItem::handle_event()
                command.realtime = 0;
 
                RenderEngine render_engine(0, preferences, 0, 0);
-               CICache video_cache(preferences);
-               render_engine.set_vcache(&video_cache);
+               CICache *video_cache = new CICache(preferences);
+               render_engine.set_vcache(video_cache);
                render_engine.arm_command(&command);
 
                double position = edl->local_session->get_selectionstart(1);
@@ -962,6 +962,7 @@ int SnapshotMenuItem::handle_event()
                if( !ret )
                        ret = file.write_video_buffer(1);
                file.close_file();
+               video_cache->remove_user();
        }
        if( !ret ) {
                asset->folder_no = AW_MEDIA_FOLDER;
index 615a9d55197f3b19cda11d376bb4803c4d6f1e28..e25b6376c9d1d26720c57d50d405029a32f4b0ae 100644 (file)
                CLAMP(value, 0, 100);                                   \
        if (autogrouptype == AUTOGROUPTYPE_ZOOM && value < 0)           \
                value = 0;                                              \
-       else if (autogrouptype == AUTOGROUPTYPE_SPEED && value < 0.001) \
-               value = 0.001;
+       else if (autogrouptype == AUTOGROUPTYPE_SPEED && value < SPEED_MIN) \
+               value = SPEED_MIN;
 
 #define AUTOMATIONVIEWCLAMPS(value, autogrouptype)                     \
        if (autogrouptype == AUTOGROUPTYPE_ZOOM && value < 0)           \
                value = 0;                                              \
-       else if (autogrouptype == AUTOGROUPTYPE_SPEED && value < 0)     \
-               value = 0;
+       else if (autogrouptype == AUTOGROUPTYPE_SPEED && value < SPEED_MIN)     \
+               value = SPEED_MIN;
 
 
 class Automation
index f573c3ecce2d48b64a8c2dc4cfd2860de972676e..31f58a663016158b04d187f74e74a286e8fadf80 100644 (file)
@@ -87,4 +87,6 @@ enum
        AUTOMATION_TYPE_PAN
 };
 
+#define SPEED_MIN 0.005
+
 #endif
index 1aa57e35b5ebf3eeb42ede875813adb50ec7a509..d71d1588715e1e58e4d0f69028d38c5ba95e3edc 100644 (file)
@@ -29,8 +29,9 @@
 #include "awindow.h"
 #include "awindowgui.h"
 #include "bccmodels.h"
-#include "bcsignals.h"
 #include "bchash.h"
+#include "bcsignals.h"
+#include "bctimer.h"
 #include "binfolder.h"
 #include "cache.h"
 #include "cstrdup.h"
@@ -114,6 +115,8 @@ AssetVIcon::AssetVIcon(AssetPicon *picon, int w, int h, double framerate, int64_
 
 AssetVIcon::~AssetVIcon()
 {
+       if( picon->gui->vicon_thread->solo == this )
+               picon->gui->vicon_thread->solo = 0;
        picon->gui->vicon_thread->del_vicon(this);
        delete temp;
 }
@@ -162,29 +165,33 @@ VFrame *AssetVIcon::frame()
        }
        if( seq_no >= images.size() ) {
                MWindow *mwindow = picon->mwindow;
-               File *file = mwindow->video_cache->check_out(asset, mwindow->edl, 1);
-               if( !file ) {
-                       broken = 1;
-                       return 0;
-               }
                if( temp && (temp->get_w() != asset->width || temp->get_h() != asset->height) ) {
                        delete temp;  temp = 0;
                }
                if( !temp )
                        temp = new VFrame(0, -1, asset->width, asset->height, BC_RGB888, -1);
-               while( seq_no >= images.size() ) {
-                       mwindow->video_cache->check_in(asset);
-                       Thread::yield();
-                       file = mwindow->video_cache->check_out(asset, mwindow->edl, 0);
-                       if( !file ) { usleep(1000);  continue; }
-                       file->set_layer(0);
+               File *file = mwindow->video_cache->check_out(asset, mwindow->edl, 1);
+               if( !file ) { broken = 1;  return 0; }
+               Timer timer;
+               while( file && seq_no >= images.size() && !avt->interrupted ) {
                        int64_t pos = images.size() / picon->gui->vicon_thread->refresh_rate * frame_rate;
                        file->set_video_position(pos,0);
+                       file->set_layer(0);
                        if( file->read_frame(temp) ) temp->clear_frame();
                        add_image(temp, vw, vh, vicon_cmodel);
+                       mwindow->video_cache->check_in(asset);
+                       if( timer.get_difference() > 500 ) return 0;
+                       Thread::yield();
+                       file = mwindow->video_cache->check_out(asset, mwindow->edl, 0);
+                       for( int retries=10; !file && --retries>=0; usleep(1000) ) {
+                               if( avt->interrupted ) return 0;
+                               file = mwindow->video_cache->check_out(asset, mwindow->edl, 0);
+                       }
+                       if( !file ) return 0;
                }
                mwindow->video_cache->check_in(asset);
        }
+       if( seq_no >= images.size() ) return 0;
        return *images[seq_no];
 }
 
@@ -534,7 +541,7 @@ void AssetViewPopup::draw_vframe(VFrame *vframe)
        double total_length = edl->tracks->total_length();
        if( !total_length ) total_length = 1;
        for( Track *track=edl->tracks->first; track!=0; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                for( Edit *edit=track->edits->first; edit!=0; edit=edit->next ) {
                        Indexable *indexable = (Indexable *)edit->asset;
                        if( !indexable ) indexable = (Indexable *)edit->nested_edl;
@@ -681,11 +688,13 @@ ViewPopup *AssetVIconThread::new_view_window(ViewPopup *vpopup)
        return av_popup;
 }
 
-void AssetVIconThread::close_view_popup()
+void AssetVIconThread::stop_vicon_drawing(int wait)
 {
        stop_drawing();
-       drawing_started(); // waits for draw lock
-       drawing_stopped();
+       if( wait ) {
+               drawing_started(); // waits for draw lock
+               drawing_stopped();
+       }
 }
 
 
@@ -1695,17 +1704,12 @@ int AWindowGUI::start_vicon_drawing()
        return 1;
 }
 
-int AWindowGUI::stop_vicon_drawing()
+int AWindowGUI::stop_vicon_drawing(int wait)
 {
-       if( !vicon_thread->interrupted )
-               vicon_thread->stop_drawing();
+       vicon_thread->stop_vicon_drawing(wait);
        return 0;
 }
 
-void AWindowGUI::close_view_popup()
-{
-       vicon_thread->close_view_popup();
-}
 
 VFrame *AssetPicon::get_vicon_frame()
 {
@@ -2207,14 +2211,16 @@ void AWindowGUI::sort_folders()
        update_assets();
 }
 
-EDL *AWindowGUI::collect_proxy(Indexable *indexable)
+EDL *AWindowGUI::collect_proxy(Asset *proxy_asset)
 {
-       Asset *proxy_asset = (Asset *)indexable;
        char path[BCTEXTLEN];
        int proxy_scale = mwindow->edl->session->proxy_scale;
        ProxyRender::from_proxy_path(path, proxy_asset, proxy_scale);
-       Asset *unproxy_asset = mwindow->edl->assets->get_asset(path);
-       if( !unproxy_asset || !unproxy_asset->layers ) return 0;
+       Indexable *unproxy_idxbl =
+               proxy_asset->proxy_edl ?
+                       (Indexable *) mwindow->edl->get_nested_edl(path) :
+                       (Indexable *) mwindow->edl->assets->get_asset(path);
+       if( !unproxy_idxbl || !unproxy_idxbl->get_video_layers() ) return 0;
 // make a clip from proxy video tracks and unproxy audio tracks
        EDL *proxy_edl = new EDL(mwindow->edl);
        proxy_edl->create_objects();
@@ -2223,7 +2229,7 @@ EDL *AWindowGUI::collect_proxy(Indexable *indexable)
        strcpy(proxy_edl->local_session->clip_title, path);
        strcpy(proxy_edl->local_session->clip_notes, _("Proxy clip"));
        proxy_edl->session->video_tracks = proxy_asset->layers;
-       proxy_edl->session->audio_tracks = unproxy_asset->channels;
+       proxy_edl->session->audio_tracks = unproxy_idxbl->get_audio_channels();
        proxy_edl->create_default_tracks();
        double length = proxy_asset->frame_rate > 0 ?
                ( proxy_asset->video_length >= 0 ?
@@ -2237,11 +2243,15 @@ EDL *AWindowGUI::collect_proxy(Indexable *indexable)
                if( current->data_type != TRACK_VIDEO ) continue;
                current->insert_asset(proxy_asset, 0, length, 0, vtrack++);
        }
-       length = (double)unproxy_asset->audio_length / unproxy_asset->sample_rate;
+       int64_t samples = unproxy_idxbl->get_audio_samples();
+       int sample_rate = unproxy_idxbl->get_sample_rate();
+       length = sample_rate > 0 ? (double)samples / sample_rate : 0;
        current = proxy_edl->tracks->first;
        for( int atrack=0; current; current=NEXT ) {
                if( current->data_type != TRACK_AUDIO ) continue;
-               current->insert_asset(unproxy_asset, 0, length, 0, atrack++);
+               Asset *asset = unproxy_idxbl->is_asset ? (Asset *)unproxy_idxbl : 0;
+               EDL *nested_edl = unproxy_idxbl->is_asset ? 0 : (EDL *)unproxy_idxbl;
+               current->insert_asset(asset, nested_edl, length, 0, atrack++);
        }
        proxy_edl->folder_no = AW_PROXY_FOLDER;
        return proxy_edl;
@@ -2257,7 +2267,7 @@ void AWindowGUI::collect_assets(int proxy)
                Indexable *indexable = result->indexable;
                if( proxy && indexable && indexable->is_asset &&
                    indexable->folder_no == AW_PROXY_FOLDER ) {
-                       EDL *drag_edl = collect_proxy(indexable);
+                       EDL *drag_edl = collect_proxy((Asset*)indexable);
                        if( drag_edl ) mwindow->session->drag_clips->append(drag_edl);
                        continue;
                }
@@ -2819,8 +2829,8 @@ int AWindowAssets::handle_event()
                break;
        }
        if( !vwindow || !vwindow->is_running() ) return 1;
-       if( proxy && picon_idxbl ) {
-               picon_edl = gui->collect_proxy(picon_idxbl);
+       if( proxy && picon_idxbl && picon_idxbl->is_asset ) {
+               picon_edl = gui->collect_proxy((Asset*)picon_idxbl);
                picon_idxbl = 0;
        }
 
index 6004247d4f158ec25264b05ff304e8cb6fe22f7a..aa182f9ecf57eb1c6aef9206ba8b400bc3be16ad 100644 (file)
@@ -208,9 +208,9 @@ public:
        void set_view_popup(AssetVIcon *v, int draw_mode);
        void set_view_popup(AssetVIcon *v);
        ViewPopup *new_view_window(ViewPopup *popup);
+       void stop_vicon_drawing(int wait=0);
        void drawing_started();
        void drawing_stopped();
-       void close_view_popup();
 
        AWindowGUI *gui;
        int draw_mode;
@@ -271,7 +271,7 @@ public:
        int drag_stop();
 // Collect items into the drag vectors of MainSession
        void collect_assets(int proxy=0);
-       EDL *collect_proxy(Indexable *indexable);
+       EDL *collect_proxy(Asset *asset);
        void create_persistent_folder(ArrayList<BC_ListBoxItem*> *output,
                int do_audio,
                int do_video,
@@ -288,8 +288,7 @@ public:
        int save_defaults(BC_Hash *defaults);
        int load_defaults(BC_Hash *defaults);
        int start_vicon_drawing();
-       int stop_vicon_drawing();
-       void close_view_popup();
+       int stop_vicon_drawing(int wait=0);
        void update_picon(Indexable *indexable);
        int cycle_assetlist_format();
        void hide_tip_info();
index 9703361cb8b04167e26dc8e21c7f55a78e808b55..0694cc2fd445fc6232625f33ad13177e47f6b102 100644 (file)
@@ -121,6 +121,8 @@ BatchRenderJob *BatchRenderJob::copy()
 void BatchRenderJob::load(FileXML *file)
 {
        int result = 0;
+       char job_title[BCSTRLEN];
+       strcpy(job_title, file->tag.title);
 
        enabled = file->tag.get_property("ENABLED", enabled);
        farmed = file->tag.get_property("FARMED", farmed);
@@ -138,7 +140,7 @@ void BatchRenderJob::load(FileXML *file)
 // coding maintenance.  The defaults must now be stuffed into the XML for
 // unique storage.
                        BC_Hash defaults;
-                       defaults.load_string(file->read_text());
+                       defaults.load_string(file->read_text(job_title));
                        asset->load_defaults(&defaults,
                                "", 0, 1, 0, 0, 0);
                }
@@ -1196,6 +1198,7 @@ void BatchRenderLoadList::run()
 
        int result2 = filewindow.run_window();
        if( !result2 ) {
+               thread->gui->lock_window("BatchRenderLoadList::run");
                strcpy(thread->batch_path, filewindow.get_submitted_path());
                thread->gui->batch_path->update(thread->batch_path);
                thread->mwindow->defaults->update("DEFAULT_BATCHLOADPATH", thread->batch_path);
@@ -1203,6 +1206,7 @@ void BatchRenderLoadList::run()
                thread->gui->create_list(1);
                thread->current_job = 0;
                thread->gui->change_job();
+               thread->gui->unlock_window();
        }
 
        startup_lock->lock("BatchRenderLoadList::run");
index f13642c856cbcecd4cd6c08f41f81787221dfcfc..93794d516f842acea5469b703e9f36b3c1170afc 100644 (file)
@@ -364,7 +364,7 @@ void CreateBD_Thread::handle_close_event(int result)
                Tracks *tracks = mwindow->edl->tracks;
                for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
                        if( vtrk->data_type != TRACK_VIDEO ) continue;
-                       if( !vtrk->record ) continue;
+                       if( !vtrk->is_armed() ) continue;
                        vtrk->expand_view = 1;
                        PluginSet *plugin_set = new PluginSet(mwindow->edl, vtrk);
                        vtrk->plugin_set.append(plugin_set);
@@ -874,7 +874,7 @@ insert_video_plugin(const char *title, KeyFrame *default_keyframe)
        Tracks *tracks = mwindow->edl->tracks;
        for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
                if( vtrk->data_type != TRACK_VIDEO ) continue;
-               if( !vtrk->record ) continue;
+               if( !vtrk->is_armed() ) continue;
                vtrk->expand_view = 1;
                PluginSet *plugin_set = new PluginSet(mwindow->edl, vtrk);
                vtrk->plugin_set.append(plugin_set);
@@ -898,7 +898,7 @@ resize_tracks()
        if( trk_h < bd_height ) trk_h = bd_height;
        for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
                if( vtrk->data_type != TRACK_VIDEO ) continue;
-               if( !vtrk->record ) continue;
+               if( !vtrk->is_armed() ) continue;
                vtrk->track_w = trk_w;
                vtrk->track_h = trk_h;
        }
@@ -933,7 +933,7 @@ option_presets()
        max_w = 0;  max_h = 0;
        int has_deinterlace = 0, has_scale = 0;
        for( Track *trk=tracks->first; trk; trk=trk->next ) {
-               if( !trk->record ) continue;
+               if( !trk->is_armed() ) continue;
                Edits *edits = trk->edits;
                switch( trk->data_type ) {
                case TRACK_VIDEO:
@@ -973,7 +973,7 @@ option_presets()
                if( max_h != bd_height ) use_resize_tracks = 1;
        }
        for( Track *trk=tracks->first; trk && !use_resize_tracks; trk=trk->next ) {
-               if( !trk->record ) continue;
+               if( !trk->is_armed() ) continue;
                switch( trk->data_type ) {
                case TRACK_VIDEO:
                        if( trk->track_w != max_w ) use_resize_tracks = 1;
index 4dfc2f89a2145e7d5cfa08c69010b68e2e546952..ff4d0ba6a940e1d42aaa3d3d85f6daa58c1958ba 100644 (file)
@@ -393,8 +393,8 @@ double BinFolders::matches_indexable(int folder, Indexable *idxbl)
        BinFolder *bin_folder = 0;
        while( --k>=0 && (bin_folder=get(k)) && bin_folder->awindow_folder!=folder );
        if( k < 0 ) return -1;
-       if( bin_folder->is_clips && idxbl->is_asset ) return -1;
-       if( !bin_folder->is_clips && !idxbl->is_asset ) return -1;
+       if( bin_folder->is_clips && idxbl->folder_no != AW_CLIP_FOLDER ) return -1;
+       if( !bin_folder->is_clips && idxbl->folder_no != AW_MEDIA_FOLDER ) return -1;
        return bin_folder->matches_indexable(idxbl);
 }
 
index 63bb4a0de4b32e9e5b9dcb0480c4f751c0f933c2..80bf347b677a49d9aee95d011514719aa814f799 100644 (file)
@@ -37,7 +37,7 @@
 
 // edl came from a command which won't exist anymore
 CICache::CICache(Preferences *preferences)
- : List<CICacheItem>()
+ : Garbage("CICache"), List<CICacheItem>()
 {
        this->preferences = preferences;
        edl = 0;
@@ -69,11 +69,11 @@ File* CICache::check_out(Asset *asset, EDL *edl, int block)
        CICacheItem *current = 0;
        long tid = (long)Thread::get_self();
        if( !tid ) tid = 1;
+       total_lock->lock("CICache::check_out");
+       add_user();
 
-       while(1)
-       {
+       while( users > 1 ) {
                File *file = 0;
-               total_lock->lock("CICache::check_out");
 // Scan directory for item
                current = first;
                while(current && strcmp(current->asset->path, asset->path) != 0)
@@ -81,14 +81,10 @@ File* CICache::check_out(Asset *asset, EDL *edl, int block)
                if(!current) { // Create new item
                        current = new CICacheItem(this, edl, asset);
                        append(current);  current->checked_out = tid;
-                       file = current->file;
                        total_lock->unlock();
+                       file = current->file;
                        int result = file->open_file(preferences, asset, 1, 0);
-                       if( result ) {
-SET_TRACE
-                               delete file;
-                               file = 0;
-                       }
+                       if( result ) { delete file; file = 0; }
                        total_lock->lock("CICache::check_out 2");
                        if( !file ) {
                                remove_pointer(current);
@@ -101,7 +97,7 @@ SET_TRACE
                }
                else {
                        file = current->file;
-                       if(!current->checked_out) {
+                       if( !current->checked_out ) {
 // Return existing/new item
                                current->Garbage::add_user();
                                current->age = EDL::next_id();
@@ -112,12 +108,21 @@ SET_TRACE
                        else
                                current = 0;
                }
-               total_lock->unlock();
-               if(current || !file || !block) break;
+               if( current || !file || !block ) break;
 // Try again after blocking
+               total_lock->unlock();
                check_out_lock->lock("CICache::check_out");
+               total_lock->lock("CICache::check_out");
+       }
+
+// cache deleted during checkout, destroy this
+       if( users == 1 ) {
+               remove_user();
+               return 0;
        }
 
+       remove_user();
+       total_lock->unlock();
 //printf("check out %p %lx %s\n", current, tid, asset->path);
        return current ? current->file : 0;
 }
@@ -148,42 +153,47 @@ int CICache::check_in(Asset *asset)
 
 void CICache::remove_all()
 {
-       CICacheItem *current, *temp;
        List<CICacheItem> removed;
-       total_lock->lock("CICache::remove_all");
-       for(current=first; current; current=temp)
-       {
-               temp = NEXT;
-// Must not be checked out because we need the pointer to check back in.
-// Really need to give the user the CacheItem.
-               if(!current->checked_out)
-               {
-//printf("CICache::remove_all: %s\n", current->asset->path);
-                       remove_pointer(current);
-                       removed.append(current);
+       for(;;) {
+               total_lock->lock("CICache::remove_all");
+               CICacheItem *current = first;
+               while( current ) {
+                       CICacheItem *next_item = current->next;
+                       if( !current->checked_out ) {
+                               remove_pointer(current);
+                               removed.append(current);
+                       }
+                       current = next_item;
                }
-       }
-       total_lock->unlock();
-       while( (current=removed.first) != 0 )
-       {
-               removed.remove_pointer(current);
-               current->Garbage::remove_user();
+               total_lock->unlock();
+               while( removed.first ) {
+                       CICacheItem *current = removed.first;
+                       removed.remove_pointer(current);
+                       current->Garbage::remove_user();
+               }
+               if( !first ) break;
+               check_out_lock->lock();
        }
 }
 
 int CICache::delete_entry(char *path)
 {
-       total_lock->lock("CICache::delete_entry");
-       CICacheItem *current = first;
-       while( current && strcmp(current->asset->path, path) !=0 )
-               current = NEXT;
-       if(current && !current->checked_out)
-               remove_pointer(current);
-       else
-               current = 0;
-//printf("CICache::delete_entry: %s\n", current->asset->path);
+       CICacheItem *current = 0;
+       for( ;; ) {
+               total_lock->lock("CICache::delete_entry");
+               current = first;
+               while( current && strcmp(current->asset->path, path) !=0 )
+                       current = NEXT;
+               if( !current ) break;
+               if( !current->checked_out ) {
+                       remove_pointer(current);
+                       break;
+               }
+               total_lock->unlock();
+               check_out_lock->lock();
+       }
        total_lock->unlock();
-       if(current)
+       if( current )
                current->Garbage::remove_user();
        return 0;
 }
@@ -247,12 +257,18 @@ int CICache::delete_oldest()
        CICacheItem *oldest = 0;
 // at least 2
        if( first != last ) {
-               CICacheItem *current = first;
-               oldest = current;
-               while( (current=NEXT) != 0 ) {
+               oldest = first;
+               CICacheItem *current = oldest->next;
+               while( current ) {
                        if( current->age < oldest->age )
                                oldest = current;
+                       current = current->next;
                }
+       }
+// settle for just deleting one frame
+       else if( first )
+               result = first->file->delete_oldest();
+       if( oldest ) {
 // Got the oldest file.  Try requesting cache purge from it.
                if( oldest->file )
                        oldest->file->purge_cache();
@@ -262,9 +278,6 @@ int CICache::delete_oldest()
                else
                        oldest = 0;
        }
-// settle for just deleting one frame
-       else if( first )
-               result = first->file->delete_oldest();
        total_lock->unlock();
        if( oldest ) {
                oldest->Garbage::remove_user();
@@ -273,16 +286,16 @@ int CICache::delete_oldest()
        return result;
 }
 
-void CICache::dump()
+void CICache::dump(FILE *fp)
 {
        CICacheItem *current;
        total_lock->lock("CICache::dump");
-       printf("CICache::dump total size %jd\n", get_memory_usage(0));
+       fprintf(fp, "CICache::dump total size %jd\n", get_memory_usage(0));
        for(current = first; current; current = NEXT)
        {
-               printf("cache item %p asset %p %s age=%d\n",
-                       current, current->asset,
-                       current->asset->path, current->age);
+               fprintf(fp, "cache item %p asset %p %s age=%d checked_out=%p\n",
+                       current, current->asset, current->asset->path,
+                       current->age, (void*)current->checked_out);
        }
        total_lock->unlock();
 }
index fde997a50289c41ee76f725681d6d2ad12eddc94..15329e6964199024c96ba8c1174f062ca0925bf2 100644 (file)
@@ -61,7 +61,7 @@ private:
        CICache *cache;
 };
 
-class CICache : public List<CICacheItem>
+class CICache : public Garbage, public List<CICacheItem>
 {
 public:
        CICache(Preferences *preferences);
@@ -104,10 +104,7 @@ public:
 // deletes oldest assets until under the memory limit
        int age();
 
-
-       void dump();
-
-
+       void dump(FILE *fp);
 private:
 
 // for deleting items
index a3461b6db942768b0c8218e330d5ab290cff1f14..b93bb4e3911e61b4225b9a85752b8dcdb2ecb474 100644 (file)
@@ -551,7 +551,7 @@ scan_audio(int vstream, double start, double end)
        Tracks *tracks = mwindow->edl->tracks;
        for(Track *atrk=tracks->first; !cancelled && atrk; atrk=atrk->next) {
                if( atrk->data_type != TRACK_AUDIO ) continue;
-               if( !atrk->record ) continue;
+               if( !atrk->is_armed() ) continue;
                Edits *edits = atrk->edits;  Edit *next = 0;
                for( Edit *edit=edits->first; !cancelled && edit; edit=next ) {
                        next = edit->next;
@@ -592,7 +592,7 @@ scan_video()
        Tracks *tracks = mwindow->edl->tracks;
        for( Track *vtrk=tracks->first; !cancelled && vtrk; vtrk=vtrk->next) {
                if( vtrk->data_type != TRACK_VIDEO ) continue;
-               if( !vtrk->record ) continue;
+               if( !vtrk->is_armed() ) continue;
                Edits *edits = vtrk->edits;  Edit *next = 0;
                for( Edit *edit=edits->first; !cancelled && edit; edit=next ) {
                        next = edit->next;
index 4328162356a290db813da21f4faf84f50ef7fb80..5c2ed20785be62ff25f1efbef060320dfdb89f67 100644 (file)
@@ -124,7 +124,7 @@ Track* CWindow::calculate_affected_track()
        Track *track = mwindow->edl->tracks->first;
        for( ; track; track=track->next ) {
                if( track->data_type != TRACK_VIDEO ) continue;
-               if( track->record ) break;
+               if( track->is_armed() ) break;
        }
        return track;
 }
@@ -134,7 +134,7 @@ Track* CWindow::calculate_mask_track()
        Track *track = mwindow->edl->tracks->first;
        for( ; track; track=track->next ) {
                if( track->data_type != TRACK_VIDEO ) continue;
-               if( track->record && track->get_id() == mask_track_id ) break;
+               if( track->is_armed() && track->get_id() == mask_track_id ) break;
        }
        return track;
 }
index 97ee1ceb260b02849b6f7e0c3545c92674cfc748..7f5ddf5fa87ef189fc4d7e05474ce94129e77e78 100644 (file)
@@ -760,7 +760,8 @@ CWindowEditing::CWindowEditing(MWindow *mwindow, CWindow *cwindow)
                0, // use_commerical
                0, // use_goto
                1, // use_clk2play
-               1) // use_scope
+               1, // use_scope
+               0) // use_gang_tracks
 {
        this->mwindow = mwindow;
        this->cwindow = cwindow;
@@ -825,6 +826,7 @@ void panel_btn(set_editing_mode,(int mode), set_editing_mode(mode))
 void panel_btn(set_auto_keyframes,(int v), set_auto_keyframes(v))
 void panel_btn(set_span_keyframes,(int v), set_span_keyframes(v))
 void panel_btn(set_labels_follow_edits,(int v), set_labels_follow_edits(v))
+void panel_btn(set_gang_tracks,(int v), set_gang_tracks(v))
 
 
 CWindowMeters::CWindowMeters(MWindow *mwindow,
index df1e01c806fba5f1bb000dd859265b2a353266a2..0d79d8707f67dbc0aa411fe3a3eb81751ce23022 100644 (file)
@@ -186,6 +186,7 @@ public:
        void panel_set_auto_keyframes(int v);
        void panel_set_span_keyframes(int v);
        void panel_set_labels_follow_edits(int v);
+       void panel_set_gang_tracks(int v);
 
        MWindow *mwindow;
        CWindow *cwindow;
index f3fd68e330660b86d1d207f78ed20d2244c38a2c..55d64b4504a871d9588508618ed8fd17618f640b 100644 (file)
@@ -1740,7 +1740,7 @@ int CWindowMaskOnTrack::handle_event()
        if( k >= 0 ) {
                track_item = (CWindowMaskItem *)track_items[k];
                Track *track = track_item ? mwindow->edl->tracks->get_track_by_id(track_item->id) : 0;
-               if( track && track->record ) track_id = track->get_id();
+               if( track && track->is_armed() ) track_id = track->get_id();
        }
        else
                track_id = mwindow->cwindow->mask_track_id;
@@ -1764,7 +1764,7 @@ void CWindowMaskOnTrack::update_items()
        for( Track *track=mwindow->edl->tracks->first; track; track=track->next ) {
                if( track->data_type != TRACK_VIDEO ) continue;
                MaskAutos *mask_autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
-               int color = !track->record ? RED : mask_autos->first ?  high_color : -1;
+               int color = !track->is_armed() ? RED : mask_autos->first ?  high_color : -1;
                MaskAuto *mask_auto = (MaskAuto*)mask_autos->default_auto;
                for( int i=0; color<0 && i<mask_auto->masks.size(); ++i )
                        if( mask_auto->masks[i]->points.size() > 0 ) color = high_color;
@@ -1812,7 +1812,7 @@ int CWindowMaskTrackTumbler::do_event(int dir)
                        track_item = items[0];
        }
        Track *track = track_item ? mwindow->edl->tracks->get_track_by_id(track_item->id) : 0;
-       int track_id = track_item && track && track->record ? track_item->id : -1;
+       int track_id = track_item && track && track->is_armed() ? track_item->id : -1;
        gui->mask_on_track->set_back_color(track_id >= 0 ?
                gui->get_resources()->text_background :
                gui->get_resources()->text_background_disarmed);
@@ -3021,7 +3021,7 @@ void CWindowMaskGUI::update()
 //printf("CWindowMaskGUI::update 1\n");
        get_keyframe(track, autos, keyframe, mask, point, 0);
        mwindow->cwindow->mask_track_id = track ? track->get_id() : -1;
-       mask_on_track->set_back_color(!track || track->record ?
+       mask_on_track->set_back_color(!track || track->is_armed() ?
                get_resources()->text_background :
                get_resources()->text_background_disarmed);
        mask_on_track->update_items();
index adeb8df59b2a0e3a5e9436afe003bfb346835647..4c8ab188aadc2518a88e6c7ff8938e4b7bb2aab6 100644 (file)
@@ -486,7 +486,7 @@ void CreateDVD_Thread::handle_close_event(int result)
                Tracks *tracks = mwindow->edl->tracks;
                for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
                        if( vtrk->data_type != TRACK_VIDEO ) continue;
-                       if( !vtrk->record ) continue;
+                       if( !vtrk->is_armed() ) continue;
                        vtrk->expand_view = 1;
                        PluginSet *plugin_set = new PluginSet(mwindow->edl, vtrk);
                        vtrk->plugin_set.append(plugin_set);
@@ -1015,7 +1015,7 @@ insert_video_plugin(const char *title, KeyFrame *default_keyframe)
        Tracks *tracks = mwindow->edl->tracks;
        for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
                if( vtrk->data_type != TRACK_VIDEO ) continue;
-               if( !vtrk->record ) continue;
+               if( !vtrk->is_armed() ) continue;
                vtrk->expand_view = 1;
                PluginSet *plugin_set = new PluginSet(mwindow->edl, vtrk);
                vtrk->plugin_set.append(plugin_set);
@@ -1039,7 +1039,7 @@ resize_tracks()
        if( trk_h < dvd_height ) trk_h = dvd_height;
        for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
                if( vtrk->data_type != TRACK_VIDEO ) continue;
-               if( !vtrk->record ) continue;
+               if( !vtrk->is_armed() ) continue;
                vtrk->track_w = trk_w;
                vtrk->track_h = trk_h;
        }
@@ -1072,7 +1072,7 @@ option_presets()
        max_w = 0;  max_h = 0;
        int has_deinterlace = 0, has_scale = 0;
        for( Track *trk=tracks->first; trk; trk=trk->next ) {
-               if( !trk->record ) continue;
+               if( !trk->is_armed() ) continue;
                Edits *edits = trk->edits;
                switch( trk->data_type ) {
                case TRACK_VIDEO:
@@ -1111,7 +1111,7 @@ option_presets()
                if( max_h != dvd_height ) use_resize_tracks = 1;
        }
        for( Track *trk=tracks->first; trk && !use_resize_tracks; trk=trk->next ) {
-               if( !trk->record ) continue;
+               if( !trk->is_armed() ) continue;
                switch( trk->data_type ) {
                case TRACK_VIDEO:
                        if( trk->track_w != max_w ) use_resize_tracks = 1;
index f06194f8a1de251b2472662176155ac76a1efeaa..f538a503e43de737614bcf25eeb6dc64075e18a4 100644 (file)
@@ -234,8 +234,23 @@ void Edit::insert_transition(char *title)
 
 void Edit::detach_transition()
 {
-       if(transition) delete transition;
+       delete transition;
        transition = 0;
+       if( edl->session->gang_tracks == GANG_NONE ) return;
+       double pos = track->from_units(startproject);
+       Track *current = edl->tracks->first;
+       for( ; current; current=current->next ) {
+               if( current == track ) continue;
+               if( current->data_type != track->data_type ) continue;
+               if( !current->armed_gang(track) ) continue;
+               int64_t track_pos = current->to_units(pos, 1);
+               Edit *edit = current->edits->editof(track_pos, PLAY_FORWARD, 0);
+               if( !edit ) continue;
+               double edit_pos = track->from_units(edit->startproject);
+               if( !edl->equivalent(pos, edit_pos) ) continue;
+               delete edit->transition;
+               edit->transition = 0;
+       }
 }
 
 int Edit::silence()
@@ -247,12 +262,36 @@ int Edit::silence()
 
 void Edit::set_selected(int v)
 {
-       if( group_id )
-               edl->tracks->set_group_selected(group_id, v);
+       if( !group_id ) {
+               if( v < 0 ) v = !is_selected ? 1 : 0;
+               int gang = edl->session->gang_tracks != GANG_NONE ? 1 : 0;
+               select_affected_edits(v, gang);
+       }
        else
-               is_selected = v >= 0 ? v : !is_selected ? 1 : 0;
+               edl->tracks->set_group_selected(group_id, v);
 }
 
+// gang<0: rest of tracks, gang==0: this track, gang>0: to next master
+void Edit::select_affected_edits(int v, int gang)
+{
+       is_selected = v;
+       if( !gang ) return;
+       double position = track->from_units(startproject);
+       for( Track *current=track->next; current; current=current->next ) {
+               if( gang > 0 && current->master ) break;
+               if( !current->is_armed() ) continue;
+               for( Edit *edit=current->edits->first; edit; edit=edit->next ) {
+                       if( edit->silence() ) continue;
+                       double start = current->from_units(edit->startproject);
+                       if( edl->equivalent(start, position) ) {
+                               edit->is_selected = v;
+                               break;
+                       }
+               }
+       }
+}
+
+
 void Edit::copy_from(Edit *edit)
 {
        this->orig_id = edit->orig_id;
index 290bf63e5b46800aa1fa7dbb712c4b95cce4cb4c..95dff778d00883fb3fb16d55da2c4a86fa35948f 100644 (file)
@@ -95,6 +95,7 @@ public:
 // Determine if silence depending on existance of asset or plugin title
        virtual int silence();
        void set_selected(int v);
+       void select_affected_edits(int v, int gang);
 
 // Media edit information
 // Units are native units for the track.
index 188d415aacfc54b02998a08d463e7fd6ca13b30f..070681e8e3cd4061573755802df74c92e39dc8c8 100644 (file)
@@ -64,7 +64,7 @@ void EditLengthThread::start(Edit *edit)
                        track && !got_it;
                        track = track->next)
                {
-                       if(track->record)
+                       if(track->is_armed())
                        {
                                int64_t start_units = track->to_units(start, 0);
                                int64_t end_units = track->to_units(end, 0);
index 11e1fc5c84609142bdc9af982999c03c3cedf395..41394277fc1de8aa66199a9567005c8e821c5089 100644 (file)
@@ -75,7 +75,8 @@ EditPanel::EditPanel(MWindow *mwindow,
        int use_commercial,
        int use_goto,
        int use_clk2play,
-       int use_scope)
+       int use_scope,
+       int use_gang_tracks)
 {
        this->window_id = window_id;
        this->editing_mode = editing_mode;
@@ -98,6 +99,7 @@ EditPanel::EditPanel(MWindow *mwindow,
        this->use_goto = use_goto;
        this->use_clk2play = use_clk2play;
        this->use_scope = use_scope;
+       this->use_gang_tracks = use_gang_tracks;
 
        this->x = x;
        this->y = y;
@@ -117,6 +119,7 @@ EditPanel::EditPanel(MWindow *mwindow,
        this->nextlabel = 0;
        this->prevedit = 0;
        this->nextedit = 0;
+       this->gang_tracks = 0;
        this->undo = 0;
        this->redo = 0;
        this->meter_panel = 0;
@@ -157,6 +160,7 @@ void EditPanel::update()
                        mwindow->edl->session->vwindow_click2play ;
                click2play->set_value(value);
        }
+       if( gang_tracks ) gang_tracks->update(mwindow->edl->session->gang_tracks);
        if( meters ) {
                if( is_cwindow() ) {
                        meters->update(mwindow->edl->session->cwindow_meter);
@@ -318,6 +322,12 @@ void EditPanel::create_buttons()
                scope_dialog = new EditPanelScopeDialog(mwindow, this);
        }
 
+       if( use_gang_tracks ) {
+               gang_tracks = new EditPanelGangTracks(mwindow, this, x1, y1-yS(1));
+               subwindow->add_subwindow(gang_tracks);
+               x1 += gang_tracks->get_w();
+       }
+
        if( use_meters ) {
                if( meter_panel ) {
                        meters = new MeterShow(mwindow, meter_panel, x1, y1);
@@ -1304,3 +1314,55 @@ int EditPanelScope::handle_event()
        return 1;
 }
 
+const char *EditPanelGangTracks::gang_tips[TOTAL_GANGS] = {
+       N_("Currently: Gang None\n  Click to: Gang Channels"),
+       N_("Currently: Gang Channels\n  Click to: Gang Media"),
+       N_("Currently: Gang Media\n  Click to: Gang None"),
+};
+
+EditPanelGangTracks::EditPanelGangTracks(MWindow *mwindow, EditPanel *panel,
+               int x, int y)
+ : BC_Button(x, y, get_images(mwindow))
+{
+       this->mwindow = mwindow;
+       this->panel = panel;
+       int gang = mwindow->edl->session->gang_tracks;
+       set_tooltip(_(gang_tips[gang]));
+}
+
+EditPanelGangTracks::~EditPanelGangTracks()
+{
+}
+
+VFrame **EditPanelGangTracks::gang_images[TOTAL_GANGS];
+
+VFrame **EditPanelGangTracks::get_images(MWindow *mwindow)
+{
+       gang_images[GANG_NONE] = mwindow->theme->get_image_set("gang0");
+       gang_images[GANG_MEDIA] = mwindow->theme->get_image_set("gang1");
+       gang_images[GANG_CHANNELS] = mwindow->theme->get_image_set("gang2");
+       int gang = mwindow->edl->session->gang_tracks;
+       return gang_images[gang];
+}
+
+void EditPanelGangTracks::update(int gang)
+{
+       set_images(gang_images[gang]);
+       draw_face();
+       set_tooltip(_(gang_tips[gang]));
+}
+
+int EditPanelGangTracks::handle_event()
+{
+       int gang = mwindow->edl->session->gang_tracks;
+       if( !shift_down() ) {
+               if( ++gang > GANG_MEDIA ) gang = GANG_NONE;
+       }
+       else {
+               if( --gang < GANG_NONE ) gang = GANG_MEDIA;
+       }
+       update(gang);
+       panel->panel_set_gang_tracks(gang);
+       return 1;
+}
+
index b81d9fed0d385d4e654d424435fec4e7407cb313..9adbaf62b567be40dc2c015ff9f7ebf45a211b4b 100644 (file)
@@ -379,6 +379,21 @@ public:
        VFrame *output_frame;
 };
 
+class EditPanelGangTracks : public BC_Button
+{
+       static VFrame **gang_images[TOTAL_GANGS];
+       static const char *gang_tips[TOTAL_GANGS];
+public:
+       EditPanelGangTracks(MWindow *mwindow, EditPanel *panel, int x, int y);
+       ~EditPanelGangTracks();
+       VFrame **get_images(MWindow *mwindow);
+       void update(int gang);
+       int handle_event();
+       EditPanel *panel;
+       MWindow *mwindow;
+};
+
+
 class EditPanelScope : public BC_Toggle
 {
 public:
@@ -412,7 +427,8 @@ public:
                int use_commerical,
                int use_goto,
                int use_clk2play,
-               int use_scope);
+               int use_scope,
+               int use_gang_tracks);
        ~EditPanel();
 
        void set_meters(MeterPanel *meter_panel);
@@ -450,6 +466,7 @@ public:
        virtual void panel_set_auto_keyframes(int v) = 0;
        virtual void panel_set_span_keyframes(int v) = 0;
        virtual void panel_set_labels_follow_edits(int v) = 0;
+       virtual void panel_set_gang_tracks(int mode) = 0;
 
        MWindow *mwindow;
        BC_WindowBase *subwindow;
@@ -475,6 +492,7 @@ public:
        int use_goto;
        int use_clk2play;
        int use_scope;
+       int use_gang_tracks;
 
        EditFit *fit;
        EditFitAutos *fit_autos;
@@ -498,6 +516,7 @@ public:
        EditNextLabel *nextlabel;
        EditPrevEdit *prevedit;
        EditNextEdit *nextedit;
+       EditPanelGangTracks *gang_tracks;
        EditUndo *undo;
        EditRedo *redo;
        MeterShow *meters;
index f991013528f886b64554ddcb90ee5b17fafec0e5..5b24a831cf6bc7e779015bee45a8a5fefee8a8b0 100644 (file)
@@ -57,5 +57,6 @@ class LockLabelsButton;
 class EditPanelScopeGUI;
 class EditPanelScopeDialog;
 class EditPanelScope;
+class EditPanelMashMixers;
 
 #endif
index 315b4078d42455b88c7aa2a57e54870b5d9cccb4..45d7d87a0a696e918e9fb337d97de799858c1b27 100644 (file)
@@ -139,7 +139,7 @@ int EditPopupOpenEDL::handle_event()
                eprintf(_("Edit is not EDL: %s"), edit_title);
                return 1;
        }
-       mwindow->stack_push(edl, idxbl);
+       mwindow->stack_push(edl, idxbl, edit);
        return 1;
 }
 
index 6739dec89dab284da8dec9be63a6128e5e6fe0c0..cb080aca25103b8349062e069f7200cff3891614 100644 (file)
@@ -437,7 +437,7 @@ int EDL::copy_assets(int copy_flags, double start, double end,
        if( (copy_flags & COPY_USED_ASSETS) ) {
 // Copy just the ones being used.
                for( current = tracks->first; current; current = NEXT ) {
-                       if( !current->record ) continue;
+                       if( !current->is_armed() ) continue;
                        current->copy_assets(start, end, &asset_list);
                }
        }
@@ -601,7 +601,7 @@ void EDL::copy_indexables(EDL *edl)
        }
 }
 
-EDL *EDL::new_nested_edl(EDL *edl, const char *path)
+EDL *EDL::new_nested_clip(EDL *edl, const char *path)
 {
        EDL *nested = new EDL;  // no parent for nested edl
        nested->create_objects();
@@ -614,19 +614,14 @@ EDL *EDL::new_nested_edl(EDL *edl, const char *path)
        return nested;
 }
 
-EDL *EDL::get_nested_edl()
+EDL *EDL::get_nested_edl(const char *path)
 {
-       Track *track = tracks->first;
-       Edit *edit = track ? track->edits->first : 0;
-       EDL *nested = edit && !edit->next && !edit->asset ? edit->nested_edl : 0;
-       while( nested && (track=track->next)!=0 ) {
-               Edit *edit = track->edits->first;
-               if( !edit || edit->next ||
-                   ( edit->nested_edl != nested &&
-                     strcmp(edit->nested_edl->path, nested->path) ) )
-                       nested = 0;
+       for( int i=0; i<nested_edls.size(); ++i ) {
+               EDL *nested_edl = nested_edls[i];
+               if( !strcmp(path, nested_edl->path) )
+                       return nested_edl;
        }
-       return nested;
+       return 0;
 }
 
 
@@ -642,8 +637,8 @@ void EDL::create_nested(EDL *nested)
 {
        int video_tracks = 0, audio_tracks = 0;
        for( Track *track=nested->tracks->first; track!=0; track=track->next ) {
-               if( track->data_type == TRACK_VIDEO && track->record ) ++video_tracks;
-               if( track->data_type == TRACK_AUDIO && track->record ) ++audio_tracks;
+               if( track->data_type == TRACK_VIDEO && track->play ) ++video_tracks;
+               if( track->data_type == TRACK_AUDIO && track->play ) ++audio_tracks;
        }
 // renderengine properties
        if( video_tracks > 0 )
@@ -1049,6 +1044,7 @@ int EDL::get_tracks_height(Theme *theme)
 {
        int total_pixels = 0;
        for( Track *current=tracks->first; current; current=NEXT ) {
+               if( current->is_hidden() ) continue;
                total_pixels += current->vertical_span(theme);
        }
        return total_pixels;
@@ -1058,6 +1054,7 @@ int64_t EDL::get_tracks_width()
 {
        int64_t total_pixels = 0;
        for( Track *current=tracks->first; current; current=NEXT ) {
+               if( current->is_hidden() ) continue;
                int64_t pixels = current->horizontal_span();
                if( pixels > total_pixels ) total_pixels = pixels;
        }
@@ -1233,7 +1230,7 @@ void EDL::insert_asset(Asset *asset,
        }
 
        for( ; current && vtrack<layers; current=NEXT ) {
-               if( !current->record || current->data_type != TRACK_VIDEO ) continue;
+               if( !current->is_armed() || current->data_type != TRACK_VIDEO ) continue;
                current->insert_asset(new_asset, new_nested_edl,
                        length, position, vtrack++);
        }
@@ -1255,7 +1252,7 @@ void EDL::insert_asset(Asset *asset,
 
        current = tracks->first;
        for( ; current && atrack < channels; current=NEXT ) {
-               if( !current->record || current->data_type != TRACK_AUDIO ) continue;
+               if( !current->is_armed() || current->data_type != TRACK_AUDIO ) continue;
                current->insert_asset(new_asset, new_nested_edl,
                        length, position, atrack++);
        }
@@ -1309,7 +1306,7 @@ void EDL::get_shared_plugins(Track *source,
        int data_type)
 {
        for( Track *track=tracks->first; track; track=track->next ) {
-               if( track->record && omit_recordable ) continue;
+               if( track->is_armed() && omit_recordable ) continue;
                if( track == source || track->data_type != data_type ) continue;
                for( int i=0; i<track->plugin_set.size(); ++i ) {
                        Plugin *plugin = track->get_current_plugin(
@@ -1326,7 +1323,7 @@ void EDL::get_shared_tracks(Track *track,
        int omit_recordable, int data_type)
 {
        for( Track *current=tracks->first; current; current=NEXT ) {
-               if( omit_recordable && current->record ) continue;
+               if( omit_recordable && current->is_armed() ) continue;
                if( current == track || current->data_type != data_type ) continue;
                module_locations->append(new SharedLocation(tracks->number_of(current), 0));
        }
@@ -1599,7 +1596,7 @@ double EDL::next_edit(double position)
 
 // Test for edit handles after position
        for( Track *track=tracks->first; track; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
                        double edit_end = track->from_units(edit->startproject + edit->length);
                        Units::fix_double(&edit_end);
@@ -1623,7 +1620,7 @@ double EDL::prev_edit(double position)
 
 // Test for edit handles before cursor position
        for( Track *track=tracks->first; track; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
                        double edit_end = track->from_units(edit->startproject);
                        Units::fix_double(&edit_end);
@@ -1869,7 +1866,7 @@ EDL *EDL::selected_edits_to_clip(int packed,
        double start = DBL_MAX, end = DBL_MIN;
        Track *first_track=0, *last_track = 0;
        for( Track *track=tracks->first; track; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                int empty = 1;
                for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
                        if( !edit->is_selected || edit->silence() ) continue;
@@ -1895,7 +1892,7 @@ EDL *EDL::selected_edits_to_clip(int packed,
        new_edl->session->video_tracks = 0;
        new_edl->session->audio_tracks = 0;
        for( Track *track=tracks->first; track; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                if( first_track ) {
                        if( first_track != track ) continue;
                        first_track = 0;
@@ -2045,7 +2042,7 @@ void EDL::paste_edits(EDL *clip, Track *first_track, double position, int overwr
                first_track = tracks->first;
        Track *src = clip->tracks->first;
        for( Track *track=first_track; track && src; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                int64_t pos = track->to_units(position, 0);
                if( edit_edits ) {
                        for( Edit *edit=src->edits->first; edit; edit=edit->next ) {
@@ -2211,7 +2208,7 @@ int EDL::collect_effects(EDL *&group)
                Edit *edit = track->edits->first;
                while( edit && !edit->is_selected ) edit = edit->next;
                if( !edit ) continue;
-               if( !track->record ) { ret = COLLECT_EFFECTS_RECORD;  break; } 
+               if( !track->is_armed() ) { ret = COLLECT_EFFECTS_RECORD;  break; } 
                Track *new_track = 0;
                edl_shared *location = 0;
                int64_t start_pos = edit->startproject;
@@ -2278,6 +2275,8 @@ int EDL::collect_effects(EDL *&group)
        }
        if( !ret )
                group = new_edl;
+       else
+               new_edl->remove_user();
        return ret;
 }
 
@@ -2298,7 +2297,7 @@ int EDL::insert_effects(EDL *group, Track *first_track)
                Edit *edit = track->edits->first;
                while( edit && !edit->is_selected ) edit = edit->next;
                if( !edit ) continue;
-               if( !track->record ) return INSERT_EFFECTS_RECORD;
+               if( !track->is_armed() ) return INSERT_EFFECTS_RECORD;
                if( track->data_type != new_track->data_type ) return INSERT_EFFECTS_TYPE;
                int gtrk = group->tracks->number_of(new_track);
                int trk = tracks->number_of(track);
@@ -2321,7 +2320,7 @@ int EDL::insert_effects(EDL *group, Track *first_track)
        new_track = group->tracks->first;
        track = first_track;
        for( ; track && new_track; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                Edit *edit = track->edits->first;
                while( edit && !edit->is_selected ) edit = edit->next;
                if( !edit ) continue;
index 80aadb2c4f708a07387ff688adc5e40af32a0a2d..5d08285bd5ddd2abf726c73c68618a55c009b6de 100644 (file)
@@ -197,8 +197,8 @@ public:
        int copy_assets(int copy_flags, double start, double end,
                FileXML *file, const char *output_path);
        void copy_indexables(EDL *edl);
-       EDL *new_nested_edl(EDL *edl, const char *path);
-       EDL *get_nested_edl();
+       EDL *new_nested_clip(EDL *edl, const char *path);
+       EDL *get_nested_edl(const char *path);
        EDL *create_nested_clip(EDL *nested);
        void create_nested(EDL *nested);
        void overwrite_clip(EDL *clip);
index 9f08c29b6dce0764f88dd62c52764248bbfbd9d5..ff56d686877ff6244529ea407acd07044304a67a 100644 (file)
@@ -158,6 +158,7 @@ class EDL;
 #define MIN_ZOOM_TIME 1
 #define MAX_ZOOM_TIME 0x100000
 #define DEFAULT_ZOOM_TIME 1024
+#define DEFAULT_ZOOM_TRACK 64
 #define MIN_AMP_ZOOM 8
 #define MAX_AMP_ZOOM 8192
 #define MIN_TRACK_ZOOM 8
index 90a5319c5b9a37011ed6179525fc9bc244c2c68e..74eb3471d944ea832c0165c19bc98cf2952e2838 100644 (file)
@@ -129,6 +129,7 @@ EDLSession::EDLSession(EDL *edl)
        scrub_speed = 2.;
        show_assets = 1;
        show_titles = 1;
+       gang_tracks = GANG_NONE;
        si_useduration = 1;
        si_duration = 3;
        test_playback_edits = 1;
@@ -324,6 +325,7 @@ int EDLSession::load_defaults(BC_Hash *defaults)
 
        show_assets = defaults->get("SHOW_ASSETS", 1);
        show_titles = defaults->get("SHOW_TITLES", 1);
+       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);
        nudge_format = defaults->get("NUDGE_FORMAT", 1);
@@ -462,6 +464,7 @@ int EDLSession::save_defaults(BC_Hash *defaults)
        defaults->update("SI_DURATION",si_duration);
        defaults->update("SHOW_ASSETS", show_assets);
        defaults->update("SHOW_TITLES", show_titles);
+       defaults->update("GANG_TRACKS", gang_tracks);
 //     defaults->update("TEST_PLAYBACK_EDITS", test_playback_edits);
        defaults->update("TIME_FORMAT", time_format);
        defaults->update("NUDGE_FORMAT", nudge_format);
@@ -646,6 +649,7 @@ int EDLSession::load_xml(FileXML *file,
                safe_regions = file->tag.get_property("SAFE_REGIONS", safe_regions);
                show_assets = file->tag.get_property("SHOW_ASSETS", 1);
                show_titles = file->tag.get_property("SHOW_TITLES", 1);
+               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);
                nudge_format = file->tag.get_property("NUDGE_FORMAT", nudge_format);
@@ -715,6 +719,7 @@ int EDLSession::save_xml(FileXML *file)
        file->tag.set_property("SAFE_REGIONS", safe_regions);
        file->tag.set_property("SHOW_ASSETS", show_assets);
        file->tag.set_property("SHOW_TITLES", show_titles);
+       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("NUDGE_FORMAT", nudge_format);
@@ -891,6 +896,7 @@ int EDLSession::copy(EDLSession *session)
        si_duration = session->si_duration;
        show_assets = session->show_assets;
        show_titles = session->show_titles;
+       gang_tracks = session->gang_tracks;
        test_playback_edits = session->test_playback_edits;
        time_format = session->time_format;
        nudge_format = session->nudge_format;
index aa74a1da4aab7ee54a338238d4bc030f13799fb5..b2994f181e602f07d20449b44c2601c37a4994c0 100644 (file)
@@ -203,6 +203,7 @@ public:
        int show_assets;
 // Show titles in resources
        int show_titles;
+       int gang_tracks;
 // Test for data before rendering a track
        int test_playback_edits;
 // Format to display times in
index 6b4b5a056aa7b61a452a0badb9ee5e534ceab0a1..da9cac9c33ae439cf043edff180c948f44a38400 100644 (file)
 
 #define INIT_ATRANSITION "Crossfade"
 #define INIT_VTRANSITION "Dissolve"
+#define GANG_NONE  0
+#define GANG_CHANNELS 1
+#define GANG_MEDIA 2
+#define TOTAL_GANGS 3
 
 class EDLSession;
 
index 58d280c00edf60315dd93d383e05196d9ee04a49..23549f9a0c603a82175ffd1f1176f8d59193b19a 100644 (file)
@@ -285,6 +285,7 @@ FFStream::FFStream(FFMPEG *ffmpeg, AVStream *st, int fidx)
 
 FFStream::~FFStream()
 {
+       frm_lock->lock("FFStream::~FFStream");
        if( reading > 0 || writing > 0 ) avcodec_close(avctx);
        if( avctx ) avcodec_free_context(&avctx);
        if( fmt_ctx ) avformat_close_input(&fmt_ctx);
@@ -295,6 +296,7 @@ FFStream::~FFStream()
        if( frame ) av_frame_free(&frame);
        if( fframe ) av_frame_free(&fframe);
        if( probe_frame ) av_frame_free(&probe_frame);
+       frm_lock->unlock();
        delete frm_lock;
        if( stats_fp ) fclose(stats_fp);
        if( stats_in ) av_freep(&stats_in);
@@ -428,14 +430,14 @@ int FFStream::decode_activate()
                                        avctx->thread_count = ffmpeg->ff_cpus();
                                ret = avcodec_open2(avctx, decoder, &copts);
                        }
+                       AVFrame *hw_frame = 0;
                        if( ret >= 0 && hw_type != AV_HWDEVICE_TYPE_NONE ) {
-                               AVFrame *frame = av_frame_alloc();
-                               if( !frame ) {
+                               if( !(hw_frame=av_frame_alloc()) ) {
                                        fprintf(stderr, "FFStream::decode_activate: av_frame_alloc failed\n");
                                        ret = AVERROR(ENOMEM);
                                }
                                if( ret >= 0 )
-                                       ret = decode(frame);
+                                       ret = decode(hw_frame);
                        }
                        if( ret < 0 && hw_type != AV_HWDEVICE_TYPE_NONE ) {
                                ff_err(ret, "HW device init failed, using SW decode.\nfile:%s\n",
@@ -444,7 +446,7 @@ int FFStream::decode_activate()
                                avcodec_free_context(&avctx);
                                av_buffer_unref(&hw_device_ctx);
                                hw_device_ctx = 0;
-                               av_frame_free(&frame);
+                               av_frame_free(&hw_frame);
                                hw_type = AV_HWDEVICE_TYPE_NONE;
                                int flags = AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY;
                                int idx = st->index;
@@ -454,7 +456,7 @@ int FFStream::decode_activate()
                                ret = 0;
                                continue;
                        }
-                       probe_frame = frame;
+                       probe_frame = hw_frame;
                        if( ret >= 0 )
                                reading = 1;
                        else
@@ -491,7 +493,7 @@ int FFStream::decode(AVFrame *frame)
        }
        int ret = 0;
        int retries = MAX_RETRY;
-
+       frm_lock->lock("FFStream::decode");
        while( ret >= 0 && !flushed && --retries >= 0 ) {
                if( need_packet ) {
                        if( (ret=read_packet()) < 0 ) break;
@@ -514,6 +516,7 @@ int FFStream::decode(AVFrame *frame)
                        flushed = st_eof();
                }
        }
+       frm_lock->unlock();
 
        if( retries < 0 ) {
                fprintf(stderr, "FFStream::decode: Retry limit\n");
@@ -726,6 +729,7 @@ int FFStream::seek(int64_t no, double rate)
        tstmp = av_rescale_q(tstmp, time_base, AV_TIME_BASE_Q);
        idx = -1;
 #endif
+       frm_lock->lock("FFStream::seek");
        av_frame_free(&probe_frame);
        avcodec_flush_buffers(avctx);
        avformat_flush(fmt_ctx);
@@ -758,7 +762,9 @@ int FFStream::seek(int64_t no, double rate)
                        if( pkt_ts >= tstmp ) break;
                }
                if( retry < 0 ) {
-                       fprintf(stderr,"FFStream::seek: retry limit, pos=%jd tstmp=%jd\n",pos,tstmp);
+                       ff_err(AVERROR(EIO), "FFStream::seek: %s\n"
+                               " retry limit, pos=%jd tstmp=%jd, ",
+                               ffmpeg->fmt_ctx->url, pos, tstmp);
                        ret = -1;
                }
                if( ret < 0 ) break;
@@ -772,6 +778,7 @@ int FFStream::seek(int64_t no, double rate)
                        break;
                }
        }
+       frm_lock->unlock();
        if( ret < 0 ) {
 printf("** seek fail %jd, %jd\n", pos, tstmp);
                seeked = need_packet = 0;
index ab8ecd7f05acd7357c27658947df85bf9876a467..ade91c481613cbf6f9f698935248ebac22c4eeef 100644 (file)
@@ -101,8 +101,8 @@ int FileREF::close_file()
        ref = 0;
        delete render_engine;  render_engine = 0;
        delete command;  command = 0;
-       delete acache;   acache = 0;
-       delete vcache;   vcache = 0;
+       if( acache ) { acache->remove_user();  acache = 0; }
+       if( vcache ) { vcache->remove_user();  vcache = 0; }
        delete temp;     temp = 0;
        for( int i=0; i<MAX_CHANNELS; ++i ) {
                delete samples[i];  samples[i] = 0;
index e045a5321b27cec19568cca901113662ebb0d181..e4e281466dff68b862f85224eb0e6596023ca51e 100644 (file)
@@ -452,8 +452,9 @@ int FileXML::append_text(const char *text, long len)
 
 char* FileXML::get_data()
 {
+       char *data = (char *)buffer->cstr();
        long ofs = buffer->itell();
-       return (char *)buffer->pos(ofs);
+       return data + ofs;
 }
 char* FileXML::string()
 {
@@ -465,23 +466,40 @@ long FileXML::length()
        return buffer->otell();
 }
 
-char* FileXML::read_text()
+char* FileXML::read_text(const char *tag_title)
 {
+       if( !tag_title ) tag_title = tag.title;
        int ch = buffer->next();
 // filter out first char is new line
        if( ch == '\n' ) ch = buffer->next();
-       long ipos = buffer->itell()-1;
+       long ipos = buffer->itell();
+       if( ch >= 0 ) --ipos;
+       long pos = ipos;
 // scan for delimiter
-       while( ch >= 0 && ch != left_delm ) ch = buffer->next();
-       long pos = buffer->itell()-1;
-       if( ch >= 0 ) buffer->iseek(pos);
+       while( ch >= 0 ) {
+               while( ch >= 0 && ch != left_delm ) ch = buffer->next();
+               if( ch < 0 ) break;
+               pos = buffer->itell()-1;
+               if( (ch = buffer->next()) != '/' ) continue;
+               const char *cp = tag_title;
+               while( (ch=buffer->next()) >= 0 && ch == *cp ) ++cp;
+               if( ch < 0 ) break;
+               if( *cp ) continue;
+               while( ch == ' ' ) ch = buffer->next();
+               if( ch == right_delm ) break;
+       }
+       if( ch < 0 )
+               pos = buffer->itell();
+       buffer->iseek(pos);
        long len = pos - ipos;
        if( len >= output_length ) {
                delete [] output;
                output_length = len+1;
                output = new char[output_length];
        }
-       decode(output,(const char *)buffer->pos(ipos), len);
+       if( len > 0 )
+               decode(output,(const char *)buffer->pos(ipos), len);
+       output[len] = 0;
        return output;
 }
 
index eb0b514a6777056c0a7309b3aa302dd30322c755..a8bcc736fc385daf572e2178390ef56e0f9f4835 100644 (file)
@@ -136,7 +136,7 @@ public:
        int append_data(const char *text);
        int append_data(const char *text, long len);
 
-       char *read_text();
+       char *read_text(const char *tag_title=0);
        int read_data_until(const char *tag_end, XMLBuffer *xbfr, int skip=0);
        int read_text_until(const char *tag_end, XMLBuffer *xbfr, int skip=0);
        int read_tag();
index 8e3e63682af1a56e43d3d474bb3f8076d9909041..d575c38e9d846aa2c507145582600c0da821a556 100644 (file)
@@ -189,9 +189,13 @@ void FloatAuto::toggle_curve_mode()
 }
 
 
-void FloatAuto::set_value(float newvalue)
+void FloatAuto::set_value(float value)
 {
-       this->value=newvalue;
+       float float_min = ((FloatAutos*)autos)->float_min;
+       if( value < float_min ) value = float_min;
+       float float_max = ((FloatAutos*)autos)->float_max;
+       if( value > float_max ) value = float_max;
+       this->value = value;
        this->adjust_curves();
        if(previous) ((FloatAuto*)previous)->adjust_curves();
        if(next)     ((FloatAuto*)next)->adjust_curves();
@@ -356,6 +360,10 @@ inline void FloatAuto::set_ctrl_positions(FloatAuto *prev, FloatAuto* next)
 void FloatAuto::adjust_to_new_coordinates(int64_t position, float value)
 // define new position and value in one step, do necessary re-adjustments
 {
+       float float_min = ((FloatAutos*)autos)->float_min;
+       if( value < float_min ) value = float_min;
+       float float_max = ((FloatAutos*)autos)->float_max;
+       if( value > float_max ) value = float_max;
        this->value = value;
        this->position = position;
        adjust_ctrl_positions();
@@ -415,6 +423,10 @@ void FloatAuto::copy(int64_t start, int64_t end, FileXML *file, int default_auto
 void FloatAuto::load(FileXML *file)
 {
        value = file->tag.get_property("VALUE", value);
+       float float_min = ((FloatAutos*)autos)->float_min;
+       if( value < float_min ) value = float_min;
+       float float_max = ((FloatAutos*)autos)->float_max;
+       if( value > float_max ) value = float_max;
        control_in_value = file->tag.get_property("CONTROL_IN_VALUE", control_in_value);
        control_out_value = file->tag.get_property("CONTROL_OUT_VALUE", control_out_value);
        curve_mode = (t_mode)file->tag.get_property("TANGENT_MODE", (int)FREE);
index 95dcace9ce6d97288a6357a7e93512ec7a825eb6..ca8dc6bf2f95e42f31d101ffb85b7b654daa1cd4 100644 (file)
@@ -37,6 +37,8 @@ FloatAutos::FloatAutos(EDL *edl,
 {
        this->default_ = default_;
        type = AUTOMATION_TYPE_FLOAT;
+       float_min = -FLT_MAX;
+       float_max = FLT_MAX;
 }
 
 FloatAutos::~FloatAutos()
index 0e7fa195f4ceb597d989b1af449faa2455f94c53..f53564d4052d0b0c9d3c4944bc98e48b3919341c 100644 (file)
@@ -70,6 +70,10 @@ public:
        void dump();
        Auto* new_auto();
        float default_;
+
+       float float_min, float_max;
+       void set_float_min(float mn) { float_min = mn; }
+       void set_float_max(float mx) { float_max = mx; }
 };
 
 
index 0e6469e2c1d5e3fe64aebcc853d7a8738a564a98..b8c0af6957a57b2c7eb96df02678e5977e24a8cb 100644 (file)
@@ -374,9 +374,10 @@ void IndexFile::close_source()
 
        delete render_engine;
        render_engine = 0;
-
-       delete cache;
-       cache = 0;
+       if( cache ) {
+               cache->remove_user();
+               cache = 0;
+       }
 }
 
 int64_t IndexFile::get_required_scale()
index 8d6a57557f86f881e8bde110ed4de3d1adb3ef5a..363c72df3ca797ddf3e283507a40f15dec6f0402 100644 (file)
@@ -25,6 +25,8 @@
 #include "cstrdup.h"
 #include "filexml.h"
 #include "keyframe.h"
+#include "keyframes.h"
+#include "transportque.inc"
 
 #include <stdio.h>
 #include <string.h>
@@ -181,7 +183,7 @@ void KeyFrame::update_parameter(BC_Hash *params,
 
                output.append_tag();
 // Write anonymous text & duplicate the rest
-               output.append_text(text ? text : this_text);
+               output.append_data(text ? text : this_text);
                output.append_data(extra ? extra : this_extra);
                output.terminate_string();
 // Move output to input
@@ -232,6 +234,27 @@ void KeyFrame::get_diff(KeyFrame *src,
        delete [] src_extra;
 }
 
+void KeyFrame::span_keyframes(int64_t start, int64_t end)
+{
+       BC_Hash *params = 0;
+       char *text = 0, *extra = 0;
+// The first one determines the changed parameters since it is the one displayed
+       KeyFrames *keyframes = (KeyFrames *)autos;
+       KeyFrame *current = keyframes->get_prev_keyframe(start, PLAY_FORWARD);
+       current->get_diff(this, &params, &text, &extra);
+// Always update the first one
+       current->update_parameter(params, text, extra);
+
+// Replace changed parameter in all selected keyframes.
+       for( current = (KeyFrame*)NEXT; current;  current = (KeyFrame*)NEXT ) {
+               if( current->position >= end ) break;
+               current->update_parameter(params, text, extra);
+       }
+       delete params;
+       delete [] text,
+       delete [] extra;
+}
+
 int KeyFrame::operator==(Auto &that)
 {
        return identical((KeyFrame*)&that);
index d766b915078dd72a382990f9c82e246bda1da386..8118afb8bc9ef79efc92518b697ff226d37527c5 100644 (file)
@@ -66,6 +66,7 @@ public:
        void get_contents(BC_Hash *ptr, char **text, char **extra);
 // Update a single parameter or the anonymous text depending on which argument is nonzero
        void update_parameter(BC_Hash *params, const char *text, const char *extra);
+       void span_keyframes(int64_t start, int64_t end);
 
        XMLBuffer *xbuf;
 };
index f590571d8be69916cd24958de728134fd6c8dc9a..fb7de36f93d32e6f118e52313b2b430235a21c1a 100644 (file)
@@ -208,7 +208,9 @@ void KeyFrameThread::handle_done_event(int result)
 {
 // Apply the preset
        if( !result ) {
+               get_gui()->lock_window("KeyFrameThread::handle_done_event");
                apply_preset(preset_text, is_factory);
+               get_gui()->unlock_window();
        }
 }
 
@@ -361,9 +363,16 @@ void KeyFrameThread::apply_preset(const char *title, int is_factory)
                mwindow->undo->update_undo_before();
 
 #ifdef USE_KEYFRAME_SPANNING
-               KeyFrame keyframe;
-               presets_db->load_preset(plugin_title, title, &keyframe, is_factory);
-               plugin->keyframes->update_parameter(&keyframe);
+               ArrayList<PluginServer*> &plugindb = *mwindow->plugindb;
+               int k = plugindb.size();
+               while( --k>=0 && strcmp(plugindb[k]->title, plugin->title) );
+               if( k >= 0 ) {
+                       PluginServer server(*plugindb[k]);
+                       server.open_plugin(0, mwindow->preferences, mwindow->edl, plugin);
+                       KeyFrame keyframe(mwindow->edl, plugin->keyframes);
+                       presets_db->load_preset(plugin_title, title, &keyframe, is_factory);
+                       server.apply_keyframe(plugin, &keyframe);
+               }
 #else
                KeyFrame *keyframe = plugin->get_keyframe();
                presets_db->load_preset(plugin_title, title, keyframe, is_factory);
index 123a6eb63dcb5cc860c98d41e1156d9f3bd472e1..7457773a08f51a7c4c38ba79ced81bf969a532bf 100644 (file)
@@ -623,22 +623,7 @@ void KeySpeedPatch::create_objects()
        add_subwindow(key_speed_ok = new KeySpeedOK(this, x, y, lok_images));
        activate();
        show_window();
-}
-
-int KeySpeedPatch::cursor_enter_event()
-{
-       if( is_event_win() )
-               mwindow->speed_before();
-       return 1;
-}
-
-int KeySpeedPatch::cursor_leave_event()
-{
-       if( is_event_win() ) {
-               mwindow->speed_after(1);
-               mwindow->resync_guis();
-       }
-       return 1;
+       mwindow->speed_before();
 }
 
 void KeySpeedPatch::update(float v)
@@ -660,9 +645,9 @@ void KeySpeedPatch::update_speed(float v)
        FloatAuto *current = (FloatAuto*)speed_autos->get_auto_for_editing(position);
        float change = v - current->get_value();
        current->set_value(v);
-       if( track->gang && track->record ) {
+       if( track->is_ganged() && track->is_armed() ) {
                TrackCanvas *track_canvas = patch->patchbay->pane->canvas;
-               track_canvas->fill_ganged_autos(1, change, track, current);
+               track_canvas->fill_ganged_autos(-1, change, track, current);
                track_canvas->update_ganged_autos(0, track, current);
                track_canvas->clear_ganged_autos();
        }
index 22d014af6d538becd704dfcc0f70f4b37e19e657..171c4cfc4ef2f3ab655e99493cf93f5657587c0e 100644 (file)
@@ -196,8 +196,6 @@ public:
        void create_objects();
        void update(float v);
        void update_speed(float v);
-       int cursor_enter_event();
-       int cursor_leave_event();
 
        MWindow *mwindow;
        PatchGUI *patch;
index 68d700f4b87b79a3e647b01869c4ed0a0eea2e46..588db9a9f87c11eca468e310873945084ca33dfb 100644 (file)
 #include "keyframe.h"
 #include "keyframes.h"
 #include "localsession.h"
+#include "plugin.h"
 #include "track.h"
 #include "transportque.inc"
 
-KeyFrames::KeyFrames(EDL *edl, Track *track)
- : Autos(edl, track)
+KeyFrames::KeyFrames(EDL *edl, Plugin *plugin)
+ : Autos(edl, plugin->track)
 {
        type = Autos::AUTOMATION_TYPE_PLUGIN;
+       plugin = plugin;
 }
 
 KeyFrames::~KeyFrames()
@@ -92,44 +94,6 @@ KeyFrame* KeyFrames::get_keyframe()
        return result;
 }
 
-
-void KeyFrames::update_parameter(KeyFrame *src)
-{
-// Create new keyframe if auto keyframes or replace entire keyframe.
-       double selection_start = edl->local_session->get_selectionstart(0);
-       double selection_end = edl->local_session->get_selectionend(0);
-       selection_start = edl->align_to_frame(selection_start, 0);
-       selection_end = edl->align_to_frame(selection_end, 0);
-
-       if( !edl->session->span_keyframes ||
-           EQUIV(selection_start, selection_end) ) {
-// Search for keyframe to write
-               KeyFrame *dst = get_keyframe();
-               dst->copy_data(src);
-       }
-       else {
-// Replace changed parameter in all selected keyframes.
-               BC_Hash *params = 0;
-               char *text = 0, *extra = 0;
-// Search all keyframes in selection but don't create a new one.
-               int64_t start = track->to_units(selection_start, 0);
-               int64_t end = track->to_units(selection_end, 0);
-               KeyFrame *current = get_prev_keyframe(start, PLAY_FORWARD);
-// The first one determines the changed parameters since it is the one displayed
-               current->get_diff(src, &params, &text, &extra);
-// Always update the first one
-               current->update_parameter(params, text, extra);
-
-               for( current = (KeyFrame*)NEXT; current;  current = (KeyFrame*)NEXT ) {
-                       if( current->position >= end ) break;
-                       current->update_parameter(params, text, extra);
-               }
-               delete params;
-               delete [] text,
-               delete [] extra;
-       }
-}
-
 Auto* KeyFrames::new_auto()
 {
        return new KeyFrame(edl, this);
index 89fa24353746b998f2ae979b1f9c1bbe13dd7112..45a453338734c1a280bf718ae4d1c4d014214442 100644 (file)
@@ -28,6 +28,7 @@
 #include "autos.h"
 #include "filexml.inc"
 #include "keyframe.inc"
+#include "plugin.inc"
 
 
 // Keyframes inherit from Autos to reuse the editing commands but
@@ -38,7 +39,7 @@
 class KeyFrames : public Autos
 {
 public:
-       KeyFrames(EDL *edl, Track *track);
+       KeyFrames(EDL *edl, Plugin *plugin);
        ~KeyFrames();
 
 // Get keyframes for editing with automatic creation if enabled.
@@ -46,14 +47,7 @@ public:
        virtual KeyFrame* get_keyframe();
 // Get the previous, first, or default keyframe depending on how many keyframes
 // exist.
-       KeyFrame* get_prev_keyframe(int64_t position,
-               int direction);
-
-// Keyframe updates using rules.
-// If a range is selected, the changed parameter is copied to all
-// the keyframes.
-// If no range is selected, a keyframe is created based on auto keyframe rules.
-       void update_parameter(KeyFrame *src);
+       KeyFrame* get_prev_keyframe(int64_t position, int direction);
 
        Auto* new_auto();
        void dump(FILE *fp=stdout);
index a946077393e514a2e007379a7187b92a77f0a758..dce124911df4b2bb5b5505ac84350b12940f407d 100644 (file)
@@ -136,23 +136,19 @@ void LoadFileThread::load_apply()
 
 // No file selected
        if( !path_list.size() ) return;
+       int replaced = load_mode == LOADMODE_REPLACE ||
+            load_mode == LOADMODE_REPLACE_CONCATENATE ? 1 : 0;
 
        mwindow->interrupt_indexes();
        mwindow->gui->lock_window("LoadFileThread::run");
-       mwindow->load_filenames(&path_list, load_mode, edl_mode, 0);
+       mwindow->load_filenames(&path_list, load_mode, edl_mode, replaced);
        mwindow->gui->mainmenu->add_load(path_list.values[0]);
        mwindow->gui->unlock_window();
        path_list.remove_all_objects();
 
        mwindow->save_backup();
-
        mwindow->restart_brender();
-
-       if( load_mode == LOADMODE_REPLACE ||
-           load_mode == LOADMODE_REPLACE_CONCATENATE )
-               mwindow->session->changes_made = 0;
-       else
-               mwindow->session->changes_made = 1;
+       mwindow->session->changes_made = !replaced ? 1 : 0;
 }
 
 
index 7e1f50eaeb030eede38dd7bff30822f6e2d6d66d..47d86c28f239cc4113423667d66c3d57d043f35d 100644 (file)
@@ -86,7 +86,7 @@ LocalSession::LocalSession(EDL *edl)
        automation_maxs[AUTOGROUPTYPE_AUDIO_FADE] = 6;
        automation_mins[AUTOGROUPTYPE_VIDEO_FADE] = 0;
        automation_maxs[AUTOGROUPTYPE_VIDEO_FADE] = 100;
-       automation_mins[AUTOGROUPTYPE_SPEED] = 0.005;
+       automation_mins[AUTOGROUPTYPE_SPEED] = SPEED_MIN;
        automation_maxs[AUTOGROUPTYPE_SPEED] = 5.000;
        automation_mins[AUTOGROUPTYPE_INT255] = 0;
        automation_maxs[AUTOGROUPTYPE_INT255] = 255;
@@ -296,7 +296,9 @@ void LocalSession::load_xml(FileXML *file, unsigned long load_flags)
                for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
                        if (!Automation::autogrouptypes_fixedrange[i]) {
                                automation_mins[i] = file->tag.get_property(xml_autogrouptypes_titlesmin[i],automation_mins[i]);
+                               AUTOMATIONCLAMPS(automation_mins[i], i);
                                automation_maxs[i] = file->tag.get_property(xml_autogrouptypes_titlesmax[i],automation_maxs[i]);
+                               AUTOMATIONCLAMPS(automation_maxs[i], i);
                        }
                }
                floatauto_type = file->tag.get_property("FLOATAUTO_TYPE", floatauto_type);
@@ -345,9 +347,9 @@ int LocalSession::load_defaults(BC_Hash *defaults)
 //     track_start = defaults->get("TRACK_START", 0);
 //     view_start = defaults->get("VIEW_START", 0);
        zoom_sample = defaults->get("ZOOM_SAMPLE", DEFAULT_ZOOM_TIME);
-       zoom_y = defaults->get("ZOOMY", 64);
+       zoom_y = defaults->get("ZOOMY", DEFAULT_ZOOM_TRACK);
        int64_t zoom_track = defaults->get("ZOOM_TRACK", 0);
-       if( zoom_track == 0 ) zoom_track = 64;
+       if( zoom_track == 0 ) zoom_track = DEFAULT_ZOOM_TRACK;
        zoom_atrack = defaults->get("ZOOM_ATRACK", zoom_track);
        zoom_vtrack = defaults->get("ZOOM_VTRACK", zoom_track);
        red = defaults->get("RED", 0.0);
@@ -361,7 +363,9 @@ int LocalSession::load_defaults(BC_Hash *defaults)
        for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
                if (!Automation::autogrouptypes_fixedrange[i]) {
                        automation_mins[i] = defaults->get(xml_autogrouptypes_titlesmin[i], automation_mins[i]);
+                       AUTOMATIONCLAMPS(automation_mins[i], i);
                        automation_maxs[i] = defaults->get(xml_autogrouptypes_titlesmax[i], automation_maxs[i]);
+                       AUTOMATIONCLAMPS(automation_maxs[i], i);
                }
        }
 
index f1b980cb83eb6123b0ff96df5d603a8d7007ff8f..64e90885255df6e2dea596e1a150d58a6cd1629a 100644 (file)
@@ -37,6 +37,7 @@
 #include "dvdcreate.h"
 #include "edl.h"
 #include "edlsession.h"
+#include "exportedl.h"
 #include "file.h"
 #include "filesystem.h"
 #include "filexml.h"
@@ -78,7 +79,8 @@
 #include "transportque.h"
 #include "viewmenu.h"
 #include "zoombar.h"
-#include "exportedl.h"
+#include "zwindow.h"
+#include "zwindowgui.h"
 
 #include <string.h>
 
@@ -207,6 +209,8 @@ void MainMenu::create_objects()
        trackmenu->add_item(new DeleteFirstTrack(mwindow));
        trackmenu->add_item(new DeleteLastTrack(mwindow));
        trackmenu->add_item(new ConcatenateTracks(mwindow));
+       trackmenu->add_item(new SwapTracksUp(mwindow));
+       trackmenu->add_item(new SwapTracksDown(mwindow));
        AppendTracks *append_tracks;
        trackmenu->add_item(append_tracks = new AppendTracks(mwindow));
        append_tracks->create_objects();
@@ -949,9 +953,7 @@ Clear::Clear(MWindow *mwindow)
 int Clear::handle_event()
 {
        if( mwindow->session->current_operation == NO_OPERATION ) {
-               mwindow->cwindow->gui->lock_window("Clear::handle_event");
                mwindow->clear_entry();
-               mwindow->cwindow->gui->unlock_window();
        }
        return 1;
 }
@@ -1158,7 +1160,7 @@ AddVideoTrack::AddVideoTrack(MWindow *mwindow)
 int AddVideoTrack::handle_event()
 {
        if( mwindow->session->current_operation == NO_OPERATION )
-               mwindow->add_video_track_entry();
+               mwindow->add_video_track_entry(1, 0);
        return 1;
 }
 
@@ -1290,6 +1292,34 @@ int MoveTracksDown::handle_event()
 }
 
 
+SwapTracksUp::SwapTracksUp(MWindow *mwindow)
+ : BC_MenuItem(_("Swap tracks up"), 0, UP)
+{
+       this->mwindow = mwindow;
+       set_shift();
+}
+
+int SwapTracksUp::handle_event()
+{
+       if( mwindow->session->current_operation == NO_OPERATION )
+               mwindow->swap_tracks_up();
+       return 1;
+}
+
+SwapTracksDown::SwapTracksDown(MWindow *mwindow)
+ : BC_MenuItem(_("Swap tracks down"), 0, DOWN)
+{
+       set_shift(); this->mwindow = mwindow;
+}
+
+int SwapTracksDown::handle_event()
+{
+       if( mwindow->session->current_operation == NO_OPERATION )
+               mwindow->swap_tracks_down();
+       return 1;
+}
+
+
 
 
 ConcatenateTracks::ConcatenateTracks(MWindow *mwindow)
@@ -1341,7 +1371,7 @@ AddSubttlTrack::AddSubttlTrack(MWindow *mwindow)
 int AddSubttlTrack::handle_event()
 {
        if( mwindow->session->current_operation == NO_OPERATION )
-               mwindow->add_subttl_track_entry();
+               mwindow->add_subttl_track_entry(1, 0);
        return 1;
 }
 
@@ -1509,7 +1539,9 @@ ShowVWindow::ShowVWindow(MWindow *mwindow)
 }
 int ShowVWindow::handle_event()
 {
+       mwindow->gui->unlock_window();
        mwindow->show_vwindow();
+       mwindow->gui->lock_window("ShowVWindow::handle_event");
        return 1;
 }
 
@@ -1521,7 +1553,9 @@ ShowAWindow::ShowAWindow(MWindow *mwindow)
 }
 int ShowAWindow::handle_event()
 {
+       mwindow->gui->unlock_window();
        mwindow->show_awindow();
+       mwindow->gui->lock_window("ShowAWindow::handle_event");
        return 1;
 }
 
@@ -1533,7 +1567,9 @@ ShowCWindow::ShowCWindow(MWindow *mwindow)
 }
 int ShowCWindow::handle_event()
 {
+       mwindow->gui->unlock_window();
        mwindow->show_cwindow();
+       mwindow->gui->lock_window("ShowCWindow::handle_event");
        return 1;
 }
 
@@ -1548,10 +1584,12 @@ ShowGWindow::ShowGWindow(MWindow *mwindow)
 int ShowGWindow::handle_event()
 {
        if( mwindow->session->current_operation == NO_OPERATION ) {
+               mwindow->gui->unlock_window();
                if( !mwindow->session->show_gwindow )
                        mwindow->show_gwindow();
                else
                        mwindow->hide_gwindow();
+               mwindow->gui->lock_window("ShowGWindow::handle_event");
                set_checked(mwindow->session->show_gwindow);
        }
        return 1;
@@ -1566,7 +1604,9 @@ ShowLWindow::ShowLWindow(MWindow *mwindow)
 }
 int ShowLWindow::handle_event()
 {
+       mwindow->gui->unlock_window();
        mwindow->show_lwindow();
+       mwindow->gui->lock_window("ShowLWindow::handle_event");
        return 1;
 }
 
@@ -1630,45 +1670,98 @@ void MixerItems::create_objects()
 {
        BC_SubMenu *mixer_submenu = new BC_SubMenu();
        add_submenu(mixer_submenu);
-       mixer_submenu->add_submenuitem(new MixerViewer(mwindow));
-       mixer_submenu->add_submenuitem(new TileMixers(mwindow));
-       mixer_submenu->add_submenuitem(new AlignMixers(mwindow));
+       mixer_submenu->add_submenuitem(new MixerViewer(this));
+       mixer_submenu->add_submenuitem(new TileMixers(this));
+       mixer_submenu->add_submenuitem(new AlignMixers(this));
 }
 
-MixerViewer::MixerViewer(MWindow *mwindow)
- : BC_MenuItem(_("Mixer Viewer"), _("Shift-M"), 'M')
+int MixerItems::activate_submenu()
+{
+       BC_SubMenu *mixer_submenu = (BC_SubMenu *)get_submenu();
+       int k = mixer_submenu->total_items();
+       while( --k >= 0 ) {
+               MixerItem *mixer_item = (MixerItem *)mixer_submenu->get_item(k);
+               if( mixer_item->idx < 0 ) continue;
+               mixer_submenu->del_item(mixer_item);
+       }
+       int n = mwindow->edl->mixers.size();
+       for( int i=0; i<n; ++i ) {
+               Mixer *mixer = mwindow->edl->mixers[i];
+               if( !mixer ) continue;
+               MixerItem *mixer_item = new MixerItem(this, mixer->title, mixer->idx);
+               mixer_submenu->add_submenuitem(mixer_item);
+       }
+       return BC_MenuItem::activate_submenu();
+}
+
+MixerItem::MixerItem(MixerItems *mixer_items, const char *text, int idx)
+ : BC_MenuItem(text)
+{
+       this->mixer_items = mixer_items;
+       this->idx = idx;
+}
+
+MixerItem::MixerItem(MixerItems *mixer_items, const char *text, const char *hotkey_text, int hotkey)
+ : BC_MenuItem(text, hotkey_text, hotkey)
+{
+       this->mixer_items = mixer_items;
+       this->idx = -1;
+}
+
+int MixerItem::handle_event()
+{
+       if( idx < 0 ) return 0;
+       MWindow *mwindow = mixer_items->mwindow;
+       Mixer *mixer = mwindow->edl->mixers.get_mixer(idx);
+       if( !mixer ) return 0;
+       ZWindow *zwindow = mwindow->get_mixer(idx);
+       if( !zwindow )
+               zwindow = mwindow->get_mixer(mixer);
+       if( !zwindow->zgui ) {
+               zwindow->set_title(mixer->title);
+               zwindow->start();
+       }
+       zwindow->zgui->lock_window("MixerItem::handle_event");
+       zwindow->zgui->raise_window();
+       zwindow->zgui->unlock_window();
+       mwindow->refresh_mixers();
+       return 1;
+}
+
+MixerViewer::MixerViewer(MixerItems *mixer_items)
+ : MixerItem(mixer_items, _("Mixer Viewer"), _("Shift-M"), 'M')
 {
-       this->mwindow = mwindow;
        set_shift(1);
 }
 
 int MixerViewer::handle_event()
 {
+       MWindow *mwindow = mixer_items->mwindow;
        mwindow->start_mixer();
        return 1;
 }
 
-TileMixers::TileMixers(MWindow *mwindow)
- : BC_MenuItem(_("Tile mixers"), "Alt-t", 't')
+TileMixers::TileMixers(MixerItems *mixer_items)
+ : MixerItem(mixer_items, _("Tile mixers"), "Alt-t", 't')
 {
-       this->mwindow = mwindow;
        set_alt();
 }
 
 int TileMixers::handle_event()
 {
+       MWindow *mwindow = mixer_items->mwindow;
        mwindow->tile_mixers();
        return 1;
 }
 
-AlignMixers::AlignMixers(MWindow *mwindow)
- : BC_MenuItem(_("Align mixers"))
+AlignMixers::AlignMixers(MixerItems *mixer_items)
+ : MixerItem(mixer_items, _("Align mixers"), "", 0)
 {
-       this->mwindow = mwindow;
 }
 
 int AlignMixers::handle_event()
 {
+       MWindow *mwindow = mixer_items->mwindow;
        int wx, wy;
        mwindow->gui->get_abs_cursor(wx, wy);
        mwindow->mixers_align->start_dialog(wx, wy);
index 9e0513cdb4cfa7c0af82b45137a1116307caa177..bf14888f3296ad0d7ab223c5a32339a4e1fc30e9 100644 (file)
@@ -501,31 +501,41 @@ class MixerItems : public BC_MenuItem
 public:
        MixerItems(MWindow *mwindow);
        void create_objects();
+       int activate_submenu();
+
        MWindow *mwindow;
 };
 
-class MixerViewer : public BC_MenuItem
+class MixerItem : public BC_MenuItem
+{
+public:
+       MixerItem(MixerItems *mixer_items, const char *text, int idx);
+       MixerItem(MixerItems *mixer_items, const char *text, const char *hotkey_text, int hotkey);
+       virtual int handle_event();
+
+       MixerItems *mixer_items;
+       int idx;
+};
+
+class MixerViewer : public MixerItem
 {
 public:
-       MixerViewer(MWindow *mwindow);
+       MixerViewer(MixerItems *mixer_items);
        int handle_event();
-       MWindow *mwindow;
 };
 
-class TileMixers : public BC_MenuItem
+class TileMixers : public MixerItem
 {
 public:
-       TileMixers(MWindow *mwindow);
+       TileMixers(MixerItems *mixer_items);
        int handle_event();
-       MWindow *mwindow;
 };
 
-class AlignMixers : public BC_MenuItem
+class AlignMixers : public MixerItem
 {
 public:
-       AlignMixers(MWindow *mwindow);
+       AlignMixers(MixerItems *mixer_items);
        int handle_event();
-       MWindow *mwindow;
 };
 
 // ======================================== audio
@@ -645,6 +655,22 @@ public:
        MWindow *mwindow;
 };
 
+class SwapTracksUp : public BC_MenuItem
+{
+public:
+       SwapTracksUp(MWindow *mwindow);
+       int handle_event();
+       MWindow *mwindow;
+};
+
+class SwapTracksDown : public BC_MenuItem
+{
+public:
+       SwapTracksDown(MWindow *mwindow);
+       int handle_event();
+       MWindow *mwindow;
+};
+
 class DeleteTracks : public BC_MenuItem
 {
 public:
index 564d1fe895287b66f5e4ddca8bf3c145123af81e..efe37ccccf2204120c935530a25373cb85a82a55 100644 (file)
@@ -301,7 +301,6 @@ void MaskUnit::process_package(LoadPackage *package)
        pkg = (MaskPackage*)package;
        start_x = pkg->start_x;  end_x = pkg->end_x;
        start_y = pkg->start_y;  end_y = pkg->end_y;
-       if( start_y >= end_y ) return;
        MaskEdge *edge = engine->edge;
        float r = engine->r, v = engine->v;
        VFrame *in = engine->in;
index b863a3137782863416543c375b00a5ce1c7054fb..d40b726df60d970df309e5d4c14e986418c2face 100644 (file)
@@ -143,7 +143,8 @@ MainEditing::MainEditing(MWindow *mwindow, MButtons *mbuttons, int x, int y)
                mwindow->has_commercials(), // use_commerical
                1, // use_goto
                0, // use_clk2play
-               0) // use_scope
+               0, // use_scope
+               1) // use_gang_tracks
 {
        this->mwindow = mwindow;
        this->mbuttons = mbuttons;
@@ -286,3 +287,8 @@ void MainEditing::panel_set_labels_follow_edits(int v)
         mwindow->set_labels_follow_edits(v);
 }
 
+void MainEditing::panel_set_gang_tracks(int v)
+{
+       mwindow->set_gang_tracks(v);
+}
+
index 698c4e839a11340f12867a1c3a0150246f2cb98b..dad5847fa261582fd52dc0469b76b8bf40fd5460 100644 (file)
@@ -108,6 +108,7 @@ public:
        void panel_set_auto_keyframes(int v);
        void panel_set_span_keyframes(int v);
        void panel_set_labels_follow_edits(int v);
+       void panel_set_gang_tracks(int v);
 
        MWindow *mwindow;
        MButtons *mbuttons;
index b5fe9227402cf6239206375f2942441b40865614..5a148d38a4b312f4f9d5143d6ec6dff2a9e82261 100644 (file)
@@ -704,7 +704,7 @@ void MixersAlign::nudge_tracks()
                        while( track && track->mixer_id != id ) track = track->next;
                        if( !track ) continue;
                        double nudge = mix->nudge;
-                       int record = track->record;  track->record = 1;
+                       int armed = track->armed;  track->armed = 1;
                        if( nudge < 0 ) {
                                track->clear(0, -nudge, 1,
                                        edl->session->labels_follow_edits,
@@ -716,7 +716,7 @@ void MixersAlign::nudge_tracks()
                                        edl->session->plugins_follow_edits,
                                        edl->session->autos_follow_edits);
                        }
-                       track->record = record;
+                       track->armed = armed;
                }
        }
        edl->optimize();
@@ -736,8 +736,8 @@ void MixersAlign::nudge_selected()
 
        ArrayList<int> track_arms;  // ugly
        for( Track *track=edl->tracks->first; track; track=track->next ) {
-               track_arms.append(track->record);
-               track->record = 0;
+               track_arms.append(track->armed);
+               track->armed = 0;
        }
        for( int m, i=0; (m=ma_gui->mixer_list->get_selection_number(0,i))>=0; ++i ) {
                if( m == midx ) continue;  // master does not move
@@ -749,7 +749,7 @@ void MixersAlign::nudge_selected()
                        while( track && track->mixer_id != id ) track = track->next;
                        if( !track ) continue;
                        double nudge = mix->nudge;
-                       track->record = 1;
+                       track->armed = 1;
                        double position = 0;  Track *first_track = 0;
                        EDL *clip = edl->selected_edits_to_clip(0, &position, &first_track);
                        if( clip ) {
@@ -775,12 +775,12 @@ void MixersAlign::nudge_selected()
                                position += nudge;
                                edl->paste_edits(clip, first_track, position, 1);
                        }
-                       track->record = 0;
+                       track->armed = 0;
                }
        }
        int i = 0;
        for( Track *track=edl->tracks->first; track; track=track->next )
-               track->record = track_arms[i++];
+               track->armed = track_arms[i++];
        edl->optimize();
 
        mwindow->update_gui(1);
index 01f3095f1c69d2e8d0b87ee726d1128fb9dd216d..c6990275851b087474cc839214c18ce7cd144dec 100644 (file)
@@ -59,7 +59,6 @@ Module::Module(RenderEngine *renderengine,
        nested_edl = 0;
        nested_renderengine = 0;
        nested_command = 0;
-       private_cache = 0;
        cache = 0;
 }
 
@@ -86,7 +85,6 @@ Module::~Module()
 
        delete nested_renderengine;
        delete nested_command;
-       if(private_cache) delete cache;
 }
 
 void Module::create_objects()
index 85b506774823e1507b881b578c5d9d23e8e8a05d..1203f3b61912d538d1f8065917e64c7e4430c532 100644 (file)
@@ -82,8 +82,6 @@ public:
 
 // CICache used during effect & nested EDL
        CICache *cache;
-// If the cache was allocated by the module
-       int private_cache;
 // Parent EDL of this module when used for effect rendering.
 // Used by APluginArray.
        EDL *edl;
index 8b93262c4e6930cd53027d40c9b3b5f2309d1c67..1466b4451275c4b0529af43647787a70dae5db74 100644 (file)
@@ -243,6 +243,7 @@ MWindow::MWindow()
        in_destructor = 0;
        speed_edl = 0;
        beeper = 0;
+       redraw_tracks = 0;
        shuttle = 0;
        wintv = 0;
        x10tv = 0;
@@ -265,9 +266,10 @@ MWindow::~MWindow()
 #ifdef HAVE_DVB
        gui->channel_info->stop();
 #endif
-       delete beeper;
-       delete create_bd;       create_bd = 0;
-       delete create_dvd;      create_dvd = 0;
+       delete beeper;          beeper = 0;
+       delete redraw_tracks;   redraw_tracks = 0;
+       delete create_bd;       create_bd = 0;
+       delete create_dvd;      create_dvd = 0;
 #ifdef HAVE_SHUTTLE
        delete shuttle;         shuttle = 0;
 #endif
@@ -301,6 +303,7 @@ MWindow::~MWindow()
        gui->del_keyboard_listener(
                (int (BC_WindowBase::*)(BC_WindowBase *))
                &MWindowGUI::keyboard_listener);
+       reset_caches();
 #if 0
 // release the hounds
        if( awindow && awindow->gui ) awindow->gui->close(0);
@@ -329,7 +332,6 @@ MWindow::~MWindow()
        gui->close(0);
        join();
 #endif
-       reset_caches();
        dead_plugins->remove_all_objects();
 // must delete theme before destroying plugindb
 //  theme destructor will be deleted by delete_plugins
@@ -347,8 +349,9 @@ MWindow::~MWindow()
        delete gui;             gui = 0;
        delete mainindexes;     mainindexes = 0;
        delete mainprogress;    mainprogress = 0;
-       delete audio_cache;     audio_cache = 0;  // delete the cache after the assets
-       delete video_cache;     video_cache = 0;  // delete the cache after the assets
+ // delete the caches after the assets
+       if( audio_cache ) { audio_cache->remove_user();  audio_cache = 0; }
+       if( video_cache ) { video_cache->remove_user();  video_cache = 0; }
        delete frame_cache;     frame_cache = 0;
        delete wave_cache;      wave_cache = 0;
        delete plugin_guis;     plugin_guis = 0;
@@ -1210,10 +1213,23 @@ ZWindow *MWindow::get_mixer(Mixer *&mixer)
        return zwindow;
 }
 
-void MWindow::del_mixer(ZWindow *zwindow)
+ZWindow *MWindow::get_mixer(int idx)
+{
+       ZWindow *zwindow = 0;
+       zwindows_lock->lock("MWindow::get_mixer");
+       for( int i=0; !zwindow && i<zwindows.size(); ++i ) {
+               ZWindow *zwdw = zwindows[i];
+               if( !zwdw->running() ) continue;
+               if( zwdw->idx != idx ) continue;
+               zwindow = zwindows[i];
+       }
+       zwindows_lock->unlock();
+       return zwindow;
+}
+
+void MWindow::close_mixer(ZWindow *zwindow)
 {
-       zwindows_lock->lock("MWindow::del_mixer 0");
-       edl->mixers.del_mixer(zwindow->idx);
+       zwindows_lock->lock("MWindow::close_mixer 0");
        if( session->selected_zwindow >= 0 ) {
                int i = zwindows.number_of(zwindow);
                if( i >= 0 && i < session->selected_zwindow )
@@ -1222,7 +1238,7 @@ void MWindow::del_mixer(ZWindow *zwindow)
                        session->selected_zwindow = -1;
        }
        zwindows_lock->unlock();
-       gui->lock_window("MWindow::del_mixer 1");
+       gui->lock_window("MWindow::close_mixer 1");
        gui->update_mixers(0, -1);
        gui->unlock_window();
 }
@@ -1297,11 +1313,11 @@ void MWindow::handle_mixers(EDL *edl, int command, int wait_tracking,
                        k = mixer->mixer_ids.size();
                        while( --k >= 0 && track->get_mixer_id() != mixer->mixer_ids[k] );
                        if( k >= 0 ) {
-                               track->record = 1;
+                               track->armed = 1;
                                track->play = track->data_type == TRACK_VIDEO ? 1 : 0;
                        }
                        else
-                               track->record = track->play = 0;
+                               track->armed = track->play = 0;
                }
                zwindow->change_source(mixer_edl);
                zwindow->handle_mixer(command, 0,
@@ -1356,7 +1372,7 @@ ZWindow *MWindow::create_mixer(Indexable *indexable, double position)
        Mixer *mixer = 0;
        ZWindow *zwindow = get_mixer(mixer);
        while( track ) {
-               track->play = track->record = 0;
+               track->play = track->armed = 0;
                if( track->data_type == TRACK_VIDEO ) {
                        sprintf(track->title, _("Mixer %d"), zwindow->idx);
                }
@@ -1499,6 +1515,14 @@ void MWindow::tile_mixers()
        }
 }
 
+void MWindow::set_gang_tracks(int v)
+{
+       edl->session->gang_tracks = v;
+       gui->update(1, 1, 0, 0, 1, 0, 0);
+       gui->flush();
+}
+
+
 void MWindow::init_cache()
 {
        audio_cache = new CICache(preferences);
@@ -1769,7 +1793,7 @@ int MWindow::put_commercial()
        //check it
        for(Track *track=tracks->first; track && !errmsg; track=track->next) {
                if( track->data_type != TRACK_VIDEO ) continue;
-               if( !track->record ) continue;
+               if( !track->armed ) continue;
                if( count > 0 ) { errmsg = _("multiple video tracks"); break; }
                ++count;
                int64_t units_start = track->to_units(start,0);
@@ -1789,7 +1813,7 @@ int MWindow::put_commercial()
        //run it
        for(Track *track=tracks->first; track && !errmsg; track=track->next) {
                if( track->data_type != TRACK_VIDEO ) continue;
-               if( !track->record ) continue;
+               if( !track->armed ) continue;
                int64_t units_start = track->to_units(start,0);
                int64_t units_end = track->to_units(end,0);
                Edits *edits = track->edits;
@@ -2469,8 +2493,6 @@ int MWindow::to_proxy(Asset *asset, int new_scale, int new_use_scaler)
                for( int i=0,n=edl->nested_edls.size(); i<n; ++i ) {
                        EDL *orig_nested = edl->nested_edls[i];
                        char new_path[BCTEXTLEN];
-                       if( !ProxyRender::from_proxy_path(new_path, orig_nested, proxy_scale) )
-                               continue;
                        proxy_render.to_proxy_path(new_path, orig_nested, proxy_scale);
 // test if proxy asset was already added to proxy_assets
                        int got_it = 0;
@@ -2974,6 +2996,7 @@ void MWindow::show_lwindow()
 
 void MWindow::restore_windows()
 {
+       gui->unlock_window();
        if( !session->show_vwindow ) {
                for( int i=0, n=vwindows.size(); i<n; ++i ) {
                        VWindow *vwindow = vwindows[i];
@@ -3018,6 +3041,7 @@ void MWindow::restore_windows()
        else if( session->show_lwindow && lwindow->gui->is_hidden() )
                show_lwindow();
 
+       gui->lock_window("MWindow::restore_windows");
        gui->focus();
 }
 
@@ -3406,7 +3430,7 @@ int MWindow::get_hash_color(Edit *edit)
        char path[BCTEXTLEN];
        if( !edit->asset || edit->track->data_type != TRACK_VIDEO ||
            edl->session->proxy_scale == 1 ||
-           ProxyRender::from_proxy_path(path, idxbl, edl->session->proxy_scale) )
+           ProxyRender::from_proxy_path(path, (Asset*)idxbl, edl->session->proxy_scale) )
                strcpy(path, idxbl->path);
        char *cp = strrchr(path, '/');
        cp = !cp ? path : cp+1;
@@ -3750,6 +3774,7 @@ void MWindow::update_project(int load_mode)
 
                for( int i=0; i<edl->mixers.size(); ++i ) {
                        Mixer *mixer = edl->mixers[i];
+                       if( !mixer->show ) continue;
                        ZWindow *zwindow = get_mixer(mixer);
                        zwindow->set_title(mixer->title);
                        zwindow->start();
@@ -3779,7 +3804,7 @@ void MWindow::update_project(int load_mode)
        if(debug) PRINT_TRACE
 }
 
-void MWindow::stack_push(EDL *new_edl, Indexable *idxbl)
+void MWindow::stack_push(EDL *new_edl, Indexable *idxbl, Edit *edit)
 {
        int got_indexes = 0;
        for( int i=0; i<new_edl->nested_edls.size(); ++i ) {
@@ -3805,7 +3830,9 @@ void MWindow::stack_push(EDL *new_edl, Indexable *idxbl)
                undo_before();
                StackItem &item = stack.append();
                item.edl = edl;
+               item.edit = edit;
                item.new_edl = new_edl;
+               item.duration = new_edl->tracks->total_length();
                item.undo = undo;
                item.idxbl = idxbl;
                item.mtime = 0;
@@ -3838,6 +3865,17 @@ void MWindow::stack_pop()
 // session edl replaced, overwrite and save clip data
        if( item.new_edl != edl )
                item.new_edl->overwrite_clip(edl);
+       Edit *edit = item.edit;
+// resize the referring edit if the edl duration changed
+       if( edit ) {
+               double duration = item.new_edl->tracks->total_length();
+               double dt = duration - item.duration;
+               if( fabs(dt) > 1e-4 ) {
+                       int64_t du = edit->track->to_units(dt,0);
+                       if( (edit->length+=du) < 0 )
+                               edit->length = 0;
+               }
+       }
        edl->remove_user();
        edl = item.edl;
        delete undo;
@@ -3847,6 +3885,7 @@ void MWindow::stack_pop()
        stack.remove();
        if( idxbl ) {
                gui->unlock_window();
+               gui->resource_thread->close_indexable(idxbl);
                remove_from_caches(idxbl);
                remove_indexfile(idxbl);
                mainindexes->add_indexable(idxbl);
@@ -3950,6 +3989,7 @@ void MWindow::clip_to_media()
                return;
        }
        undo_before();
+       awindow->gui->stop_vicon_drawing();
        int clips_total = session->drag_clips->total;
        for( int i=0; i<clips_total; ++i ) {
                EDL *clip = session->drag_clips->values[i];
@@ -3963,7 +4003,7 @@ void MWindow::clip_to_media()
                char *bp = strrchr(clip->local_session->clip_title, '/');
                bp = bp ? bp+1 : clip->local_session->clip_title;
                cp += snprintf(cp, ep-cp, "%s", bp);
-               EDL *nested = edl->new_nested_edl(clip, path);
+               EDL *nested = edl->new_nested_clip(clip, path);
                edl->clips.remove(clip);
                clip->remove_user();
                mainindexes->add_indexable(nested);
@@ -4426,6 +4466,9 @@ int MWindow::create_aspect_ratio(float &w, float &h, int width, int height)
 
 void MWindow::reset_caches()
 {
+       int locked  = gui->get_window_lock();
+       if( locked ) gui->unlock_window();
+       awindow->gui->stop_vicon_drawing(1);
        frame_cache->remove_all();
        wave_cache->remove_all();
        audio_cache->remove_all();
@@ -4445,10 +4488,12 @@ void MWindow::reset_caches()
                if( vwindow->playback_engine->video_cache )
                        vwindow->playback_engine->video_cache->remove_all();
        }
+       if( locked ) gui->lock_window("MWindow::reset_caches");
 }
 
 void MWindow::remove_from_caches(Indexable *idxbl)
 {
+       awindow->gui->stop_vicon_drawing(1);
        frame_cache->remove_item(idxbl);
        wave_cache->remove_item(idxbl);
        if( gui->render_engine &&
@@ -4482,12 +4527,13 @@ void MWindow::remove_from_caches(Indexable *idxbl)
                if( zwindow->zgui->playback_engine->video_cache )
                        zwindow->zgui->playback_engine->video_cache->delete_entry(asset);
        }
+       awindow->gui->start_vicon_drawing();
 }
 
 void MWindow::remove_assets_from_project(int push_undo, int redraw, int delete_indexes,
                ArrayList<Indexable*> *drag_assets, ArrayList<EDL*> *drag_clips)
 {
-       awindow->gui->close_view_popup();
+       awindow->gui->stop_vicon_drawing(1);
 
 // Remove from VWindow.
        if( drag_clips ) {
@@ -4642,6 +4688,14 @@ void MWindow::dump_exe(FILE *fp)
        fprintf(fp, "\n");
 }
 
+void MWindow::dump_caches(FILE *fp)
+{
+       fprintf(fp, "audio cache: ");
+       audio_cache->dump(fp);
+       fprintf(fp, "video cache: ");
+       video_cache->dump(fp);
+}
+
 void MWindow::trap_hook(FILE *fp, void *vp)
 {
        MWindow *mwindow = (MWindow *)vp;
@@ -4653,6 +4707,8 @@ void MWindow::trap_hook(FILE *fp, void *vp)
        mwindow->dump_undo(fp);
        fprintf(fp, "\nEXE: %s\n", AboutPrefs::build_timestamp);
        mwindow->dump_exe(fp);
+       fprintf(fp, "\nCACHES:\n");
+       mwindow->dump_caches(fp);
 }
 
 
@@ -4961,7 +5017,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
                                track->track_h = edl->session->output_h;
                        }
                        else if( delete_tracks )
-                               edl->tracks->delete_track(track);
+                               edl->tracks->delete_track(track, 0);
                }
                edl->retrack();
                edl->resample(old_framerate, session->frame_rate, TRACK_VIDEO);
@@ -4997,7 +5053,7 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
                                                delete edit;
                                }
                                if( !track->edits->first )
-                                       edl->tracks->delete_track(track);
+                                       edl->tracks->delete_track(track, 0);
                        }
                }
                edl->rechannel();
@@ -5093,3 +5149,28 @@ int MWindow::get_cpus()
        return get_cpus(edl->session->output_w, edl->session->output_h);
 }
 
+void MWindow::draw_trackmovement()
+{
+       if( !redraw_tracks )
+               redraw_tracks = new DrawTrackMovement(this);
+       redraw_tracks->start();
+}
+
+DrawTrackMovement::DrawTrackMovement(MWindow *mwindow)
+ : Thread(1, 0, 0)
+{
+       this->mwindow = mwindow;
+}
+DrawTrackMovement::~DrawTrackMovement()
+{
+       join();
+}
+
+void DrawTrackMovement::run()
+{
+       mwindow->gui->lock_window("DrawTrackMovement::run");
+       mwindow->edl->tracks->update_y_pixels(mwindow->theme);
+       mwindow->gui->draw_trackmovement();
+       mwindow->gui->unlock_window();
+}
+
index 826ca600abb693afc81a294323ec94b4273051b2..8f80280f13ef45a412969db698e89a0b6e35bf03 100644 (file)
@@ -112,8 +112,10 @@ class StackItem
 public:
        EDL *edl, *new_edl;
        Indexable *idxbl;
+       Edit *edit;
        MainUndo *undo;
        int64_t mtime;
+       double duration;
 };
 
 class Stack : public ArrayList<StackItem>
@@ -144,6 +146,17 @@ public:
 };
 
 
+class DrawTrackMovement : public Thread
+{
+public:
+       DrawTrackMovement(MWindow *mwindow);
+       ~DrawTrackMovement();
+       void run();
+
+       MWindow *mwindow;
+};
+
+
 class MWindow : public Thread
 {
 public:
@@ -175,7 +188,7 @@ public:
 // Total horizontal pixels in timeline
        int get_tracks_width();
 // session stack
-       void stack_push(EDL *edl, Indexable *idxbl);
+       void stack_push(EDL *edl, Indexable *idxbl, Edit *edit=0);
        void stack_pop();
        int save(EDL *edl, char *filename, int stat);
        int save(int save_as);
@@ -272,12 +285,14 @@ public:
        void close_mixers(int result=1);
        void open_mixers();
        ZWindow *get_mixer(Mixer *&mixer);
-       void del_mixer(ZWindow *zwindow);
+       ZWindow *get_mixer(int idx);
+       void close_mixer(ZWindow *zwindow);
        int mixer_track_active(Track *track);
        void update_mixer_tracks();
        void start_mixer();
        int select_zwindow(ZWindow *zwindow);
        void tile_mixers();
+       void set_gang_tracks(int v);
        int load_filenames(ArrayList<char*> *filenames,
                int load_mode = LOADMODE_REPLACE,
                int edl_mode = LOADMODE_EDL_CLIP,
@@ -291,6 +306,8 @@ public:
        int interrupt_indexes();  // Stop index building
 
        int redraw_time_dependancies();     // after reconfiguring the time format, sample rate, frame rate
+       void draw_trackmovement();          // after reconfiguring tracks/patchbay guis
+       DrawTrackMovement *redraw_tracks;
 
 // =========================================== movement
 
@@ -391,13 +408,13 @@ public:
                AUDIO_5_1_TO_2,
                AUDIO_1_TO_1
        };
-       void add_audio_track_entry(int above, Track *dst);
-       int add_audio_track(int above, Track *dst);
        void add_clip_to_edl(EDL *edl);
-       void add_video_track_entry(Track *dst = 0);
-       int add_video_track(int above, Track *dst);
-       void add_subttl_track_entry(Track *dst = 0);
-       int add_subttl_track(int above, Track *dst);
+       void add_audio_track_entry(int above, Track *dst);
+       Track *add_audio_track(int above, Track *dst);
+       void add_video_track_entry(int above, Track *dst);
+       Track *add_video_track(int above, Track *dst);
+       void add_subttl_track_entry(int above, Track *dst);
+       Track *add_subttl_track(int above, Track *dst);
 
        void asset_to_all();
        void asset_to_size();
@@ -442,7 +459,7 @@ public:
 
 // TrackCanvas calls this to insert multiple effects from the drag_pluginservers
 // into pluginset_highlighted.
-       void insert_effects_canvas(double start, double length);
+       void insert_effects_canvas(Track *dest_track, double start, double length);
 
 // CWindow calls this to insert multiple effects from
 // the drag_pluginservers array.
@@ -483,6 +500,10 @@ public:
        void move_tracks_down();
        void move_track_up(Track *track);
        void move_tracks_up();
+       void swap_track_down(Track *track);
+       void swap_tracks_down();
+       void swap_track_up(Track *track);
+       void swap_tracks_up();
        void mute_selection();
        void new_folder(const char *new_folder, int is_clips);
        void delete_folder(char *folder);
@@ -598,6 +619,7 @@ public:
        void dump_edl(FILE *fp=stdout);
        void dump_undo(FILE *fp=stdout);
        void dump_exe(FILE *fp=stdout);
+       void dump_caches(FILE *fp=stdout);
        static void trap_hook(FILE *fp, void *vp);
 
        void reset_android_remote();
index 7e6c644548f55b4d741836c455f272f39994df44..6242b788bc027a81b389e66075b923c27febae55 100644 (file)
@@ -85,7 +85,8 @@
 void MWindow::add_audio_track_entry(int above, Track *dst)
 {
        undo_before();
-       add_audio_track(above, dst);
+       Track *track = add_audio_track(above, dst);
+       track->master = 1;
        save_backup();
        undo_after(_("add track"), LOAD_ALL);
 
@@ -95,10 +96,11 @@ void MWindow::add_audio_track_entry(int above, Track *dst)
        cwindow->refresh_frame(CHANGE_EDL);
 }
 
-void MWindow::add_video_track_entry(Track *dst)
+void MWindow::add_video_track_entry(int above, Track *dst)
 {
        undo_before();
-       add_video_track(1, dst);
+       Track *track = add_video_track(above, dst);
+       track->master = 1;
        undo_after(_("add track"), LOAD_ALL);
 
        restart_brender();
@@ -109,10 +111,11 @@ void MWindow::add_video_track_entry(Track *dst)
        save_backup();
 }
 
-void MWindow::add_subttl_track_entry(Track *dst)
+void MWindow::add_subttl_track_entry(int above, Track *dst)
 {
        undo_before();
-       add_subttl_track(1, dst);
+       Track *track = add_subttl_track(above, dst);
+       track->master = 1;
        undo_after(_("add track"), LOAD_ALL);
 
        restart_brender();
@@ -124,28 +127,28 @@ void MWindow::add_subttl_track_entry(Track *dst)
 }
 
 
-int MWindow::add_audio_track(int above, Track *dst)
+Track *MWindow::add_audio_track(int above, Track *dst)
 {
-       edl->tracks->add_audio_track(above, dst);
+       Track *track = edl->tracks->add_audio_track(above, dst);
        edl->tracks->update_y_pixels(theme);
        save_backup();
-       return 0;
+       return track;
 }
 
-int MWindow::add_video_track(int above, Track *dst)
+Track *MWindow::add_video_track(int above, Track *dst)
 {
-       edl->tracks->add_video_track(above, dst);
+       Track *track = edl->tracks->add_video_track(above, dst);
        edl->tracks->update_y_pixels(theme);
        save_backup();
-       return 0;
+       return track;
 }
 
-int MWindow::add_subttl_track(int above, Track *dst)
+Track *MWindow::add_subttl_track(int above, Track *dst)
 {
-       edl->tracks->add_subttl_track(above, dst);
+       Track *track = edl->tracks->add_subttl_track(above, dst);
        edl->tracks->update_y_pixels(theme);
        save_backup();
-       return 0;
+       return track;
 }
 
 void MWindow::asset_to_all()
@@ -179,7 +182,7 @@ void MWindow::asset_to_all()
 
                        for( Track *current=edl->tracks->first; current; current=NEXT ) {
                                if( current->data_type == TRACK_VIDEO /* &&
-                                       current->record */  ) {
+                                       current->is_armed() */  ) {
                                        current->track_w = w;
                                        current->track_h = h;
                                }
@@ -761,19 +764,40 @@ void MWindow::insert(double position, FileXML *file,
 //printf("MWindow::insert 6 %p\n", vwindow->get_edl());
 }
 
-void MWindow::insert_effects_canvas(double start,
-       double length)
+void MWindow::insert_effects_canvas(Track *dest_track, double start, double length)
 {
-       Track *dest_track = session->track_highlighted;
-       if( !dest_track ) return;
-
        undo_before();
 
-       for( int i=0; i<session->drag_pluginservers->total; ++i ) {
-               PluginServer *plugin = session->drag_pluginservers->values[i];
-               insert_effect(plugin->title, 0, dest_track,
-                       i == 0 ? session->pluginset_highlighted : 0,
-                       start, length, PLUGIN_STANDALONE);
+       ArrayList<SharedLocation> shared_locations;
+       PluginSet *pluginset = session->pluginset_highlighted;
+       int gang = edl->session->gang_tracks != GANG_NONE ? 1 : 0;
+       int data_type = dest_track->data_type;
+       int first_track = 1;
+
+       for( Track *track=dest_track; track; track=track->next ) {
+               if( gang && track->master && !first_track ) break;
+               if( track->data_type != data_type ) continue;
+               if( !track->is_armed() ) continue;
+               int module = edl->tracks->number_of(track);
+               for( int i=0; i<session->drag_pluginservers->total; ++i ) {
+                       PluginServer *plugin = session->drag_pluginservers->values[i];
+                       int shared = gang; // && plugin->multichannel ? 1 : 0;
+                       int plugin_type = !first_track && shared ?
+                               PLUGIN_SHAREDPLUGIN : PLUGIN_STANDALONE;
+                       SharedLocation *shared_location = !first_track ?
+                               &shared_locations[i] : &shared_locations.append();
+                       insert_effect(plugin->title, shared_location, track,
+                                       pluginset, start, length, plugin_type);
+                       if( first_track && shared ) {
+                               shared_location->module = module;
+                               shared_location->plugin = pluginset ?
+                                       track->plugin_set.number_of(pluginset) :
+                                       track->plugin_set.total-1 ;
+                       }
+               }
+               if( !gang ) break;
+               first_track = 0;
+               pluginset = 0;
        }
 
        save_backup();
@@ -787,8 +811,6 @@ void MWindow::insert_effects_cwindow(Track *dest_track)
 {
        if( !dest_track ) return;
 
-       undo_before();
-
        double start = 0;
        double length = dest_track->get_length();
 
@@ -799,55 +821,45 @@ void MWindow::insert_effects_cwindow(Track *dest_track)
                        edl->local_session->get_selectionstart();
        }
 
-       for( int i=0; i<session->drag_pluginservers->total; ++i ) {
-               PluginServer *plugin = session->drag_pluginservers->values[i];
-               insert_effect(plugin->title, 0, dest_track, 0,
-                       start, length, PLUGIN_STANDALONE);
-       }
-
-       save_backup();
-       undo_after(_("insert effect"), LOAD_EDITS | LOAD_PATCHES);
-       restart_brender();
-       sync_parameters(CHANGE_EDL);
+       insert_effects_canvas(dest_track, start, length);
        gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
 }
 
-void MWindow::insert_effect(char *title,
-       SharedLocation *shared_location,
-       int data_type,
-       int plugin_type,
-       int single_standalone)
+void MWindow::insert_effect(char *title, SharedLocation *shared_location,
+               int data_type, int plugin_type, int single_standalone)
 {
        Track *current = edl->tracks->first;
        SharedLocation shared_location_local;
        shared_location_local.copy_from(shared_location);
        int first_track = 1;
+       double start_pos = edl->local_session->get_selectionstart(1);
+       double end_pos = edl->local_session->get_selectionend(1);
        for( ; current; current=NEXT ) {
-               if( current->data_type == data_type &&
-                       current->record ) {
-                       insert_effect(title, &shared_location_local,
-                               current, 0, 0, 0, plugin_type);
-
-                       if( first_track ) {
-                               if( plugin_type == PLUGIN_STANDALONE && single_standalone ) {
-                                       plugin_type = PLUGIN_SHAREDPLUGIN;
-                                       shared_location_local.module = edl->tracks->number_of(current);
-                                       shared_location_local.plugin = current->plugin_set.total - 1;
-                               }
-                               first_track = 0;
+               if( current->data_type != data_type ) continue;
+               if( !current->is_armed() ) continue;
+               double start = start_pos, end = end_pos;
+               if( plugin_type == PLUGIN_STANDALONE && start >= end ) {
+                       start = 0;
+                       end = current->get_length();
+               }
+               double length = end - start;
+               insert_effect(title, &shared_location_local,
+                               current, 0, start, length, plugin_type);
+               if( first_track ) {
+                       if( plugin_type == PLUGIN_STANDALONE && single_standalone ) {
+                               plugin_type = PLUGIN_SHAREDPLUGIN;
+                               shared_location_local.module = edl->tracks->number_of(current);
+                               shared_location_local.plugin = current->plugin_set.total - 1;
+                               start_pos = start;  end_pos = end;
                        }
+                       first_track = 0;
                }
        }
 }
 
-
 void MWindow::insert_effect(char *title,
-       SharedLocation *shared_location,
-       Track *track,
-       PluginSet *plugin_set,
-       double start,
-       double length,
-       int plugin_type)
+               SharedLocation *shared_location, Track *track, PluginSet *plugin_set,
+               double start, double length, int plugin_type)
 {
        KeyFrame *default_keyframe = 0;
        PluginServer *server = 0;
@@ -860,9 +872,8 @@ void MWindow::insert_effect(char *title,
                server->save_data(default_keyframe);
        }
 // Insert plugin object
-       track->insert_effect(title, shared_location,
-               default_keyframe, plugin_set,
-               start, length, plugin_type);
+       track->insert_effect(title, shared_location, default_keyframe,
+                       plugin_set, start, length, plugin_type);
        track->optimize();
 
        if( plugin_type == PLUGIN_STANDALONE ) {
@@ -1194,6 +1205,56 @@ void MWindow::move_tracks_up()
 }
 
 
+void MWindow::swap_track_down(Track *track)
+{
+       undo_before();
+       edl->tracks->swap_track_down(track);
+       save_backup();
+       undo_after(_("swap track down"), LOAD_ALL);
+
+       restart_brender();
+       gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
+       sync_parameters(CHANGE_EDL);
+       save_backup();
+}
+
+void MWindow::swap_tracks_down()
+{
+       undo_before();
+       edl->tracks->swap_tracks_down();
+       save_backup();
+       undo_after(_("swap tracks down"), LOAD_ALL);
+
+       restart_brender();
+       gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
+       sync_parameters(CHANGE_EDL);
+       save_backup();
+}
+
+void MWindow::swap_track_up(Track *track)
+{
+       undo_before();
+       edl->tracks->swap_track_up(track);
+       save_backup();
+       undo_after(_("swap track up"), LOAD_ALL);
+       restart_brender();
+       gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
+       sync_parameters(CHANGE_EDL);
+       save_backup();
+}
+
+void MWindow::swap_tracks_up()
+{
+       undo_before();
+       edl->tracks->swap_tracks_up();
+       save_backup();
+       undo_after(_("swap tracks up"), LOAD_ALL);
+       restart_brender();
+       gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
+       sync_parameters(CHANGE_EDL);
+}
+
+
 void MWindow::mute_selection()
 {
        double start = edl->local_session->get_selectionstart();
@@ -1522,6 +1583,7 @@ int MWindow::paste_edls(ArrayList<EDL*> *new_edls, int load_mode,
                need_new_tracks = 1;
                for( int i=0; i<new_edls->total; ++i ) {
                        EDL *new_edl = new_edls->values[i];
+                       int first_track = 1;
                        for( Track *current=new_edl->tracks->first; current; current=NEXT ) {
                                switch( current->data_type ) {
                                case TRACK_VIDEO:
@@ -1537,6 +1599,10 @@ int MWindow::paste_edls(ArrayList<EDL*> *new_edls, int load_mode,
                                default:
                                        continue;
                                }
+                               if( first_track ) {
+                                       edl->tracks->last->master = 1;
+                                       first_track = 0;
+                               }
 // re-label only if not already labeled
                                if( new_edl->local_session->asset2edl )
                                        strcpy(current->title, edl->tracks->last->title);
@@ -1554,7 +1620,7 @@ int MWindow::paste_edls(ArrayList<EDL*> *new_edls, int load_mode,
            load_mode == LOADMODE_PASTE ) {
                Track *current = first_track ? first_track : edl->tracks->first;
                for( ; current; current=NEXT ) {
-                       if( current->record ) {
+                       if( current->is_armed() ) {
                                destination_tracks.append(current);
                        }
                }
@@ -1658,14 +1724,14 @@ int MWindow::paste_edls(ArrayList<EDL*> *new_edls, int load_mode,
                                if( destination_track < destination_tracks.total &&
                                    destination_tracks.values[destination_track]->data_type == new_track->data_type ) {
                                        Track *track = destination_tracks.values[destination_track];
-
 // Replace default keyframes if first EDL and new tracks were created.
 // This means data copied from one track and pasted to another won't retain
 // the camera position unless it's a keyframe.  If it did, previous data in the
 // track might get unknowingly corrupted.  Ideally we would detect when differing
 // default keyframes existed and create discrete keyframes for both.
                                        int replace_default = (i == 0) && need_new_tracks;
-
+// master tracks are the first track in each new edl when new tracks are created
+                                       int master = track->master;
 //printf("MWindow::paste_edls 1 %d\n", replace_default);
 // Insert new track at current position
                                        switch( load_mode ) {
@@ -1691,6 +1757,7 @@ int MWindow::paste_edls(ArrayList<EDL*> *new_edls, int load_mode,
 //PRINT_TRACE
                                        track->insert_track(new_track, current_position, replace_default,
                                                edit_plugins, edit_autos, edl_length);
+                                       if( master ) track->master = 1;
 //PRINT_TRACE
                                }
 
@@ -2164,7 +2231,7 @@ void MWindow::save_clip(EDL *new_edl, const char *txt)
        Track *track = new_edl->tracks->first;
        const char *path = edl->path;
        for( ; (!path || !*path) && track; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                Edit *edit = track->edits->first;
                if( !edit ) continue;
                Indexable *indexable = edit->get_source();
@@ -2391,7 +2458,7 @@ void MWindow::remap_audio(int pattern)
        int current_track = 0;
        for( Track *current=edl->tracks->first; current; current=NEXT ) {
                if( current->data_type == TRACK_AUDIO &&
-                       current->record ) {
+                       current->is_armed() ) {
                        Autos *pan_autos = current->automation->autos[AUTOMATION_PAN];
                        PanAuto *pan_auto = (PanAuto*)pan_autos->get_auto_for_editing(-1);
 
index 7b92aa3258ae2a6635b163b0aaaff3a80329e418..9c3dc9d8fa0b5df2798f9bcbbe648ad7d0cbc1cb 100644 (file)
@@ -316,7 +316,7 @@ int MWindowGUI::resize_event(int w, int h)
 //printf("MWindowGUI::resize_event %d\n", __LINE__);
        mwindow->session->mwindow_w = w;
        mwindow->session->mwindow_h = h;
-       int x1 = get_w() - MainShBtns::calculate_w(-1, 0, -1) - xS(5);
+       int x1 = w - MainShBtns::calculate_w(-1, 0, -1) - xS(5);
        mainshbtns->reposition_window(x1, -1);
        int x2 = x1 - mwindow->theme->stack_button_w - xS(5);
        stack_button->reposition_window(x2, stack_button->get_y());
@@ -1256,18 +1256,18 @@ int MWindowGUI::keypress_event()
                        if( (this_track = pane[i]->over_patchbay()) != 0 ) break;
                }
 
-               if( get_keypress() == TAB ) { // Switch the record button
+               if( get_keypress() == TAB ) { // Switch the armed button
                        if( this_track )
-                               this_track->record = !this_track->record ? 1 : 0;
+                               this_track->armed = !this_track->armed ? 1 : 0;
                }
                else {
                        int total_selected = mwindow->edl->tracks->total_of(Tracks::RECORD);
                        // all selected if nothing previously selected or
                        // if this patch was previously the only one selected and armed
                        int selected = !total_selected || (total_selected == 1 &&
-                               this_track && this_track->record ) ? 1 : 0;
+                               this_track && this_track->armed ) ? 1 : 0;
                        mwindow->edl->tracks->select_all(Tracks::RECORD, selected);
-                       if( !selected && this_track ) this_track->record = 1;
+                       if( !selected && this_track ) this_track->armed = 1;
                }
 
                update(0, NORMAL_DRAW, 0, 0, 1, 0, 1);
index 5abe4e6c20b15cf77c96a46d198f0856b19a085f..2c0479bb947953c8f1383ea1035831ce999498f2 100644 (file)
@@ -356,17 +356,13 @@ void MWindow::zoom_amp(int64_t zoom_amp)
 void MWindow::zoom_atrack(int64_t zoom)
 {
        int64_t old_zoom = edl->local_session->zoom_atrack;
-// scale waveforms
-       edl->local_session->zoom_y = (int64_t)((float)edl->local_session->zoom_y *
-                       zoom / old_zoom);
-       CLAMP(edl->local_session->zoom_y, MIN_AMP_ZOOM, MAX_AMP_ZOOM);
+       CLAMP(zoom, MIN_TRACK_ZOOM, MAX_TRACK_ZOOM);
+       edl->local_session->zoom_atrack = zoom;
 
-// scale tracks
        edl->local_session->zoom_atrack = zoom;
        for( Track *track= edl->tracks->first; track; track=track->next ) {
                if( track->data_type != TRACK_AUDIO ) continue;
-               track->data_h = track->data_h * zoom / old_zoom;
-               bclamp(track->data_h, MIN_TRACK_ZOOM, MAX_TRACK_ZOOM);
+               track->data_h = zoom;
        }
 // shift row position
        for( int i=0; i<TOTAL_PANES; ++i ) edl->local_session->track_start[i] =
@@ -378,12 +374,12 @@ void MWindow::zoom_atrack(int64_t zoom)
 void MWindow::zoom_vtrack(int64_t zoom)
 {
        int64_t old_zoom = edl->local_session->zoom_vtrack;
-// scale tracks
+       CLAMP(zoom, MIN_TRACK_ZOOM, MAX_TRACK_ZOOM);
        edl->local_session->zoom_vtrack = zoom;
+
        for( Track *track= edl->tracks->first; track; track=track->next ) {
                if( track->data_type != TRACK_VIDEO ) continue;
-               track->data_h = track->data_h * zoom / old_zoom;
-               bclamp(track->data_h, MIN_TRACK_ZOOM, MAX_TRACK_ZOOM);
+               track->data_h = zoom;
        }
 // shift row position
        for( int i=0; i<TOTAL_PANES; ++i ) edl->local_session->track_start[i] =
@@ -660,7 +656,7 @@ int MWindow::nearest_plugin_keyframe(int shift_down, int dir)
        double position = dir == PLAY_FORWARD ? end : start;
        double new_position = dir == PLAY_FORWARD ? start : end;
        for( Track *track=edl->tracks->first; track; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                for( int i=0; i<track->plugin_set.size(); ++i ) {
                        PluginSet *plugin_set = track->plugin_set[i];
                        int64_t pos = track->to_units(position, 0);
@@ -698,7 +694,7 @@ int MWindow::nearest_auto_keyframe(int shift_down, int dir)
        double position = dir == PLAY_FORWARD ? end : start;
        double new_position = dir == PLAY_FORWARD ? start : end;
        for( Track *track=edl->tracks->first; track; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                int64_t pos = track->to_units(position, 0);
                for( int i=0; i<AUTOMATION_TOTAL; ++i ) {
                        Autos *autos = track->automation->autos[i];
index d60a5be0ae17acc5c7aa3102aea5128251c97586..a76d736ae5839f9f03f87329bcd45238af6ad19b 100644 (file)
@@ -101,8 +101,10 @@ PackageRenderer::PackageRenderer()
 PackageRenderer::~PackageRenderer()
 {
        delete command;
-       delete audio_cache;
-       delete video_cache;
+       if( audio_cache )
+               audio_cache->remove_user();
+       if( video_cache )
+               video_cache->remove_user();
        delete vconfig;
        delete aconfig;
        delete timer;
index 3292eeb5543911fe576d85f51b266b77d4de1e75..381e1c0f4d925ce329b171c6c2d23ada7bd9c494 100644 (file)
@@ -283,6 +283,7 @@ int PatchBay::cursor_motion_event()
                                track;
                                track = track->next)
                        {
+                               if( track->is_hidden() ) continue;
                                int y = track->y_pixel - mwindow->edl->local_session->track_start[pane->number];
                                int h = track->vertical_span(mwindow->theme);
                                if(cursor_y >= y && cursor_y < y + h)
@@ -301,16 +302,16 @@ int PatchBay::cursor_motion_event()
                                                        }
                                                        break;
                                                case Tracks::RECORD:
-                                                       if(track->record != new_status)
+                                                       if(track->armed != new_status)
                                                        {
-                                                               track->record = new_status;
+                                                               track->armed = new_status;
                                                                update_gui = 1;
                                                        }
                                                        break;
                                                case Tracks::GANG:
-                                                       if(track->gang != new_status)
+                                                       if(track->ganged != new_status)
                                                        {
-                                                               track->gang = new_status;
+                                                               track->ganged = new_status;
                                                                update_gui = 1;
                                                        }
                                                        break;
@@ -451,10 +452,9 @@ int PatchBay::update()
 // Every patch has a GUI regardless of whether or not it is visible.
 // Make sure GUI's are allocated for every patch and deleted for non-existant
 // patches.
-       for(Track *current = mwindow->edl->tracks->first;
-               current;
-               current = NEXT, patch_count++)
+       for(Track *current = mwindow->edl->tracks->first; current; current = NEXT)
        {
+               if( current->is_hidden() ) continue;
                PatchGUI *patchgui = 0;
                int y = current->y_pixel;
                y -= mwindow->edl->local_session->track_start[pane->number];
@@ -502,6 +502,7 @@ int PatchBay::update()
                        patches.append(patchgui);
                        patchgui->create_objects();
                }
+               ++patch_count;
        }
 
        while(patches.total > patch_count)
@@ -521,8 +522,8 @@ void PatchBay::synchronize_faders(float change, int data_type, Track *skip)
                current = NEXT)
        {
                if(current->data_type == data_type &&
-                       current->gang &&
-                       current->record &&
+                       current->armed_gang(skip) &&
+                       current->is_armed() &&
                        current != skip)
                {
                        FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[AUTOMATION_FADE];
@@ -551,15 +552,11 @@ void PatchBay::synchronize_faders(float change, int data_type, Track *skip)
 
 void PatchBay::synchronize_nudge(int64_t value, Track *skip)
 {
-       for(Track *current = mwindow->edl->tracks->first;
-               current;
-               current = NEXT)
-       {
-               if(current->data_type == skip->data_type &&
-                       current->gang &&
-                       current->record &&
-                       current != skip)
-               {
+       Track *current = mwindow->edl->tracks->first;
+       for( ; current; current = NEXT ) {
+               if( current->data_type == skip->data_type &&
+                   current->armed_gang(skip) && current->is_armed() &&
+                   current != skip ) {
                        current->nudge = value;
                        PatchGUI *patch = get_patch_of(current);
                        if(patch) patch->update(patch->x, patch->y);
index cb2c240307a5568f94b886e0bc94652c02947c5a..f99601c1178f91db5306f1d3680d95efd986bf39 100644 (file)
@@ -60,9 +60,10 @@ PatchGUI::PatchGUI(MWindow *mwindow,
        record = 0;
        play = 0;
 //     automate = 0;
-       gang = 0;
        draw = 0;
        mute = 0;
+       gang = 0;
+       master = 0;
        zoom = 0;
        expand = 0;
        nudge = 0;
@@ -78,9 +79,10 @@ PatchGUI::~PatchGUI()
        delete record;
        delete play;
 //     delete automate;
-       delete gang;
        delete draw;
        delete mute;
+       delete gang;
+       delete master;
        delete zoom;
        delete expand;
        delete nudge;
@@ -94,6 +96,7 @@ void PatchGUI::create_objects()
 
 int PatchGUI::reposition(int x, int y)
 {
+       if( track->is_hidden() ) return 0;
        int x1 = 0;
        int y1 = 0;
 
@@ -114,13 +117,16 @@ int PatchGUI::reposition(int x, int y)
                        x1 += record->get_w();
 //                     automate->reposition_window(x1, y1 + y);
 //                     x1 += automate->get_w();
-                       gang->reposition_window(gang->get_x(), y1 + y);
-                       x1 += gang->get_w();
                        draw->reposition_window(draw->get_x(), y1 + y);
                        x1 += draw->get_w();
                        mute->reposition_window(mute->get_x(), y1 + y);
                        x1 += mute->get_w();
+                       gang->reposition_window(gang->get_x(), y1 + y);
+                       x1 += gang->get_w();
+                       master->reposition_window(master->get_x(), y1 + y);
+                       x1 += master->get_w();
                        zoom->reposition_window(zoom->get_x(), y1 + y);
+//                     x1 += zoom->get_w();
                }
                y1 += mwindow->theme->play_h;
        }
@@ -136,6 +142,7 @@ int PatchGUI::reposition(int x, int y)
 
 int PatchGUI::update(int x, int y)
 {
+       if( track->is_hidden() ) return 0;
 //TRACE("PatchGUI::update 1");
        reposition(x, y);
 //TRACE("PatchGUI::update 10");
@@ -171,17 +178,19 @@ int PatchGUI::update(int x, int y)
                if( h < y2 ) {
                        delete play;    play = 0;
                        delete record;  record = 0;
-                       delete gang;    gang = 0;
                        delete draw;    draw = 0;
                        delete mute;    mute = 0;
+                       delete gang;    gang = 0;
+                       delete master;  master = 0;
                        delete zoom;    zoom = 0;
                }
                else {
                        play->update(track->play);
-                       record->update(track->record);
-                       gang->update(track->gang);
+                       record->update(track->armed);
                        draw->update(track->draw);
                        mute->update(mwindow->get_int_auto(this, AUTOMATION_MUTE)->value);
+                       gang->update(track->ganged);
+                       master->update(track->master);
                }
        }
        else if( h >= y2 ) {
@@ -190,13 +199,16 @@ int PatchGUI::update(int x, int y)
                x1 += play->get_w();
                patchbay->add_subwindow(record = new RecordPatch(mwindow, this, x1 + x, y1 + y));
                x1 += record->get_w();
-               patchbay->add_subwindow(gang = new GangPatch(mwindow, this, x1 + x, y1 + y));
-               x1 += gang->get_w();
                patchbay->add_subwindow(draw = new DrawPatch(mwindow, this, x1 + x, y1 + y));
                x1 += draw->get_w();
                patchbay->add_subwindow(mute = new MutePatch(mwindow, this, x1 + x, y1 + y));
                x1 += mute->get_w();
+               patchbay->add_subwindow(gang = new GangPatch(mwindow, this, x1 + x, y1 + y));
+               x1 += gang->get_w();
+               patchbay->add_subwindow(master = new MasterPatch(mwindow, this, x1 + x, y1 + y));
+               x1 += master->get_w();
                patchbay->add_subwindow(zoom = new ZoomPatch(mwindow, this, x1 + x, y1 + y));
+//             x1 += zoom->get_w();
        }
        if( play )
                y1 = y2;
@@ -364,7 +376,7 @@ RecordPatch::RecordPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
  : BC_Toggle(x,
                y,
                mwindow->theme->get_image_set("recordpatch_data"),
-               patch->track->record,
+               patch->track->armed,
                "",
                0,
                0,
@@ -386,8 +398,8 @@ int RecordPatch::button_press_event()
                patch->toggle_behavior(Tracks::RECORD,
                        get_value(),
                        this,
-                       &patch->track->record);
-               patch->title->set_back_color(patch->track->record ?
+                       &patch->track->armed);
+               patch->title->set_back_color(patch->track->armed ?
                        get_resources()->text_background :
                        get_resources()->text_background_disarmed);
                patch->title->set_text_row(0);
@@ -421,7 +433,7 @@ int RecordPatch::button_release_event()
 GangPatch::GangPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
  : BC_Toggle(x, y,
                mwindow->theme->get_image_set("gangpatch_data"),
-               patch->track->gang,
+               patch->track->ganged,
                "",
                0,
                0,
@@ -443,7 +455,7 @@ int GangPatch::button_press_event()
                patch->toggle_behavior(Tracks::GANG,
                        get_value(),
                        this,
-                       &patch->track->gang);
+                       &patch->track->ganged);
                return 1;
        }
        return 0;
@@ -580,7 +592,7 @@ int MutePatch::button_release_event()
 
 
 ZoomPatch::ZoomPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
- : BC_Tumbler(x, y)
+ : BC_Tumbler(x, y, mwindow->theme->get_image_set("tumblepatch_data"))
 {
        this->mwindow = mwindow;
        this->patch = patch;
@@ -605,15 +617,26 @@ int ZoomPatch::handle_down_event()
 }
 
 
+MasterPatch::MasterPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
+ : BC_Toggle(x, y, mwindow->theme->get_image_set("masterpatch_data"),
+               patch->track->master, "", 0, 0, 0)
+{
+       this->mwindow = mwindow;
+       this->patch = patch;
+       set_tooltip(_("Master Track"));
+}
+
+int MasterPatch::handle_event()
+{
+       patch->track->master = patch->track->master ? 0 : 1;
+       mwindow->draw_trackmovement();  // delayed, can delete *this
+       return 1;
+}
+
+
 ExpandPatch::ExpandPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
- : BC_Toggle(x,
-               y,
-               mwindow->theme->get_image_set("expandpatch_data"),
-               patch->track->expand_view,
-               "",
-               0,
-               0,
-               0)
+ : BC_Toggle(x, y, mwindow->theme->get_image_set("expandpatch_data"),
+               patch->track->expand_view, "", 0, 0, 0)
 {
        this->mwindow = mwindow;
        this->patch = patch;
@@ -655,14 +678,14 @@ TitlePatch::TitlePatch(MWindow *mwindow, PatchGUI *patch, int x, int y, int w)
 {
        this->mwindow = mwindow;
        this->patch = patch;
-       set_back_color(patch->track->record ?
+       set_back_color(patch->track->armed ?
                        get_resources()->text_background :
                        get_resources()->text_background_disarmed);
 }
 
 void TitlePatch::update(const char *text)
 {
-       set_back_color(patch->track->record ?
+       set_back_color(patch->track->armed ?
                        get_resources()->text_background :
                        get_resources()->text_background_disarmed);
        BC_TextBox::update(text);
@@ -706,7 +729,7 @@ void NudgePatch::set_value(int64_t value)
        mwindow->undo->update_undo_before(_("nudge."), this);
        patch->track->nudge = value;
 
-       if(patch->track->gang && patch->track->record)
+       if(patch->track->is_ganged() && patch->track->is_armed())
                patch->patchbay->synchronize_nudge(patch->track->nudge, patch->track);
 
        mwindow->undo->update_undo_after(_("nudge."), LOAD_PATCHES);
index a120beed07dcd21e7cbb09e284c670ca6c64c71e..edbfddedfb7d588d43f4547e314d971f8749bc14 100644 (file)
@@ -39,6 +39,7 @@ class GangPatch;
 class DrawPatch;
 class MutePatch;
 class ZoomPatch;
+class MasterPatch;
 class ExpandPatch;
 class NudgePatch;
 class MixPatch;
@@ -84,6 +85,7 @@ public:
        DrawPatch *draw;
        MutePatch *mute;
        ZoomPatch *zoom;
+       MasterPatch *master;
        ExpandPatch *expand;
        NudgePatch *nudge;
        MixPatch *mix;
@@ -172,6 +174,15 @@ public:
        PatchGUI *patch;
 };
 
+class MasterPatch : public BC_Toggle
+{
+public:
+       MasterPatch(MWindow *mwindow, PatchGUI *patch, int x, int y);
+       int handle_event();
+       MWindow *mwindow;
+       PatchGUI *patch;
+};
+
 class ExpandPatch : public BC_Toggle
 {
 public:
index 3e00f9d8e828cb6269441d7865e29033f9ccf1db..e9acd3c70f8c9212170ec900c36ceb078209ee3f 100644 (file)
@@ -338,6 +338,13 @@ public:
        PreferencesWindow *pwindow;
 };
 
+class PrefsUseHWDevItems : public ArrayList<BC_ListBoxItem *>
+{
+public:
+       PrefsUseHWDevItems() {}
+       ~PrefsUseHWDevItems() { remove_all_objects(); }
+};
+
 class PrefsUseHWDev : public BC_PopupTextBox
 {
 public:
@@ -347,7 +354,7 @@ public:
        int handle_event();
 
        PreferencesWindow *pwindow;
-       ArrayList<BC_ListBoxItem *> hw_dev_names;
+       PrefsUseHWDevItems hw_dev_names;
 };
 
 
index 8ce98234c3ffc7ed2b0ed6e4c00b4f6e3fa749ee..82bd7bb6587b930b77caa7f4da7673255539b3a3 100644 (file)
@@ -85,8 +85,10 @@ PlaybackEngine::~PlaybackEngine()
        Thread::join();
        delete preferences;
        delete_render_engine();
-       delete audio_cache;
-       delete video_cache;
+       if( audio_cache )
+               audio_cache->remove_user();
+       if( video_cache )
+               video_cache->remove_user();
        delete tracking_lock;
        delete tracking_done;
        delete pause_lock;
@@ -162,10 +164,12 @@ void PlaybackEngine::wait_render_engine()
 
 void PlaybackEngine::create_cache()
 {
-       if(audio_cache) { delete audio_cache;  audio_cache = 0; }
-       if(video_cache) { delete video_cache;  video_cache = 0; }
-       if(!audio_cache) audio_cache = new CICache(preferences);
-       if(!video_cache) video_cache = new CICache(preferences);
+       if( audio_cache )
+               audio_cache->remove_user();
+       if( video_cache )
+               video_cache->remove_user();
+       audio_cache = new CICache(preferences);
+       video_cache = new CICache(preferences);
 }
 
 
index d9d9a48af851b5ed30df9bb1cdd323dac2e60a7a..8caf4678bb3493ff5b7e0326ab6d82c5bf5d8d3e 100644 (file)
@@ -30,6 +30,7 @@
 #include "preferences.h"
 #include "shuttle.h"
 #include "theme.h"
+#include "tracks.h"
 #include "transportque.h"
 #include "vframe.h"
 
@@ -329,21 +330,14 @@ EDL* PlayTransport::get_edl()
        return mwindow->edl;
 }
 
-int PlayTransport::pause_transport()
+int PlayTransport::set_transport(int mode)
 {
-       if(active_button) active_button->set_mode(PLAY_MODE);
-       return 0;
-}
-
-
-int PlayTransport::reset_transport()
-{
-       fast_reverse->set_mode(PLAY_MODE);
-       reverse_play->set_mode(PLAY_MODE);
-       forward_play->set_mode(PLAY_MODE);
-       frame_reverse_play->set_mode(PLAY_MODE);
-       frame_forward_play->set_mode(PLAY_MODE);
-       fast_play->set_mode(PLAY_MODE);
+       fast_reverse->set_mode(mode);
+       reverse_play->set_mode(mode);
+       forward_play->set_mode(mode);
+       frame_reverse_play->set_mode(mode);
+       frame_forward_play->set_mode(mode);
+       fast_play->set_mode(mode);
        return 0;
 }
 
@@ -358,10 +352,29 @@ PTransportButton::~PTransportButton()
 {
 }
 
-int PTransportButton::set_mode(int mode)
+void PTransportButton::set_mode(int mode)
 {
        this->mode = mode;
-       return 0;
+}
+
+void PTransportButton::loop_mode(int dir)
+{
+       if( mode != LOOP_MODE ) return;
+       EDL *edl = transport->get_edl();
+       if( !edl ) return;
+       PlaybackEngine *engine = transport->engine;
+       if( !engine || engine->is_playing_back ) return;
+       double position = engine->get_tracking_position();
+       switch( dir ) {
+       case PLAY_FORWARD:
+               if( position >= edl->tracks->total_playable_length() )
+                       transport->goto_start();
+               break;
+       case PLAY_REVERSE:
+               if( position <= 0 )
+                       transport->goto_end();
+               break;
+       }
 }
 
 int PTransportButton::play_command(const char *lock_msg, int command)
@@ -398,6 +411,7 @@ FastReverseButton::FastReverseButton(MWindow *mwindow, PlayTransport *transport,
 }
 int FastReverseButton::handle_event()
 {
+       loop_mode(PLAY_REVERSE);
        return play_command("FastReverseButton::handle_event", FAST_REWIND);
 }
 
@@ -410,6 +424,7 @@ ReverseButton::ReverseButton(MWindow *mwindow, PlayTransport *transport, int x,
 }
 int ReverseButton::handle_event()
 {
+       loop_mode(PLAY_REVERSE);
        return play_command("ReverseButton::handle_event", NORMAL_REWIND);
 }
 
@@ -437,6 +452,7 @@ PlayButton::PlayButton(MWindow *mwindow, PlayTransport *transport, int x, int y)
 }
 int PlayButton::handle_event()
 {
+       loop_mode(PLAY_FORWARD);
        return play_command("PlayButton::handle_event", NORMAL_FWD);
 }
 
@@ -466,6 +482,7 @@ FastPlayButton::FastPlayButton(MWindow *mwindow, PlayTransport *transport, int x
 }
 int FastPlayButton::handle_event()
 {
+       loop_mode(PLAY_FORWARD);
        return play_command("FastPlayButton::handle_event", FAST_FWD);
 }
 
index 20d989997b31058ebaeb086b21b8a63131086707..791a801ff0c6493f1602b46420bfc40af04d7674 100644 (file)
@@ -29,8 +29,7 @@
 #include "playtransport.inc"
 
 #define PLAY_MODE 0
-#define PAUSE_MODE 1
-#define PAUSEDOWN_MODE 2
+#define LOOP_MODE 1
 
 class PlayTransport
 {
@@ -62,8 +61,7 @@ public:
 // speed - play speed for SLOW/FAST playback, zero defaults to slow=.5,fast=2.
        void handle_transport(int command, int wait_tracking=0,
                int use_inout=0, int toggle_audio=0, int loop_play=0, float speed=0);
-       int pause_transport();
-       int reset_transport();
+       int set_transport(int mode);
        int get_w();
        int is_stopped();
 // Get the EDL to play back with default to mwindow->edl
@@ -100,7 +98,8 @@ class PTransportButton : public BC_Button
 public:
        PTransportButton(MWindow *mwindow, PlayTransport *transport, int x, int y, VFrame **data);
        virtual ~PTransportButton();
-       virtual int set_mode(int mode);
+       void set_mode(int mode);
+       void loop_mode(int dir);
        int play_command(const char *lock_msg, int command);
 
        int mode;
index 36b10330a52fd7c6010f78fed7f42571f4fc8eb0..dce1f5b7aaadc654b6385d406a0b6cf925893a35 100644 (file)
@@ -49,7 +49,7 @@ Plugin::Plugin(EDL *edl, Track *track, const char *title)
        show = 0;
        on = 1;
        gui_id = -1;
-       keyframes = new KeyFrames(edl, track);
+       keyframes = new KeyFrames(edl, this);
        keyframes->create_objects();
 }
 
@@ -66,7 +66,7 @@ Plugin::Plugin(EDL *edl, PluginSet *plugin_set, const char *title)
        show = 0;
        on = 1;
        gui_id = -1;
-       keyframes = new KeyFrames(edl, track);
+       keyframes = new KeyFrames(edl, this);
        keyframes->create_objects();
 }
 
index a04e9858a5cf5ebfcb657dbd92c52a7e1cc0a279..7d971a691c361771b36a3aa9fe68c1d4f956a77a 100644 (file)
@@ -266,8 +266,10 @@ int PluginArray::stop_plugins()
                        values[i]->close_plugin();
                }
        }
-
-       delete cache;
+       if( cache ) {
+               cache->remove_user();
+               cache = 0;
+       }
        return 0;
 }
 
index 467fa2aa8346bb3909698f9135dc8bde924b9799..94a208844658668db4048770b28b1eefb3044843 100644 (file)
@@ -1083,9 +1083,12 @@ int PluginClient::send_configure_change()
        if(server->mwindow)
                server->mwindow->undo->update_undo_before(_("tweek"), this);
 #ifdef USE_KEYFRAME_SPANNING
-       KeyFrame keyframe;
+       EDL *edl = server->edl;
+        Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
+       KeyFrames *keyframes = plugin ? plugin->keyframes : 0;
+       KeyFrame keyframe(edl, keyframes);
        save_data(&keyframe);
-       server->apply_keyframe(&keyframe);
+       server->apply_keyframe(plugin, &keyframe);
 #else
        KeyFrame* keyframe = server->get_keyframe();
 // Call save routine in plugin
@@ -1097,6 +1100,14 @@ int PluginClient::send_configure_change()
        return 0;
 }
 
+// virtual default spanning keyframe update.  If a range is selected,
+// then changed parameters are copied to (prev + selected) keyframes.
+// redefine per client for custom keyframe updates, see tracer, sketcher, crikey
+void PluginClient::span_keyframes(KeyFrame *src, int64_t start, int64_t end)
+{
+       src->span_keyframes(start, end);
+}
+
 
 KeyFrame* PluginClient::get_prev_keyframe(int64_t position, int is_local)
 {
@@ -1164,3 +1175,4 @@ int PluginClient::gui_open()
        return server->gui_open();
 }
 
+
index 8abf7666dbf39ea4877a160dc5605e7045027133..b338debaf09f5f5037aa9fa7ed60e4dc2185d22f 100644 (file)
@@ -381,7 +381,7 @@ public:
 // console.  This gets a keyframe from the EDL, with the position set to the
 // EDL tracking position.
        int send_configure_change();
-
+       virtual void span_keyframes(KeyFrame *src, int64_t start, int64_t end);
 
 // Called from process_buffer
 // Returns 1 if a GUI is open so OpenGL routines can determine if
index f9c24fffb9c41c8948f2b254e9b6dabbe8fde1c6..8063982bfe8ffa652b11cf624af470f050b76e17 100644 (file)
@@ -435,8 +435,10 @@ void PluginDialog::apply()
 
 void PluginDialogThread::apply()
 {
-       if( mwindow->edl )
-               mwindow->edl->session->single_standalone = single_standalone;
+       Plugin *plugin = 0;
+       EDL *edl = mwindow->edl;
+       if( edl )
+               edl->session->single_standalone = single_standalone;
        if(plugin_type) {
                mwindow->gui->lock_window("PluginDialogThread::run 3");
                mwindow->undo->update_undo_before();
@@ -444,16 +446,20 @@ void PluginDialogThread::apply()
                        mwindow->insert_effect(plugin_title, &shared_location,
                                data_type, plugin_type, single_standalone);
                }
-               else {
-                       Plugin *plugin = mwindow->edl->tracks->plugin_exists(plugin_id);
-                       if( plugin ) {
-                               plugin->change_plugin(plugin_title,
+               else if( (plugin=edl->tracks->plugin_exists(plugin_id)) != 0 ) {
+                       plugin->change_plugin(plugin_title,
                                        &shared_location, plugin_type);
+               }
+               else if( edl->tracks->track_exists(track) ) {
+                       double start = edl->local_session->get_selectionstart(1);
+                       double end = edl->local_session->get_selectionend(1);
+                       if( start >= end ) {
+                               start = 0;
+                               end = track->get_length();
                        }
-                       else if( mwindow->edl->tracks->track_exists(track) ) {
-                                       mwindow->insert_effect(plugin_title, &shared_location,
-                                       track, 0, 0, 0, plugin_type);
-                       }
+                       double length = end - start;
+                       mwindow->insert_effect(plugin_title, &shared_location,
+                                       track, 0, start, length, plugin_type);
                }
 
                mwindow->save_backup();
index 2cc12d62737625feec8a15602b2ffbea57fe6d95..486d73195d0c4605f055638f1aab9ec7adfa24f1 100644 (file)
@@ -8,6 +8,7 @@
 #include "bcwindowbase.h"
 #include "bctitle.h"
 #include "cstrdup.h"
+#include "keys.h"
 #include "language.h"
 #include "mwindow.h"
 #include "pluginfclient.h"
@@ -186,6 +187,10 @@ PluginFClientText::
 
 int PluginFClientText::handle_event()
 {
+       if( get_keypress() == RETURN ) {
+               fwin->update();
+               activate();
+       }
        return 0;
 }
 
index 7b7dc678e717b2dd1578bfb3f4f3cad2092852e4..c6ef09cbe2125257a6dc07c004b9402f11b750fd 100644 (file)
@@ -52,6 +52,8 @@ PluginLV2::PluginLV2()
        schedule.schedule_work = lv2_worker_schedule;
        worker_iface = 0;  worker_done = -1;
        pthread_mutex_init(&worker_lock, 0);
+       pthread_mutex_init(&startup_lock, 0);
+       pthread_mutex_lock(&startup_lock);
        pthread_cond_init(&worker_ready, 0);
        work_avail = 0;   work_input = 0;
        work_output = 0;  work_tail = &work_output;
@@ -417,6 +419,7 @@ PluginLV2Work *PluginLV2::get_work()
 void *PluginLV2::worker_func()
 {
        pthread_mutex_lock(&worker_lock);
+       pthread_mutex_unlock(&startup_lock);
        for(;;) {
                while( !worker_done && !work_input )
                        pthread_cond_wait(&worker_ready, &worker_lock);
@@ -440,6 +443,7 @@ void *PluginLV2::worker_func(void* vp)
 void PluginLV2::worker_start()
 {
        pthread_create(&worker_thread, 0, worker_func, this);
+       pthread_mutex_lock(&startup_lock);
 }
 
 void PluginLV2::worker_stop()
index ac99d2535dfc3015ba23ba910db6b28f8016ba53..6f1e60096a94cbbbad1df6b8d84ab78394c18859 100644 (file)
@@ -137,7 +137,7 @@ public:
        LV2_Worker_Schedule schedule;
        PluginLV2Work *work_avail, *work_input;
        PluginLV2Work *work_output, **work_tail;
-       pthread_mutex_t worker_lock;
+       pthread_mutex_t startup_lock, worker_lock;
        pthread_cond_t worker_ready;
        int worker_done;
 };
index a12eaac6245667ea02b45352ecb1f30f75a6176b..18619cc7ad98ff2d88c7f16eabb5df4128de393a 100644 (file)
@@ -1028,7 +1028,7 @@ void PluginServer::get_defaults_path(char *path)
        switch( plugin_type ) {
        case PLUGIN_TYPE_FFMPEG:
        case PLUGIN_TYPE_LV2:
-               strcpy(string2, client->plugin_title());
+               strcpy(string2, title);
                break;
        case PLUGIN_TYPE_BUILTIN:
        case PLUGIN_TYPE_LADSPA:
@@ -1174,16 +1174,28 @@ KeyFrame* PluginServer::get_keyframe()
 }
 
 
-void PluginServer::apply_keyframe(KeyFrame *src)
-{
-       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
-       if( !plugin )
-               keyframe->copy_data(src);
-       else if( plugin->is_transition() )
-               plugin->get_keyframe()->copy_data(src);
-       else
-// Span keyframes
-               plugin->keyframes->update_parameter(src);
+void PluginServer::apply_keyframe(Plugin *plugin, KeyFrame *src)
+{
+       KeyFrame* dst = !plugin ? keyframe :
+               plugin->is_transition() ? plugin->get_keyframe() : 0;
+       if( !dst ) {
+               if( edl->session->span_keyframes ) {
+                       double selection_start = edl->local_session->get_selectionstart(0);
+                       double selection_end = edl->local_session->get_selectionend(0);
+                       selection_start = edl->align_to_frame(selection_start, 0);
+                       selection_end = edl->align_to_frame(selection_end, 0);
+                       Track *track = plugin->track;
+                       int64_t start = track->to_units(selection_start, 1);
+                       int64_t end = track->to_units(selection_end, 1);
+                       if( start != end ) {
+                               client->span_keyframes(src, start, end);
+                               return;
+                       }
+               }
+               dst = get_keyframe();
+       }
+       if( dst )
+               dst->copy_data(src);
 }
 
 
index f0c8500de5bee094dcebf8bac8671807cfd235ec..1808db7e2435c502795eec3b8f23e113baa1f784 100644 (file)
@@ -170,7 +170,7 @@ public:
        KeyFrame* get_keyframe();
 // Apply new settings from the plugin GUI.  Called by PluginClient::send_configure_change
 // Used in keyframe spanning mode.
-       void apply_keyframe(KeyFrame *src);
+       void apply_keyframe(Plugin *plugin, KeyFrame *src);
 
 // Create new theme object.  Used by theme plugins.
        Theme* new_theme();
index 2dabe6adb092d7b698a01b8759426d6c10029ab1..d9c160f16f8c2c097e4f5309f5f3ca87bc83ed3f 100644 (file)
@@ -329,7 +329,7 @@ void PresetsDBPlugin::load(FileXML *file, int is_factory)
                                const char *keyframe_title = file->tag.get_property("TITLE", string);
                                PresetsDBKeyframe *keyframe = new PresetsDBKeyframe(keyframe_title, is_factory);
                                XMLBuffer data;
-                               file->read_text_until("/KEYFRAME", &data);
+                               file->read_data_until("/KEYFRAME", &data);
                                keyframe->set_data(data.cstr());
                                keyframes.append(keyframe);
                
@@ -352,7 +352,7 @@ void PresetsDBPlugin::save(FileXML *file)
                        file->tag.set_title("KEYFRAME");
                        file->tag.set_property("TITLE", keyframe->title);
                        file->append_tag();
-                       file->append_text(keyframe->data);
+                       file->append_data(keyframe->data);
                        file->tag.set_title("/KEYFRAME");
                        file->append_tag();
                        file->append_newline();
index fbb34fcfc4061e767bb63c8fe0734be1bee07f8f..fff64f37fb1eb850e8df5505f818f3abc4bcc871 100644 (file)
@@ -229,11 +229,11 @@ void ProxyRender::to_proxy_path(char *new_path, Indexable *indexable, int scale)
 //printf("ProxyRender::to_proxy_path %d %s %s\n", __LINE__, new_path), asset->path);
 }
 
-int ProxyRender::from_proxy_path(char *new_path, Indexable *indexable, int scale)
+int ProxyRender::from_proxy_path(char *new_path, Asset *asset, int scale)
 {
        char prxy[BCTEXTLEN];
        int n = sprintf(prxy, ".proxy%d", scale);
-       strcpy(new_path, indexable->path);
+       strcpy(new_path, asset->path);
        char *ptr = strstr(new_path, prxy);
        if( !ptr || (ptr[n] != '-' && ptr[n] != '.') ) return 1;
 // remove proxy, path.proxy#-sfx.ext => path.sfx
@@ -242,6 +242,12 @@ int ProxyRender::from_proxy_path(char *new_path, Indexable *indexable, int scale
        char *cp = ptr + n;
        for( *cp='.'; cp<ext; ++cp ) *ptr++ = *cp;
        *ptr = 0;
+       if( asset->proxy_edl ) {
+               if( (cp = strrchr(new_path, '/')) != 0 ) {
+                       for( ptr=new_path; *++cp; ) *ptr++ = *cp;
+                       *ptr = 0;
+               }
+       }
        return 0;
 }
 
@@ -307,6 +313,7 @@ Asset *ProxyRender::add_original(Indexable *idxbl, int new_scale)
                        proxy->video_length = video_frames;
                }
                proxy->folder_no = AW_PROXY_FOLDER;
+               proxy->proxy_edl = !idxbl->is_asset ? 1 : 0;
                proxy->audio_data = 0;
                proxy->video_data = 1;
                proxy->layers = 1;
@@ -650,7 +657,8 @@ ProxyClient::ProxyClient(MWindow *mwindow,
 ProxyClient::~ProxyClient()
 {
        delete render_engine;
-       delete video_cache;
+       if( video_cache )
+               video_cache->remove_user();
        delete src_file;
 }
 
index 7f88686dda1b7579a550cbf4a5fe70555525f821..b134b910be78a42a17bac33b1f3450d3c05082aa 100644 (file)
@@ -67,7 +67,7 @@ public:
        ProxyRender(MWindow *mwindow, Asset *format_asset, int asset_scale);
        ~ProxyRender();
        void to_proxy_path(char *new_path, Indexable *indexable, int scale);
-       static int from_proxy_path(char *new_path, Indexable *indexable, int scale);
+       static int from_proxy_path(char *new_path, Asset *asset, int scale);
 
        ArrayList<Indexable *> orig_idxbls;   // originals which match the proxy assets
        ArrayList<Indexable *> orig_proxies;  // proxy assets
index d5d2ea49506b2aeae5f1be0170d09d02e1ca44c5..4f7d1734a94942baed2b2ab71c84d63bb058ff38 100644 (file)
@@ -34,7 +34,7 @@ RecordableATracks::RecordableATracks(Tracks *tracks)
                current_track;
                current_track = current_track->next)
        {
-               if(current_track->record && current_track->data_type == TRACK_AUDIO)
+               if(current_track->is_armed() && current_track->data_type == TRACK_AUDIO)
                        append((ATrack*)current_track);
        }
 }
index 4e5ae4526d74911d6717588a7dae7f57fac0ea83..d9ea7b54a3d2a96c0a2dcf1a18576d7af0fd25ee 100644 (file)
@@ -33,7 +33,7 @@ RecordableVTracks::RecordableVTracks(Tracks *tracks)
                current_track;
                current_track = current_track->next)
        {
-               if(current_track->record && current_track->data_type == TRACK_VIDEO)
+               if(current_track->is_armed() && current_track->data_type == TRACK_VIDEO)
                        append((VTrack*)current_track);
        }
 }
index 746b41879f3fd25bdb4c92d63f897d6f031a1bc0..741d6ff3747c0ef55dbbe5e5aeddf00584c09fe0 100644 (file)
@@ -882,8 +882,8 @@ printf("Render::render_single: Session finished.\n");
                mwindow->restart_brender();
        if( farm_server ) delete farm_server;
        delete command;
-       delete audio_cache;
-       delete video_cache;
+       audio_cache->remove_user();
+       video_cache->remove_user();
 // Must delete packages after server
        delete render->packages;
 
index 27794d27c388884101fe939f80d3d8507abe3301..4c28c0325a66a7723b2f7866132fed540a302d52 100644 (file)
@@ -670,17 +670,18 @@ void ResourceThread::stop()
        video_thread->stop();
 }
 
-void ResourceThread::reset(int pane_number)
+void ResourceThread::reset(int pane_number, int indexes_only)
 {
        audio_thread->reset(pane_number);
-       video_thread->reset(pane_number);
+       if( !indexes_only )
+               video_thread->reset(pane_number);
 }
 
 void ResourceThread::close_indexable(Indexable *idxbl)
 {
        if( audio_thread && audio_thread->render_engine_id == idxbl->id )
                audio_thread->close_render_engine();
-       if( video_thread && audio_thread->render_engine_id == idxbl->id )
+       if( video_thread && video_thread->render_engine_id == idxbl->id )
                video_thread->close_render_engine();
 }
 
index 1f8fada53dfbe31e69aa3a541b20807666770545..8434553d13e9d9add53405844c46b71e99e71f31 100644 (file)
@@ -205,7 +205,7 @@ public:
 
        void run();
        void stop();
-       void reset(int pane_number);
+       void reset(int pane_number, int indexes_only);
        void close_indexable(Indexable*);
 
        MWindow *mwindow;
index 289ae2616f4b150389d7c193e4dc7a0efd4976c8..8e558fd1c221853547b2d96a4e5e52627c22c11e 100644 (file)
@@ -428,7 +428,7 @@ int SWindowGUI::update_selection()
        Edit *edit = 0;
        Tracks *tracks = edl->tracks;
        for( Track *track=tracks->first; track && !edit; track=track->next ) {
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                if( track->data_type != TRACK_SUBTITLE ) continue;
                int64_t pos = track->to_units(position,0);
                edit = track->edits->editof(pos, PLAY_FORWARD, 0);
@@ -448,7 +448,7 @@ int MWindow::paste_subtitle_text(char *text, double start, double end)
        Tracks *tracks = edl->tracks;
        for( Track *track=tracks->first; track; track=track->next ) {
                if( track->data_type != TRACK_SUBTITLE ) continue;
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                int64_t start_i = track->to_units(start, 0);
                int64_t end_i = track->to_units(end, 1);
                track->edits->clear(start_i,end_i);
@@ -838,7 +838,7 @@ void SWindowGUI::save_spumux_data()
        Tracks *tracks = swindow->mwindow->edl->tracks;
        for( Track *track=tracks->first; track; track=track->next ) {
                if( track->data_type != TRACK_SUBTITLE ) continue;
-               if( !track->record ) continue;
+               if( !track->is_armed() ) continue;
                char *cp = track_title, *ep = cp+sizeof(track_title)-6;
                for( const char *bp=track->title; cp<ep && *bp!=0; ) {
                        int wch = butf8(bp); // iswalnum(wch) broken by MS port
index c1847b78edb95f22b4b6ef8229dd24fa1e168cb9..d89c789f76cb95018e954fc1f0d65002c16e0d7c 100644 (file)
@@ -179,6 +179,7 @@ Theme::Theme()
        statusbar_cancel_data = 0;
        timebar_view_data = 0;
        transition_data = 0;
+       tumblepatch_data = 0;
        uptriangle_data = 0;
        viewasset_data = 0;
        vtimebar_bg_data = 0;
index b5b2d0599930f9baa2164f118b5470911e9dcf99..199de0a843af51e936b17809da12044576a8f68b 100644 (file)
@@ -374,6 +374,7 @@ public:
        VFrame **statusbar_cancel_data;
        VFrame *timebar_view_data;
        VFrame **transition_data;
+       VFrame **tumblepatch_data;
        VFrame **uptriangle_data;
        VFrame **viewasset_data;
        VFrame *vtimebar_bg_data;
index 27cd96b5076e5f7126bee7ad59556909ff4bab98..9e86481c8df919e4d01f441b2a60ce8ff292368f 100644 (file)
@@ -60,9 +60,10 @@ Track::Track(EDL *edl, Tracks *tracks) : ListItem<Track>()
        data_h = 64;
        expand_view = 0;
        draw = 1;
-       gang = 1;
+       ganged = 1;
+       master = 0;
        title[0] = 0;
-       record = 1;
+       armed = 1;
        play = 1;
        nudge = 0;
        track_w = edl->session->output_w;
@@ -88,8 +89,9 @@ int Track::copy_settings(Track *track)
 {
        this->expand_view = track->expand_view;
        this->draw = track->draw;
-       this->gang = track->gang;
-       this->record = track->record;
+       this->ganged = track->ganged;
+       this->master = track->master;
+       this->armed = track->armed;
        this->nudge = track->nudge;
        this->mixer_id = track->mixer_id;
        this->play = track->play;
@@ -316,9 +318,10 @@ int Track::load(FileXML *file, int track_offset, uint32_t load_flags)
        int current_plugin = 0;
 
 
-       record = file->tag.get_property("RECORD", record);
+       armed = file->tag.get_property("RECORD", armed);
        play = file->tag.get_property("PLAY", play);
-       gang = file->tag.get_property("GANG", gang);
+       ganged = file->tag.get_property("GANG", ganged);
+       master = file->tag.get_property("MASTER", 1);
        draw = file->tag.get_property("DRAW", draw);
        nudge = file->tag.get_property("NUDGE", nudge);
        mixer_id = file->tag.get_property("MIXER_ID", mixer_id);
@@ -477,90 +480,17 @@ void Track::insert_plugin_set(Track *track,
                shift_effects(position, min_length, edit_autos, 0);
 }
 
-
-Plugin* Track::insert_effect(const char *title,
-               SharedLocation *shared_location,
-               KeyFrame *default_keyframe,
-               PluginSet *plugin_set,
-               double start,
-               double length,
-               int plugin_type)
+Plugin* Track::insert_effect(const char *title, SharedLocation *shared_location,
+               KeyFrame *default_keyframe, PluginSet *plugin_set,
+               double start, double length, int plugin_type)
 {
-       if(!plugin_set)
-       {
+       if( !plugin_set ) {
                plugin_set = new PluginSet(edl, this);
                this->plugin_set.append(plugin_set);
        }
-
-       Plugin *plugin = 0;
-
-// Position is identical to source plugin
-       if(plugin_type == PLUGIN_SHAREDPLUGIN)
-       {
-               Track *source_track = tracks->get_item_number(shared_location->module);
-               if(source_track)
-               {
-                       Plugin *source_plugin = source_track->get_current_plugin(
-                               edl->local_session->get_selectionstart(1),
-                               shared_location->plugin,
-                               PLAY_FORWARD,
-                               1,
-                               0);
-
-// From an attach operation
-                       if(source_plugin)
-                       {
-                               plugin = plugin_set->insert_plugin(title,
-                                       source_plugin->startproject,
-                                       source_plugin->length,
-                                       plugin_type,
-                                       shared_location,
-                                       default_keyframe,
-                                       1);
-                       }
-                       else
-// From a drag operation
-                       {
-                               plugin = plugin_set->insert_plugin(title,
-                                       to_units(start, 0),
-                                       to_units(length, 1),
-                                       plugin_type,
-                                       shared_location,
-                                       default_keyframe,
-                                       1);
-                       }
-               }
-       }
-       else
-       {
-// This should be done in the caller
-               if(EQUIV(length, 0))
-               {
-                       if(edl->local_session->get_selectionend() >
-                               edl->local_session->get_selectionstart())
-                       {
-                               start = edl->local_session->get_selectionstart();
-                               length = edl->local_session->get_selectionend() - start;
-                       }
-                       else
-                       {
-                               start = 0;
-                               length = get_length();
-                       }
-               }
-//printf("Track::insert_effect %f %f %d %d\n", start, length, to_units(start, 0),
-//                     to_units(length, 0));
-
-               plugin = plugin_set->insert_plugin(title,
-                       to_units(start, 0),
-                       to_units(length, 1),
-                       plugin_type,
-                       shared_location,
-                       default_keyframe,
-                       1);
-       }
-//printf("Track::insert_effect 2 %f %f\n", start, length);
-
+       Plugin *plugin = plugin_set->insert_plugin(title,
+                       to_units(start, 0), to_units(length, 1), plugin_type,
+                       shared_location, default_keyframe, 1);
        expand_view = 1;
        return plugin;
 }
@@ -638,8 +568,7 @@ void Track::remove_pluginset(PluginSet *plugin_set)
                if(plugin_set == this->plugin_set.values[i]) break;
 
        this->plugin_set.remove_object(plugin_set);
-       for(i++ ; i < this->plugin_set.total; i++)
-       {
+       for( ++i ; i<=this->plugin_set.total; ++i ) {
                SharedLocation old_location, new_location;
                new_location.module = old_location.module = tracks->number_of(this);
                old_location.plugin = i;
@@ -665,26 +594,54 @@ void Track::shift_effects(int64_t position, int64_t length, int edit_autos, Edit
 void Track::detach_effect(Plugin *plugin)
 {
 //printf("Track::detach_effect 1\n");
-       for(int i = 0; i < plugin_set.total; i++)
-       {
-               PluginSet *plugin_set = this->plugin_set.values[i];
-               for(Plugin *dest = (Plugin*)plugin_set->first;
-                       dest;
-                       dest = (Plugin*)dest->next)
-               {
-                       if(dest == plugin)
-                       {
-                               int64_t start = plugin->startproject;
-                               int64_t end = plugin->startproject + plugin->length;
-
-                               plugin_set->clear(start, end, 1);
-                               optimize();
+       for( int i=0; i<plugin_set.size(); ++i ) {
+               PluginSet *pluginset = plugin_set[i];
+               Plugin *dest = (Plugin*)pluginset->first;
+               while( dest && dest != plugin ) dest = (Plugin*)dest->next;
+               if( !dest ) continue;
+               tracks->detach_ganged_effects(plugin);
+               int64_t start = plugin->startproject;
+               int64_t end = start + plugin->length;
+               pluginset->clear(start, end, 1);
+               optimize();
 //printf("Track::detach_effect 2 %d\n", plugin_set->length());
 // Delete 0 length pluginsets
-                               return;
-                       }
+               return;
+       }
+}
+
+void Track::detach_shared_effects(int module)
+{
+       for( int i=0; i<plugin_set.size(); ++i ) {
+               PluginSet *pluginset = this->plugin_set[i];
+               Plugin *dest = (Plugin*)pluginset->first;
+               for( ; dest; dest=(Plugin*)dest->next ) {
+                       if( (dest->plugin_type != PLUGIN_SHAREDPLUGIN &&
+                            dest->plugin_type != PLUGIN_SHAREDMODULE) ) continue;
+                       if( dest->shared_location.module != module ) continue;
+                       int64_t start = dest->startproject;
+                       int64_t end = start + dest->length;
+                       pluginset->clear(start, end, 1);
                }
        }
+       optimize();
+}
+
+void Track::detach_ganged_effects(Plugin *plugin)
+{
+       for( int i=0; i<plugin_set.size(); ++i ) {
+               PluginSet *pluginset = this->plugin_set[i];
+               Plugin *dest = (Plugin*)pluginset->first;
+               for( ; dest; dest=(Plugin*)dest->next ) {
+                       if( strcmp(dest->title, plugin->title) != 0 ) continue;
+                       if( dest->startproject != plugin->startproject ) continue;
+                       if( dest->length != plugin->length ) continue;
+                       int64_t start = dest->startproject;
+                       int64_t end = start + dest->length;
+                       pluginset->clear(start, end, 1);
+               }
+       }
+       optimize();
 }
 
 void Track::resample(double old_rate, double new_rate)
@@ -696,25 +653,6 @@ void Track::resample(double old_rate, double new_rate)
        nudge = (int64_t)(nudge * new_rate / old_rate);
 }
 
-void Track::detach_shared_effects(int module)
-{
-       for(int i = 0; i < plugin_set.size(); i++) {
-               PluginSet *plugin_set = this->plugin_set.get(i);
-               for(Plugin *dest = (Plugin*)plugin_set->first; dest; ) {
-                       if( (dest->plugin_type == PLUGIN_SHAREDPLUGIN ||
-                               dest->plugin_type == PLUGIN_SHAREDMODULE) &&
-                               dest->shared_location.module == module ) {
-                               int64_t start = dest->startproject;
-                               int64_t end = dest->startproject + dest->length;
-                               plugin_set->clear(start, end, 1);
-                       }
-
-                       if(dest) dest = (Plugin*)dest->next;
-               }
-       }
-       optimize();
-}
-
 
 void Track::optimize()
 {
@@ -845,9 +783,10 @@ void Track::synchronize_params(Track *track)
 
 int Track::dump(FILE *fp)
 {
-       fprintf(fp,"   Data type %d, draw %d, gang %d, play %d, record %d, nudge %jd, masks 0x%04x\n",
-               data_type, draw, gang, play, record, nudge, masks);
        fprintf(fp,"   Title %s\n", title);
+       fprintf(fp,"   Data type %d, draw %d, gang %d, master %d, mixer_id %d\n"
+                  "      play %d, armed %d, nudge %jd, masks 0x%04x\n",
+               data_type, draw, ganged, master, mixer_id, play, armed, nudge, masks);
        fprintf(fp,"   Edits:\n");
        for(Edit* current = edits->first; current; current = NEXT)
                current->dump(fp);
@@ -1005,11 +944,12 @@ int Track::copy(int copy_flags, double start, double end,
 
 
        file->tag.set_title("TRACK");
-       file->tag.set_property("RECORD", record);
+       file->tag.set_property("RECORD", armed);
        file->tag.set_property("NUDGE", nudge);
        file->tag.set_property("MIXER_ID", mixer_id);
        file->tag.set_property("PLAY", play);
-       file->tag.set_property("GANG", gang);
+       file->tag.set_property("GANG", ganged);
+       file->tag.set_property("MASTER", master);
        file->tag.set_property("DRAW", draw);
        file->tag.set_property("EXPAND", expand_view);
        file->tag.set_property("DATA_H", data_h);
@@ -1851,3 +1791,69 @@ void Track::set_camera(float x, float y, float z)
        set_fauto_xyz(AUTOMATION_CAMERA_X, x, y, z);
 }
 
+Track *Track::gang_master()
+{
+       Track *track = this;
+       switch( edl->session->gang_tracks ) {
+       case GANG_NONE:
+               return track;
+       case GANG_CHANNELS: {
+               Track *current = track;
+               int data_type = track->data_type;
+               while( current && !track->master ) {
+                       if( !(current = current->previous) ) break;
+                       if( current->data_type == data_type ) track = current;
+                       if( track->master ) break;
+               }
+               break; }
+       case GANG_MEDIA: {
+               while( track && !track->master ) track = track->previous;
+               break; }
+       }
+       if( !track ) track = tracks->first;
+       return track;
+}
+
+int Track::is_hidden()
+{
+       if( master ) return 0;
+       if( edl->session->gang_tracks == GANG_MEDIA ) return 1;
+       if( edl->session->gang_tracks == GANG_CHANNELS ) {
+               for( Track *track=previous; track; track=track->previous ) {
+                       if( track->data_type == data_type ) return 1;
+                       if( track->master ) return 0;
+               }
+       }
+       return 0;
+}
+int Track::is_armed()
+{
+       return gang_master()->armed;
+}
+
+int Track::is_ganged()
+{
+       return gang_master()->ganged;
+}
+
+int Track::armed_gang(Track *track)
+{
+       if( edl->session->gang_tracks == GANG_NONE ) return ganged;
+       Track *current = gang_master();
+       for(;;) {
+               if( track == current ) return 1;
+               current = current->next;
+               if( !current || current->master ) return 0;
+       }
+       return 1;
+}
+
+
+int Track::index_in(Mixer *mixer)
+{
+       if( !mixer || mixer_id < 0 ) return -1;
+       int k = mixer->mixer_ids.size();
+       while( --k >= 0 && mixer_id != mixer->mixer_ids[k] );
+       return k;
+}
+
index f59e989804905f877a08a25ca1cad5bf5caf8edd..a23f664806cd95ca6f7f284335d847103b17081e 100644 (file)
@@ -50,6 +50,7 @@
 #include "trackcanvas.inc"
 #include "tracks.inc"
 #include "transition.inc"
+#include "zwindow.inc"
 
 // UNITS ARE SAMPLES FOR ALL
 
@@ -140,7 +141,8 @@ public:
 
 // detach shared effects referencing module
        void detach_shared_effects(int module);
-
+// detach all corresponding effects in gang
+       void detach_ganged_effects(Plugin *plugin);
 
 // Called by playable tracks to test for playable server.
 // Descends the plugin tree without creating a virtual console.
@@ -165,6 +167,12 @@ public:
        void change_plugins(SharedLocation &old_location, SharedLocation &new_location, int do_swap);
        void change_modules(int old_location, int new_location, int do_swap);
        Plugin *plugin_exists(int plugin_id);
+       Track *gang_master();
+       int is_hidden();
+       int is_armed();
+       int is_ganged();
+       int armed_gang(Track *track);
+       int index_in(Mixer *mixer);
 
        EDL *edl;
        Tracks *tracks;
@@ -183,10 +191,10 @@ public:
 // There is some debate on whether to expand gang from faders to
 // dragging operations.  This would allow every edit in a column to get dragged
 // simultaneously.
-       int gang;
+       int ganged;
        char title[BCTEXTLEN];
        int play;
-       int record;
+       int armed;
 // mask enable bit flags
        int masks;
 // Nudge in track units.  Positive shifts track earlier in time.  This way
@@ -318,7 +326,8 @@ public:
        int pixel;   // pixel position from top of track view
 // Dimensions of this track if video
        int track_w, track_h;
-       int mixer_id;
+// mixer set track id, gang master flag
+       int mixer_id, master;
 
 private:
 // Identification of the track
index 7d2da1e210463fe55eeef9ddab4d33572cc48495..c0f8f995d3453504ef4fc830c5cf9d55c7189e8a 100644 (file)
@@ -210,6 +210,7 @@ int TrackCanvas::drag_cursor_motion(int cursor_x, int cursor_y,
 // Find the edit and track the cursor is over
                for(Track *track = mwindow->edl->tracks->first; track; track = track->next)
                {
+                       if( track->is_hidden() ) continue;
                        int64_t track_x, track_y, track_w, track_h;
                        track_dimensions(track, track_x,&n