From: Good Guy Date: Mon, 6 Nov 2017 02:41:33 +0000 (-0700) Subject: mixer X-Git-Url: https://git.cinelerra-gg.org/git/?a=commitdiff_plain;h=0513350234a8dcd08e5a0117d5121724ef7b76b6;p=goodguy%2Fhistory.git mixer --- diff --git a/cinelerra-5.1/cinelerra/Makefile b/cinelerra-5.1/cinelerra/Makefile index fa22ff0c..d6895838 100644 --- a/cinelerra-5.1/cinelerra/Makefile +++ b/cinelerra-5.1/cinelerra/Makefile @@ -333,6 +333,8 @@ OBJS = \ $(OBJDIR)/wwindow.o \ $(OBJDIR)/zoombar.o \ $(OBJDIR)/zoompanel.o \ + $(OBJDIR)/zwindow.o \ + $(OBJDIR)/zwindowgui.o \ # $(OBJDIR)/renderfarmfsclient.o \ # $(OBJDIR)/renderfarmfsserver.o \ diff --git a/cinelerra-5.1/cinelerra/aedit.C b/cinelerra-5.1/cinelerra/aedit.C index b6aa0268..3b830bb0 100644 --- a/cinelerra-5.1/cinelerra/aedit.C +++ b/cinelerra-5.1/cinelerra/aedit.C @@ -71,7 +71,7 @@ int64_t AEdit::get_source_end(int64_t default_) if(nested_edl) { - return (int64_t)(nested_edl->tracks->total_playable_length() * + return (int64_t)(nested_edl->tracks->total_length() * edl->session->sample_rate + 0.5); } diff --git a/cinelerra-5.1/cinelerra/apatchgui.C b/cinelerra-5.1/cinelerra/apatchgui.C index 64d458f5..824e7a86 100644 --- a/cinelerra-5.1/cinelerra/apatchgui.C +++ b/cinelerra-5.1/cinelerra/apatchgui.C @@ -32,6 +32,7 @@ #include "intautos.h" #include "language.h" #include "localsession.h" +#include "mainsession.h" #include "mainundo.h" #include "mwindow.h" #include "mwindowgui.h" @@ -40,20 +41,11 @@ #include "patchbay.h" #include "theme.h" #include "trackcanvas.h" +#include "zwindow.h" - - - -APatchGUI::APatchGUI(MWindow *mwindow, - PatchBay *patchbay, - ATrack *track, - int x, - int y) - : PatchGUI(mwindow, - patchbay, - track, - x, - y) +APatchGUI::APatchGUI(MWindow *mwindow, PatchBay *patchbay, + ATrack *track, int x, int y) + : PatchGUI(mwindow, patchbay, track, x, y) { data_type = TRACK_AUDIO; this->atrack = track; @@ -64,9 +56,9 @@ APatchGUI::APatchGUI(MWindow *mwindow, APatchGUI::~APatchGUI() { - if(fade) delete fade; - if(meter) delete meter; - if(pan) delete pan; + if( fade ) delete fade; + if( meter ) delete meter; + if( pan ) delete pan; } void APatchGUI::create_objects() @@ -78,23 +70,20 @@ int APatchGUI::reposition(int x, int y) { int y1 = PatchGUI::reposition(x, y); - if(fade) fade->reposition_window(fade->get_x(), - y1 + y); + if( fade ) + fade->reposition_window(fade->get_x(), y1+y); y1 += mwindow->theme->fade_h; - - if(meter) meter->reposition_window(meter->get_x(), - y1 + y, - -1, - meter->get_w()); + if( meter ) + meter->reposition_window(meter->get_x(), y1+y, -1, meter->get_w()); y1 += mwindow->theme->meter_h; - - if(pan) pan->reposition_window(pan->get_x(), - y1 + y); - - if(nudge) nudge->reposition_window(nudge->get_x(), - y1 + y); - + if( mix ) + mix->reposition_window(mix->get_x(), y1+y); + if( pan ) + pan->reposition_window(pan->get_x(), y1+y); + if( nudge ) + nudge->reposition_window(nudge->get_x(), y1+y); y1 += mwindow->theme->pan_h; + return y1; } @@ -104,109 +93,78 @@ int APatchGUI::update(int x, int y) int x1 = 0; int y1 = PatchGUI::update(x, y); - if(fade) - { - if(h - y1 < mwindow->theme->fade_h) - { + if( fade ) { + if( h - y1 < mwindow->theme->fade_h ) { delete fade; fade = 0; } - else - { + else { FloatAuto *previous = 0, *next = 0; double unit_position = mwindow->edl->local_session->get_selectionstart(1); unit_position = mwindow->edl->align_to_frame(unit_position, 0); unit_position = atrack->to_units(unit_position, 0); FloatAutos *ptr = (FloatAutos*)atrack->automation->autos[AUTOMATION_FADE]; - float value = ptr->get_value( - (long)unit_position, - PLAY_FORWARD, - previous, - next); - fade->update(fade->get_w(), - value, + float value = ptr->get_value((long)unit_position, PLAY_FORWARD, previous, next); + fade->update(fade->get_w(), value, mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_AUDIO_FADE], mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_AUDIO_FADE]); } } else - if(h - y1 >= mwindow->theme->fade_h) - { - patchbay->add_subwindow(fade = new AFadePatch(mwindow, - this, - x1 + x, - y1 + y, + if( h - y1 >= mwindow->theme->fade_h ) { + patchbay->add_subwindow(fade = new AFadePatch(mwindow, this, x1+x, y1+y, patchbay->get_w() - 10)); } y1 += mwindow->theme->fade_h; - if(meter) - { - if(h - y1 < mwindow->theme->meter_h) - { - delete meter; - meter = 0; + if( meter ) { + if( h - y1 < mwindow->theme->meter_h ) { + delete meter; meter = 0; } } else - if(h - y1 >= mwindow->theme->meter_h) - { - patchbay->add_subwindow(meter = new AMeterPatch(mwindow, - this, - x1 + x, - y1 + y)); + if( h - y1 >= mwindow->theme->meter_h ) { + patchbay->add_subwindow(meter = new AMeterPatch(mwindow, this, x1+x, y1+y)); } y1 += mwindow->theme->meter_h; - x1 += 10; - - if(pan) - { - if(h - y1 < mwindow->theme->pan_h) - { - delete pan; - pan = 0; - delete nudge; - nudge = 0; + + if( pan ) { + if( h - y1 < mwindow->theme->pan_h ) { + delete mix; mix = 0; + delete pan; pan = 0; + delete nudge; nudge = 0; } - else - { - if(pan->get_total_values() != mwindow->edl->session->audio_channels) - { + else { + if( mwindow->session->selected_zwindow >= 0 ) { + int v = mwindow->mixer_track_active(track); + mix->update(v); + } + if( pan->get_total_values() != mwindow->edl->session->audio_channels ) { pan->change_channels(mwindow->edl->session->audio_channels, mwindow->edl->session->achannel_positions); } - else - { + else { int handle_x, handle_y; PanAuto *previous = 0, *next = 0; double unit_position = mwindow->edl->local_session->get_selectionstart(1); unit_position = mwindow->edl->align_to_frame(unit_position, 0); unit_position = atrack->to_units(unit_position, 0); PanAutos *ptr = (PanAutos*)atrack->automation->autos[AUTOMATION_PAN]; - ptr->get_handle(handle_x, - handle_y, - (long)unit_position, - PLAY_FORWARD, - previous, - next); + ptr->get_handle(handle_x, handle_y, (long)unit_position, + PLAY_FORWARD, previous, next); pan->update(handle_x, handle_y); } nudge->update(); } } else - if(h - y1 >= mwindow->theme->pan_h) - { - patchbay->add_subwindow(pan = new APanPatch(mwindow, - this, - x1 + x, - y1 + y)); - x1 += pan->get_w() + 10; - patchbay->add_subwindow(nudge = new NudgePatch(mwindow, - this, - x1 + x, - y1 + y, - patchbay->get_w() - x1 - 10)); + if( h - y1 >= mwindow->theme->pan_h ) { + patchbay->add_subwindow(mix = new AMixPatch(mwindow, this, x1+x, y1+y+5)); + x1 += mix->get_w() + 10; + patchbay->add_subwindow(pan = new APanPatch(mwindow, this, x1+x, y1+y)); + x1 += pan->get_w() + 20; + patchbay->add_subwindow(nudge = new NudgePatch(mwindow, this, x1+x, y1+y, + patchbay->get_w() - x1-x - 10)); } y1 += mwindow->theme->pan_h; @@ -215,8 +173,7 @@ int APatchGUI::update(int x, int y) void APatchGUI::synchronize_fade(float value_change) { - if(fade && !change_source) - { + if( fade && !change_source ) { fade->update(fade->get_value() + value_change); fade->update_edl(); } @@ -256,22 +213,20 @@ float AFadePatch::update_edl() int AFadePatch::handle_event() { - if(shift_down()) - { + if( shift_down() ) { update(0.0); set_tooltip(get_caption()); } patch->change_source = 1; float change = update_edl(); - if(patch->track->gang && patch->track->record) + if( patch->track->gang && patch->track->record ) patch->patchbay->synchronize_faders(change, TRACK_AUDIO, patch->track); patch->change_source = 0; mwindow->sync_parameters(CHANGE_PARAMS); - if(mwindow->edl->session->auto_conf->autos[AUTOMATION_FADE]) - { + if( mwindow->edl->session->auto_conf->autos[AUTOMATION_FADE] ) { mwindow->gui->draw_overlays(1); } return 1; @@ -349,8 +304,7 @@ int APanPatch::handle_event() mwindow->sync_parameters(CHANGE_PARAMS); - if(need_undo && mwindow->edl->session->auto_conf->autos[AUTOMATION_PAN]) - { + if( need_undo && mwindow->edl->session->auto_conf->autos[AUTOMATION_PAN] ) { mwindow->gui->draw_overlays(1); } return 1; @@ -378,15 +332,9 @@ int AKeyPanPatch::handle_event() AMeterPatch::AMeterPatch(MWindow *mwindow, APatchGUI *patch, int x, int y) - : BC_Meter(x, - y, - METER_HORIZ, - patch->patchbay->get_w() - 10, - mwindow->edl->session->min_meter_db, - mwindow->edl->session->max_meter_db, - mwindow->edl->session->meter_format, - 0, - -1) + : BC_Meter(x, y, METER_HORIZ, patch->patchbay->get_w() - 10, + mwindow->edl->session->min_meter_db, mwindow->edl->session->max_meter_db, + mwindow->edl->session->meter_format, 0, -1) { this->mwindow = mwindow; this->patch = patch; @@ -396,8 +344,7 @@ AMeterPatch::AMeterPatch(MWindow *mwindow, APatchGUI *patch, int x, int y) int AMeterPatch::button_press_event() { - if(cursor_inside() && is_event_win() && get_buttonpress() == 1) - { + if( cursor_inside() && is_event_win() && get_buttonpress() == 1 ) { mwindow->reset_meters(); return 1; } @@ -405,3 +352,13 @@ int AMeterPatch::button_press_event() return 0; } +AMixPatch::AMixPatch(MWindow *mwindow, APatchGUI *patch, int x, int y) + : MixPatch(mwindow, patch, x, y) +{ + set_tooltip(_("Mixer")); +} + +AMixPatch::~AMixPatch() +{ +} + diff --git a/cinelerra-5.1/cinelerra/apatchgui.h b/cinelerra-5.1/cinelerra/apatchgui.h index 61b223f6..c8342057 100644 --- a/cinelerra-5.1/cinelerra/apatchgui.h +++ b/cinelerra-5.1/cinelerra/apatchgui.h @@ -107,4 +107,11 @@ public: APatchGUI *patch; }; +class AMixPatch : public MixPatch +{ +public: + AMixPatch(MWindow *mwindow, APatchGUI *patch, int x, int y); + ~AMixPatch(); +}; + #endif diff --git a/cinelerra-5.1/cinelerra/assetpopup.C b/cinelerra-5.1/cinelerra/assetpopup.C index 24304c72..f5a3be2a 100644 --- a/cinelerra-5.1/cinelerra/assetpopup.C +++ b/cinelerra-5.1/cinelerra/assetpopup.C @@ -44,6 +44,7 @@ #include "tracks.h" #include "vwindow.h" #include "vwindowgui.h" +#include "zwindow.h" AssetPopup::AssetPopup(MWindow *mwindow, AWindowGUI *gui) @@ -67,6 +68,7 @@ void AssetPopup::create_objects() add_item(index = new AssetPopupBuildIndex(mwindow, this)); add_item(view = new AssetPopupView(mwindow, this)); add_item(view_window = new AssetPopupViewWindow(mwindow, this)); + add_item(mixer = new AssetPopupMixer(mwindow, this)); add_item(new AssetPopupPaste(mwindow, this)); add_item(menu_item = new BC_MenuItem(_("Match..."))); menu_item->add_submenu(submenu = new BC_SubMenu()); @@ -256,6 +258,44 @@ int AssetPopupViewWindow::handle_event() return 1; } +AssetPopupMixer::AssetPopupMixer(MWindow *mwindow, AssetPopup *popup) + : BC_MenuItem(_("Open Mixers")) +{ + this->mwindow = mwindow; + this->popup = popup; +} + +AssetPopupMixer::~AssetPopupMixer() +{ +} + +int AssetPopupMixer::handle_event() +{ + mwindow->select_zwindow(0); + for( int i=0; isession->drag_assets->total; ++i ) { + Indexable *indexable = mwindow->session->drag_assets->values[i]; + ArrayList new_assets; + new_assets.append(indexable); + Track *track = mwindow->edl->tracks->last; + mwindow->load_assets(&new_assets, -1, LOADMODE_NEW_TRACKS, 0, 0, 0, 0, 0, 0); + track = !track ? mwindow->edl->tracks->first : track->next; + Mixer *mixer = 0; + ZWindow *zwindow = mwindow->get_mixer(mixer); + while( track ) { + track->play = track->record = 0; + mixer->mixer_ids.append(track->get_mixer_id()); + track = track->next; + } + char *path = indexable->path; + char *tp = strrchr(path, '/'); + if( !tp ) tp = path; else ++tp; + zwindow->set_title(tp); + zwindow->start(); + } + mwindow->queue_mixers(mwindow->edl,CURRENT_FRAME,0,0,1,0); + mwindow->resync_guis(); + return 1; +} AssetPopupPaste::AssetPopupPaste(MWindow *mwindow, AssetPopup *popup) : BC_MenuItem(_("Paste")) diff --git a/cinelerra-5.1/cinelerra/assetpopup.h b/cinelerra-5.1/cinelerra/assetpopup.h index d6c3136e..ee1a3d1f 100644 --- a/cinelerra-5.1/cinelerra/assetpopup.h +++ b/cinelerra-5.1/cinelerra/assetpopup.h @@ -54,6 +54,7 @@ public: AssetPopupBuildIndex *index; AssetPopupView *view; AssetPopupViewWindow *view_window; + AssetPopupMixer *mixer; AWindowListFormat *format; }; @@ -120,6 +121,18 @@ public: AssetPopup *popup; }; +class AssetPopupMixer : public BC_MenuItem +{ +public: + AssetPopupMixer(MWindow *mwindow, AssetPopup *popup); + ~AssetPopupMixer(); + + int handle_event(); + + MWindow *mwindow; + AssetPopup *popup; +}; + class AssetPopupPaste : public BC_MenuItem { public: diff --git a/cinelerra-5.1/cinelerra/assetpopup.inc b/cinelerra-5.1/cinelerra/assetpopup.inc index 537f1174..66e2e396 100644 --- a/cinelerra-5.1/cinelerra/assetpopup.inc +++ b/cinelerra-5.1/cinelerra/assetpopup.inc @@ -28,6 +28,7 @@ class AssetPopupSort; class AssetPopupBuildIndex; class AssetPopupView; class AssetPopupViewWindow; +class AssetPopupMixer; class AssetPopupPaste; class AssetMatchSize; class AssetMatchRate; diff --git a/cinelerra-5.1/cinelerra/cwindow.C b/cinelerra-5.1/cinelerra/cwindow.C index 063f4e05..29d54504 100644 --- a/cinelerra-5.1/cinelerra/cwindow.C +++ b/cinelerra-5.1/cinelerra/cwindow.C @@ -233,6 +233,7 @@ void CWindow::update(int position, if(position) { + mwindow->queue_mixers(mwindow->edl, CURRENT_FRAME,1,0,1,0); playback_engine->que->send_command(CURRENT_FRAME, CHANGE_NONE, mwindow->edl, diff --git a/cinelerra-5.1/cinelerra/cwindowgui.C b/cinelerra-5.1/cinelerra/cwindowgui.C index 20eff120..95bae397 100644 --- a/cinelerra-5.1/cinelerra/cwindowgui.C +++ b/cinelerra-5.1/cinelerra/cwindowgui.C @@ -829,7 +829,7 @@ int CWindowSlider::handle_event() void CWindowSlider::set_position() { - double new_length = mwindow->edl->tracks->total_playable_length(); + double new_length = mwindow->edl->tracks->total_length(); // if(mwindow->edl->local_session->preview_end <= 0 || // mwindow->edl->local_session->preview_end > new_length) // mwindow->edl->local_session->preview_end = new_length; diff --git a/cinelerra-5.1/cinelerra/edl.C b/cinelerra-5.1/cinelerra/edl.C index cd20a7b0..a27e10cc 100644 --- a/cinelerra-5.1/cinelerra/edl.C +++ b/cinelerra-5.1/cinelerra/edl.C @@ -240,6 +240,7 @@ int EDL::load_xml(FileXML *file, for(int i = 0; i < clips.size(); i++) clips.get(i)->Garbage::remove_user(); clips.remove_all(); + mixers.remove_all_objects(); } if(load_flags & LOAD_TIMEBAR) @@ -299,6 +300,14 @@ int EDL::load_xml(FileXML *file, new_folder(folder); } else + if(file->tag.title_is("MIXERS")) + { + if((load_flags & LOAD_SESSION)) + mixers.load(file); + else + result = file->skip_tag(); + } + else if(file->tag.title_is("ASSETS")) { if(load_flags & LOAD_ASSETS) @@ -413,6 +422,7 @@ int EDL::copy_all(EDL *edl) copy_session(edl); copy_assets(edl); copy_clips(edl); + copy_mixers(edl); tracks->copy_from(edl->tracks); labels->copy_from(edl->labels); return 0; @@ -456,6 +466,12 @@ void EDL::copy_assets(EDL *edl) } } +void EDL::copy_mixers(EDL *edl) +{ + if(this == edl) return; + mixers.copy_from(edl->mixers); +} + void EDL::copy_session(EDL *edl, int session_only) { if(this == edl) return; @@ -629,6 +645,7 @@ int EDL::copy(double start, output_path, 1, 0); + mixers.save(file); } file->append_newline(); @@ -1147,7 +1164,7 @@ void EDL::insert_asset(Asset *asset, if(new_nested_edl) { - length = new_nested_edl->tracks->total_playable_length(); + length = new_nested_edl->tracks->total_length(); layers = 1; channels = new_nested_edl->session->audio_channels; } @@ -1479,7 +1496,7 @@ int EDL::get_sample_rate() int64_t EDL::get_audio_samples() { - return (int64_t)(tracks->total_playable_length() * + return (int64_t)(tracks->total_length() * session->sample_rate); } @@ -1516,7 +1533,7 @@ int EDL::get_video_layers() int64_t EDL::get_video_frames() { - return (int64_t)(tracks->total_playable_length() * + return (int64_t)(tracks->total_length() * session->frame_rate); } diff --git a/cinelerra-5.1/cinelerra/edl.h b/cinelerra-5.1/cinelerra/edl.h index 45740cdf..2e8eec9c 100644 --- a/cinelerra-5.1/cinelerra/edl.h +++ b/cinelerra-5.1/cinelerra/edl.h @@ -50,6 +50,7 @@ #include "theme.inc" #include "tracks.inc" #include "vedit.inc" +#include "zwindow.h" // Loading and saving are built on load and copy except for automation: @@ -110,6 +111,7 @@ public: int copy_all(EDL *edl); void copy_assets(EDL *edl); void copy_clips(EDL *edl); + void copy_mixers(EDL *edl); // Copy pan and fade settings from edl void synchronize_params(EDL *edl); // Determine if the positions are equivalent if they're within half a frame @@ -245,6 +247,7 @@ public: ArrayList vwindow_edls; // is the vwindow_edl shared and therefore should not be deleted in destructor // int vwindow_edl_shared; + Mixers mixers; // Media files // Shared between all EDLs diff --git a/cinelerra-5.1/cinelerra/gwindowgui.C b/cinelerra-5.1/cinelerra/gwindowgui.C index d0126861..b1892034 100644 --- a/cinelerra-5.1/cinelerra/gwindowgui.C +++ b/cinelerra-5.1/cinelerra/gwindowgui.C @@ -190,8 +190,10 @@ GWindowColorButton::GWindowColorButton(GWindowToggle *auto_toggle, int x, int y, { this->auto_toggle = auto_toggle; this->color = 0; - for( int i=0; i<3; ++i ) + for( int i=0; i<3; ++i ) { vframes[i] = new VFrame(w, w, BC_RGBA8888, -1); + vframes[i]->clear_frame(); + } } GWindowColorButton::~GWindowColorButton() diff --git a/cinelerra-5.1/cinelerra/keyframepopup.C b/cinelerra-5.1/cinelerra/keyframepopup.C index 9fb15e71..aff99d6d 100644 --- a/cinelerra-5.1/cinelerra/keyframepopup.C +++ b/cinelerra-5.1/cinelerra/keyframepopup.C @@ -229,22 +229,6 @@ KeyframePopupShow::~KeyframePopupShow() { } -PatchGUI *KeyframePopupShow::get_patchgui(Track *track) -{ - PatchGUI *patchgui = 0; - TimelinePane **panes = mwindow->gui->pane; - for( int i=0; ipatchbay; - if( !patchbay ) continue; - for( int j=0; jpatches.total && !patchgui; ++j ) { - if( patchbay->patches.values[j]->track == track ) - patchgui = patchbay->patches.values[j]; - } - } - return patchgui; -} - int KeyframePopupShow::handle_event() { MWindowGUI *mgui = mwindow->gui; @@ -280,7 +264,7 @@ int KeyframePopupShow::handle_event() default: { show_window = 0; - PatchGUI *patchgui = get_patchgui(popup->keyframe_automation->track); + PatchGUI *patchgui = mwindow->get_patchgui(popup->keyframe_automation->track); if( !patchgui ) break; switch( popup->keyframe_autos->autoidx ) { diff --git a/cinelerra-5.1/cinelerra/keyframepopup.h b/cinelerra-5.1/cinelerra/keyframepopup.h index 68676792..99220c94 100644 --- a/cinelerra-5.1/cinelerra/keyframepopup.h +++ b/cinelerra-5.1/cinelerra/keyframepopup.h @@ -99,7 +99,6 @@ class KeyframePopupShow : public BC_MenuItem public: KeyframePopupShow(MWindow *mwindow, KeyframePopup *popup); ~KeyframePopupShow(); - PatchGUI *get_patchgui(Track *track); int handle_event(); MWindow *mwindow; diff --git a/cinelerra-5.1/cinelerra/mainmenu.C b/cinelerra-5.1/cinelerra/mainmenu.C index a36efcce..0bf2973d 100644 --- a/cinelerra-5.1/cinelerra/mainmenu.C +++ b/cinelerra-5.1/cinelerra/mainmenu.C @@ -256,6 +256,7 @@ void MainMenu::create_objects() windowmenu->add_item(new BC_MenuItem("-")); windowmenu->add_item(split_x = new SplitX(mwindow)); windowmenu->add_item(split_y = new SplitY(mwindow)); + windowmenu->add_item(mixer_viewer = new MixerViewer(mwindow)); windowmenu->add_item(new TileWindows(mwindow,_("Default positions"),-1,_("Ctrl-P"),'p')); windowmenu->add_item(new TileWindows(mwindow,_("Tile left"),0)); windowmenu->add_item(new TileWindows(mwindow,_("Tile right"),1)); @@ -1526,3 +1527,16 @@ int SplitY::handle_event() } +MixerViewer::MixerViewer(MWindow *mwindow) + : BC_MenuItem(_("Mixer Viewer"), _("Shift-M"), 'M') +{ + this->mwindow = mwindow; + set_shift(1); +} + +int MixerViewer::handle_event() +{ + mwindow->start_mixer(); + return 1; +} + diff --git a/cinelerra-5.1/cinelerra/mainmenu.h b/cinelerra-5.1/cinelerra/mainmenu.h index 6e277aed..8300bcb4 100644 --- a/cinelerra-5.1/cinelerra/mainmenu.h +++ b/cinelerra-5.1/cinelerra/mainmenu.h @@ -43,6 +43,7 @@ class KeyframeCurveTypeMenu; class KeyframeCurveTypeItem; class SplitX; class SplitY; +class MixerViewer; #include "arraylist.h" @@ -146,6 +147,7 @@ public: ShowLWindow *show_lwindow; SplitX *split_x; SplitY *split_y; + MixerViewer *mixer_viewer; }; // ========================================= edit @@ -687,4 +689,12 @@ public: MWindow *mwindow; }; +class MixerViewer : public BC_MenuItem +{ +public: + MixerViewer(MWindow *mwindow); + int handle_event(); + MWindow *mwindow; +}; + #endif diff --git a/cinelerra-5.1/cinelerra/mainsession.C b/cinelerra-5.1/cinelerra/mainsession.C index 4ff969fd..f7224b4c 100644 --- a/cinelerra-5.1/cinelerra/mainsession.C +++ b/cinelerra-5.1/cinelerra/mainsession.C @@ -60,6 +60,8 @@ MainSession::MainSession(MWindow *mwindow) cwindow_fullscreen = 0; rwindow_fullscreen = 0; vwindow_fullscreen = 0; + zwindow_fullscreen = 0; + selected_zwindow = -1; actual_frame_rate = 0; window_config = 0; a_x11_host[0] = 0; diff --git a/cinelerra-5.1/cinelerra/mainsession.h b/cinelerra-5.1/cinelerra/mainsession.h index 81b2439f..ab53708d 100644 --- a/cinelerra-5.1/cinelerra/mainsession.h +++ b/cinelerra-5.1/cinelerra/mainsession.h @@ -173,7 +173,8 @@ public: int cwindow_fullscreen; int rwindow_fullscreen; int vwindow_fullscreen; - + int zwindow_fullscreen; + int selected_zwindow; double actual_frame_rate; diff --git a/cinelerra-5.1/cinelerra/menueffects.C b/cinelerra-5.1/cinelerra/menueffects.C index a0a661fd..b1f8a050 100644 --- a/cinelerra-5.1/cinelerra/menueffects.C +++ b/cinelerra-5.1/cinelerra/menueffects.C @@ -281,7 +281,7 @@ void MenuEffectThread::run() if(mwindow->edl->local_session->get_selectionend() == mwindow->edl->local_session->get_selectionstart()) - total_end = mwindow->edl->tracks->total_playable_length(); + total_end = mwindow->edl->tracks->total_length(); else total_end = mwindow->edl->local_session->get_selectionend(); diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index 238c17aa..9d3b4860 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -105,6 +105,7 @@ #include "theme.h" #include "threadloader.h" #include "timebar.h" +#include "timelinepane.h" #include "tipwindow.h" #include "trackcanvas.h" #include "track.h" @@ -124,6 +125,8 @@ #include "wavecache.h" #include "wwindow.h" #include "zoombar.h" +#include "zwindow.h" +#include "zwindowgui.h" #include "exportedl.h" #include "defaultformats.h" @@ -182,6 +185,7 @@ MWindow::MWindow() plugin_gui_lock = new Mutex("MWindow::plugin_gui_lock"); dead_plugin_lock = new Mutex("MWindow::dead_plugin_lock"); vwindows_lock = new Mutex("MWindow::vwindows_lock"); + zwindows_lock = new Mutex("MWindow::zwindows_lock"); brender_lock = new Mutex("MWindow::brender_lock"); keyframe_gui_lock = new Mutex("MWindow::keyframe_gui_lock"); @@ -274,6 +278,7 @@ MWindow::~MWindow() if( twindow && twindow->is_running() ) twindow->close_window(); if( wwindow && wwindow->is_running() ) wwindow->close_window(); vwindows.remove_all_objects(); + zwindows.remove_all_objects(); gui->close(0); if( awindow ) awindow->join(); if( cwindow ) cwindow->join(); @@ -294,6 +299,7 @@ MWindow::~MWindow() close_gui(twindow); close_gui(wwindow); vwindows.remove_all_objects(); + zwindows.remove_all_objects(); gui->close(0); join(); #endif @@ -338,6 +344,7 @@ MWindow::~MWindow() delete dead_plugin_lock; delete plugin_gui_lock; delete vwindows_lock; + delete zwindows_lock; delete brender_lock; delete keyframe_gui_lock; colormodels.remove_all_objects(); @@ -1118,6 +1125,154 @@ VWindow *MWindow::get_viewer(int start_it, int idx) return vwindow; } +ZWindow *MWindow::get_mixer(Mixer *&mixer) +{ + zwindows_lock->lock("MWindow::get_mixer"); + if( !mixer ) mixer = edl->mixers.new_mixer(); + ZWindow *zwindow = 0; + for( int i=0; !zwindow && iis_running() ) zwindow = zwindows[i]; + if( !zwindow ) + zwindows.append(zwindow = new ZWindow(this)); + zwindow->idx = mixer->idx; + zwindows_lock->unlock(); + return zwindow; +} + +void MWindow::del_mixer(ZWindow *zwindow) +{ + zwindows_lock->lock("MWindow::del_mixer 0"); + edl->mixers.del_mixer(zwindow->idx); + zwindow->idx = -1; + if( session->selected_zwindow >= 0 ) { + int i = zwindows.number_of(zwindow); + if( i >= 0 && i < session->selected_zwindow ) + --session->selected_zwindow; + else if( i == session->selected_zwindow ) + session->selected_zwindow = -1; + } + zwindows_lock->unlock(); + gui->lock_window("MWindow::del_mixer 1"); + gui->update_mixers(0, -1); + gui->unlock_window(); +} + +void MWindow::start_mixer() +{ + Mixer *mixer = 0; + ZWindow *zwindow = get_mixer(mixer); + const char *title = 0; + + for( Track *track=edl->tracks->first; track!=0; track=track->next ) { + PatchGUI *patchgui = get_patchgui(track); + if( !patchgui || !patchgui->mixer ) continue; + mixer->mixer_ids.append(track->get_mixer_id()); + if( !title ) title = track->title; + } + + session->selected_zwindow = -1; + gui->lock_window("MWindow::start_mixer"); + gui->update_mixers(0, 0); + gui->unlock_window(); + + zwindow->set_title(title); + zwindow->start(); + queue_mixers(edl,CURRENT_FRAME,0,0,1,0); +} + +int MWindow::mixer_track_active(Track *track) +{ + int i = session->selected_zwindow; + if( i < 0 || i >= zwindows.size() ) return 0; + ZWindow *zwindow = zwindows[i]; + Mixer *mixer = edl->mixers.get_mixer(zwindow->idx); + if( !mixer ) return 0; + int n = mixer->mixer_ids.number_of(track->get_mixer_id()); + return n >= 0 ? 1 : 0; +} + +void MWindow::update_mixer_tracks() +{ + zwindows_lock->lock("MixPatch::handle_event"); + int i = session->selected_zwindow; + if( i >= 0 && i < zwindows.size() ) { + ZWindow *zwindow = zwindows[i]; + zwindow->update_mixer_ids(); + } + zwindows_lock->unlock(); +} + +void MWindow::queue_mixers(EDL *edl, int command, int wait_tracking, + int use_inout, int update_refresh, int toggle_audio) +{ + zwindows_lock->lock("MWindow::queue_mixers"); + for( int vidx=0; vidxrunning() ) continue; + Mixer *mixer = edl->mixers.get_mixer(zwindow->idx); + if( !mixer || !mixer->mixer_ids.size() ) continue; + int k = -1; + for( Track *track = edl->tracks->first; k<0 && track!=0; track=track->next ) { + if( track->data_type != TRACK_VIDEO ) continue; + int mixer_id = track->get_mixer_id(); + k = mixer->mixer_ids.size(); + while( --k >= 0 && mixer_id != mixer->mixer_ids[k] ); + } + if( k < 0 ) continue; + EDL *mixer_edl = new EDL(this->edl); + mixer_edl->create_objects(); + mixer_edl->copy_all(edl); + mixer_edl->remove_vwindow_edls(); + for( Track *track = mixer_edl->tracks->first; track!=0; track=track->next ) { + k = mixer->mixer_ids.size(); + while( --k >= 0 && track->get_mixer_id() != mixer->mixer_ids[k] ); + if( k >= 0 ) { + track->record = 1; + track->play = track->data_type == TRACK_VIDEO ? 1 : 0; + } + else + track->record = track->play = 0; + } + zwindow->change_source(mixer_edl); + zwindow->issue_command(command, + wait_tracking, use_inout, update_refresh, toggle_audio); + } + zwindows_lock->unlock(); +} + +void MWindow::stop_mixers() +{ + for( int vidx=0; vidxrunning() ) continue; + zwindow->issue_command(STOP, 0, 0, 0, 0); + } +} + +int MWindow::select_zwindow(ZWindow *zwindow) +{ + int ret = 0, n = zwindows.number_of(zwindow); + if( session->selected_zwindow != n ) { + session->selected_zwindow = n; + for( int i=0; irunning() ) continue; + ZWindowGUI *zgui = zwindow->zgui; + zgui->lock_window("MWindow::select_zwindow 0"); + zwindow->highlighted = i == n ? 1 : 0; + if( zgui->draw_overlays() ) + zgui->canvas->get_canvas()->flash(1); + zgui->unlock_window(); + } + ret = 1; + gui->lock_window("MWindow::select_window 1"); + gui->update_mixers(0, -1); + gui->unlock_window(); + } + return ret; +} + + void MWindow::init_cache() { audio_cache = new CICache(preferences); @@ -1418,6 +1573,11 @@ void MWindow::stop_playback(int wait) if( !vwindow->is_running() ) continue; vwindow->playback_engine->stop_playback(); } + for(int i = 0; i < zwindows.size(); i++) { + ZWindow *zwindow = zwindows[i]; + if( !zwindow->is_running() ) continue; + zwindow->zgui->playback_engine->stop_playback(); + } if( locked ) gui->lock_window("MWindow::stop_playback"); } @@ -1820,7 +1980,7 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__); edl->session->proxy_use_scaler = 0; edl->session->proxy_auto_scale = 0; edl->local_session->preview_start = 0; - edl->local_session->preview_end = edl->tracks->total_playable_length(); + edl->local_session->preview_end = edl->tracks->total_length(); edl->local_session->loop_playback = 0; edl->local_session->set_selectionstart(0); edl->local_session->set_selectionend(0); @@ -2504,6 +2664,7 @@ void MWindow::sync_parameters(int change_type) } else { + queue_mixers(edl,CURRENT_FRAME,0,0,1,0); cwindow->playback_engine->que->send_command(CURRENT_FRAME, change_type, edl, @@ -3022,8 +3183,8 @@ void MWindow::update_project(int load_mode) if(debug) PRINT_TRACE // Close all the vwindows - if(load_mode == LOADMODE_REPLACE || - load_mode == LOADMODE_REPLACE_CONCATENATE) { + if( load_mode == LOADMODE_REPLACE || + load_mode == LOADMODE_REPLACE_CONCATENATE ) { if(debug) PRINT_TRACE int first_vwindow = 0; if(session->show_vwindow) first_vwindow = 1; @@ -3041,13 +3202,28 @@ void MWindow::update_project(int load_mode) vwindow->close_window(); } if(debug) PRINT_TRACE + select_zwindow(0); + for( int i=0; iis_running() ) continue; + zwindow->close_window(); + } + + for( int i=0; imixers.size(); ++i ) { + Mixer *mixer = edl->mixers[i]; + ZWindow *zwindow = get_mixer(mixer); + zwindow->set_title(mixer->title); + zwindow->start(); + } } - else if(vwindows.size()) { - VWindow *vwindow = vwindows[DEFAULT_VWINDOW]; - if( vwindow->is_running() ) { - vwindow->gui->lock_window("MWindow::update_project"); - vwindow->update(1); - vwindow->gui->unlock_window(); + else { + if(vwindows.size()) { + VWindow *vwindow = vwindows[DEFAULT_VWINDOW]; + if( vwindow->is_running() ) { + vwindow->gui->lock_window("MWindow::update_project"); + vwindow->update(1); + vwindow->gui->unlock_window(); + } } } @@ -3066,6 +3242,7 @@ void MWindow::update_project(int load_mode) if(debug) PRINT_TRACE gui->lock_window("MWindow::update_project"); + gui->update_mixers(0, 0); gui->flush(); if(debug) PRINT_TRACE } @@ -3198,6 +3375,8 @@ int MWindow::create_aspect_ratio(float &w, float &h, int width, int height) void MWindow::reset_caches() { + gui->resource_thread->get_video_source(0); + gui->resource_thread->get_audio_source(0); frame_cache->remove_all(); wave_cache->remove_all(); audio_cache->remove_all(); @@ -3838,4 +4017,19 @@ PanAuto* MWindow::get_pan_auto(PatchGUI *patch) return (PanAuto*)ptr->get_prev_auto( (long)unit_position, PLAY_FORWARD, current); } +PatchGUI *MWindow::get_patchgui(Track *track) +{ + PatchGUI *patchgui = 0; + TimelinePane **panes = gui->pane; + for( int i=0; ipatchbay; + if( !patchbay ) continue; + for( int j=0; jpatches.total && !patchgui; ++j ) { + if( patchbay->patches.values[j]->track == track ) + patchgui = patchbay->patches.values[j]; + } + } + return patchgui; +} diff --git a/cinelerra-5.1/cinelerra/mwindow.h b/cinelerra-5.1/cinelerra/mwindow.h index a7bd7e3d..8f26357e 100644 --- a/cinelerra-5.1/cinelerra/mwindow.h +++ b/cinelerra-5.1/cinelerra/mwindow.h @@ -95,6 +95,7 @@ #include "videowindow.inc" #include "vpatchgui.h" #include "vwindow.inc" +#include "zwindow.inc" #include "wwindow.inc" #include "wavecache.inc" @@ -203,8 +204,15 @@ public: void dump_plugindb(FILE *fp); void stop_playback(int wait=0); - - + void queue_mixers(EDL *edl, int command, int wait_tracking, + int use_inout, int update_refresh, int toggle_audio); + void stop_mixers(); + ZWindow *get_mixer(Mixer *&mixer); + void del_mixer(ZWindow *zwindow); + int mixer_track_active(Track *track); + void update_mixer_tracks(); + void start_mixer(); + int select_zwindow(ZWindow *zwindow); int load_filenames(ArrayList *filenames, int load_mode = LOADMODE_REPLACE, @@ -494,6 +502,7 @@ public: FloatAuto* get_float_auto(PatchGUI *patch,int idx); IntAuto* get_int_auto(PatchGUI *patch,int idx); PanAuto* get_pan_auto(PatchGUI *patch); + PatchGUI *get_patchgui(Track *track); int modify_edithandles(); int modify_pluginhandles(); @@ -600,6 +609,9 @@ public: // Viewer Mutex *vwindows_lock; ArrayList vwindows; +// Mixer + Mutex *zwindows_lock; + ArrayList zwindows; // Asset manager AWindow *awindow; // Automation window diff --git a/cinelerra-5.1/cinelerra/mwindow.inc b/cinelerra-5.1/cinelerra/mwindow.inc index 366236ff..9e872bc1 100644 --- a/cinelerra-5.1/cinelerra/mwindow.inc +++ b/cinelerra-5.1/cinelerra/mwindow.inc @@ -97,6 +97,7 @@ N_("Cinelerra: Load") N_("Cinelerra: Loading") N_("Cinelerra: Locate file") N_("Cinelerra: Mask") +N_("Cinelerra: Mixer") N_("Cinelerra: New folder") N_("Cinelerra: New Project") N_("Cinelerra: Normalize") diff --git a/cinelerra-5.1/cinelerra/mwindowedit.C b/cinelerra-5.1/cinelerra/mwindowedit.C index a149b275..4d77f8a9 100644 --- a/cinelerra-5.1/cinelerra/mwindowedit.C +++ b/cinelerra-5.1/cinelerra/mwindowedit.C @@ -1092,7 +1092,7 @@ void MWindow::overwrite(EDL *source) } source->copy(src_start, src_start + overwrite_len, - 1, 0, 0, &file, "", 1); + 0, 0, 0, &file, "", 1); // HACK around paste_edl get_start/endselection on its own // so we need to clear only when not using both io points @@ -1330,7 +1330,7 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, if( !new_edls->total ) return 0; //PRINT_TRACE -// double original_length = edl->tracks->total_playable_length(); +// double original_length = edl->tracks->total_length(); // double original_preview_end = edl->local_session->preview_end; //PRINT_TRACE @@ -1344,6 +1344,7 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, edl = new EDL; edl->create_objects(); edl->copy_session(new_edls->values[0]); + edl->copy_mixers(new_edls->values[0]); gui->mainmenu->update_toggles(0); gui->unlock_window(); gwindow->gui->update_toggles(1); @@ -1605,7 +1606,7 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, // Fix preview range // if( EQUIV(original_length, original_preview_end) ) // { -// edl->local_session->preview_end = edl->tracks->total_playable_length(); +// edl->local_session->preview_end = edl->tracks->total_length(); // } // Start examining next batch of index files diff --git a/cinelerra-5.1/cinelerra/mwindowgui.C b/cinelerra-5.1/cinelerra/mwindowgui.C index 7587d46d..8825e25d 100644 --- a/cinelerra-5.1/cinelerra/mwindowgui.C +++ b/cinelerra-5.1/cinelerra/mwindowgui.C @@ -2236,6 +2236,23 @@ void MWindowGUI::draw_trackmovement() } +void MWindowGUI::update_mixers(Track *track, int v) +{ + for( int i=0; ipatchbay; + if( !patchbay ) continue; + for( int j=0; jpatches.total; ++j ) { + PatchGUI *patchgui = patchbay->patches.values[j]; + if( !patchgui->mix ) continue; + if( !track || patchgui->track == track ) { + patchgui->mix->update(v>=0 ? v : + mwindow->mixer_track_active(patchgui->track)); + } + } + } +} + PaneButton::PaneButton(MWindow *mwindow, int x, int y) : BC_Button(x, y, mwindow->theme->get_image_set("pane")) { diff --git a/cinelerra-5.1/cinelerra/mwindowgui.h b/cinelerra-5.1/cinelerra/mwindowgui.h index 2d5fd10c..4eb54cf0 100644 --- a/cinelerra-5.1/cinelerra/mwindowgui.h +++ b/cinelerra-5.1/cinelerra/mwindowgui.h @@ -51,6 +51,7 @@ #include "statusbar.inc" #include "swindow.inc" #include "timelinepane.inc" +#include "track.inc" #include "trackcanvas.inc" #include "trackscroll.inc" #include "transitionpopup.inc" @@ -127,6 +128,7 @@ public: void set_playing_back(int value); void set_editing_mode(int flush); void set_meter_format(int mode, int min, int max); + void update_mixers(Track *track, int v); int translation_event(); int resize_event(int w, int h); // handle a resize event diff --git a/cinelerra-5.1/cinelerra/patchgui.C b/cinelerra-5.1/cinelerra/patchgui.C index 3a20d44c..a2a19864 100644 --- a/cinelerra-5.1/cinelerra/patchgui.C +++ b/cinelerra-5.1/cinelerra/patchgui.C @@ -42,7 +42,7 @@ #include "tracks.h" #include "transportque.h" #include "vframe.h" - +#include "zwindow.h" PatchGUI::PatchGUI(MWindow *mwindow, @@ -65,22 +65,24 @@ PatchGUI::PatchGUI(MWindow *mwindow, mute = 0; expand = 0; nudge = 0; + mix = 0; change_source = 0; - track_id = -1; - if(track) track_id = track->get_id(); + track_id = track ? track->get_id() : -1; + mixer = 0; } PatchGUI::~PatchGUI() { - if(title) delete title; - if(record) delete record; - if(play) delete play; -// if(automate) delete automate; - if(gang) delete gang; - if(draw) delete draw; - if(mute) delete mute; - if(expand) delete expand; - if(nudge) delete nudge; + delete title; + delete record; + delete play; +// delete automate; + delete gang; + delete draw; + delete mute; + delete expand; + delete nudge; + delete mix; } void PatchGUI::create_objects() @@ -789,5 +791,34 @@ void NudgePatch::update() } +MixPatch::MixPatch(MWindow *mwindow, PatchGUI *patch, int x, int y) + : BC_Toggle(x, y, mwindow->theme->get_image_set("mixpatch_data"), + patch->mixer, "", 0, 0, 0) +{ + this->mwindow = mwindow; + this->patch = patch; +} + +MixPatch::~MixPatch() +{ +} + +int MixPatch::handle_event() +{ + int v = patch->track ? get_value() : 0; + if( patch->mixer != v ) { + if( patch->track ) + mwindow->gui->update_mixers(patch->track, v); + else + update(v); + mwindow->update_mixer_tracks(); + } + return 1; +} +void MixPatch::update(int v) +{ + patch->mixer = v; + BC_Toggle::update(v); +} diff --git a/cinelerra-5.1/cinelerra/patchgui.h b/cinelerra-5.1/cinelerra/patchgui.h index e16dfce5..126b0666 100644 --- a/cinelerra-5.1/cinelerra/patchgui.h +++ b/cinelerra-5.1/cinelerra/patchgui.h @@ -40,6 +40,7 @@ class DrawPatch; class MutePatch; class ExpandPatch; class NudgePatch; +class MixPatch; class PatchGUI { @@ -69,7 +70,7 @@ public: // Used by update routines so non-existent track doesn't need to be dereferenced // to know it doesn't match the current EDL. int track_id; - int data_type; + int data_type, mixer; int x, y; // Don't synchronize the fader if this is true. int change_source; @@ -83,6 +84,7 @@ public: MutePatch *mute; ExpandPatch *expand; NudgePatch *nudge; + MixPatch *mix; char string_return[BCTEXTLEN]; }; @@ -181,5 +183,17 @@ public: PatchGUI *patch; }; +class MixPatch : public BC_Toggle +{ +public: + MixPatch(MWindow *mwindow, PatchGUI *patch, int x, int y); + ~MixPatch(); + int handle_event(); + void update(int v); + + MWindow *mwindow; + PatchGUI *patch; +}; + #endif diff --git a/cinelerra-5.1/cinelerra/playbackengine.C b/cinelerra-5.1/cinelerra/playbackengine.C index 7dcea2df..0918ead4 100644 --- a/cinelerra-5.1/cinelerra/playbackengine.C +++ b/cinelerra-5.1/cinelerra/playbackengine.C @@ -425,3 +425,68 @@ void PlaybackEngine::stop_playback() renderengine_lock->unlock(); } + +void PlaybackEngine::issue_command(EDL *edl, int command, int wait_tracking, + int use_inout, int update_refresh, int toggle_audio) +{ +//printf("PlayTransport::handle_transport 1 %d\n", command); +// Stop requires transferring the output buffer to a refresh buffer. + int do_stop = 0, resume = 0; + int prev_command = this->command->command; + int prev_single_frame = this->command->single_frame(); + int prev_audio = this->command->audio_toggle ? + !prev_single_frame : prev_single_frame; + int cur_single_frame = TransportCommand::single_frame(command); + int cur_audio = toggle_audio ? + !cur_single_frame : cur_single_frame; + +// Dispatch command + switch(command) { + case FAST_REWIND: // Commands that play back + case NORMAL_REWIND: + case SLOW_REWIND: + case SINGLE_FRAME_REWIND: + case SINGLE_FRAME_FWD: + case SLOW_FWD: + case NORMAL_FWD: + case FAST_FWD: + if( !prev_single_frame && + prev_command == command && + cur_audio == prev_audio ) { +// Same direction pressed twice and no change in audio state, Stop + do_stop = 1; + break; + } +// Resume or change direction + switch( prev_command ) { + default: + que->send_command(STOP, CHANGE_NONE, 0, 0); + interrupt_playback(wait_tracking); + resume = 1; +// fall through + case STOP: + case COMMAND_NONE: + case SINGLE_FRAME_FWD: + case SINGLE_FRAME_REWIND: +// Start from scratch + que->send_command(command, CHANGE_NONE, edl, + 1, resume, use_inout, toggle_audio, + mwindow->preferences->forward_render_displacement); + break; + } + break; + +// Commands that stop + case STOP: + case REWIND: + case GOTO_END: + do_stop = 1; + break; + } + + if( do_stop ) { + que->send_command(STOP, CHANGE_NONE, 0, 0); + interrupt_playback(wait_tracking); + } +} + diff --git a/cinelerra-5.1/cinelerra/playbackengine.h b/cinelerra-5.1/cinelerra/playbackengine.h index 9d2d35e3..1dd0482e 100644 --- a/cinelerra-5.1/cinelerra/playbackengine.h +++ b/cinelerra-5.1/cinelerra/playbackengine.h @@ -82,6 +82,8 @@ public: void run(); void stop_playback(); + void issue_command(EDL *edl, int command, int wait_tracking, + int use_inout, int update_refresh, int toggle_audio); // Maintain caches through console changes CICache *audio_cache, *video_cache; diff --git a/cinelerra-5.1/cinelerra/playtransport.C b/cinelerra-5.1/cinelerra/playtransport.C index 6fc55d63..c7334213 100644 --- a/cinelerra-5.1/cinelerra/playtransport.C +++ b/cinelerra-5.1/cinelerra/playtransport.C @@ -179,8 +179,13 @@ int PlayTransport::flip_vertical(int vertical, int &x, int &y) int PlayTransport::keypress_event() { - int result = 1; int key = subwindow->get_keypress(); + return do_keypress(key); +} + +int PlayTransport::do_keypress(int key) +{ + int result = 1; // unqualified keys, still holding lock switch( key ) { case HOME: @@ -275,71 +280,13 @@ void PlayTransport::goto_end() void PlayTransport::handle_transport(int command, int wait_tracking, int use_inout, int update_refresh, int toggle_audio) { - if( !get_edl() ) return; - -// Stop requires transferring the output buffer to a refresh buffer. - int do_stop = 0; - int resume = 0; -//printf("PlayTransport::handle_transport 1 %d\n", command); - int prev_command = engine->command->command; - int prev_single_frame = engine->command->single_frame(); - int prev_audio = engine->command->audio_toggle ? - !prev_single_frame : prev_single_frame; - int cur_single_frame = TransportCommand::single_frame(command); - int cur_audio = toggle_audio ? - !cur_single_frame : cur_single_frame; - -// Dispatch command - switch(command) { - case FAST_REWIND: // Commands that play back - case NORMAL_REWIND: - case SLOW_REWIND: - case SINGLE_FRAME_REWIND: - case SINGLE_FRAME_FWD: - case SLOW_FWD: - case NORMAL_FWD: - case FAST_FWD: - if( !prev_single_frame && - prev_command == command && - cur_audio == prev_audio ) { -// Same direction pressed twice and no change in audio state, Stop - do_stop = 1; - break; - } -// Resume or change direction - switch( prev_command ) { - default: - engine->que->send_command(STOP, CHANGE_NONE, 0, 0); - engine->interrupt_playback(wait_tracking); - resume = 1; -// fall through - case STOP: - case COMMAND_NONE: - case SINGLE_FRAME_FWD: - case SINGLE_FRAME_REWIND: -// Start from scratch - engine->que->send_command(command, CHANGE_NONE, get_edl(), - 1, resume, use_inout, toggle_audio, - mwindow->preferences->forward_render_displacement); - break; - } - break; - -// Commands that stop - case STOP: - case REWIND: - case GOTO_END: - do_stop = 1; - break; - } - - if( do_stop ) { - engine->que->send_command(STOP, CHANGE_NONE, 0, 0); - engine->interrupt_playback(wait_tracking); - } + EDL *edl = get_edl(); + if( !edl ) return; + if( !is_vwindow() ) + mwindow->queue_mixers(edl, command, wait_tracking, use_inout, update_refresh, toggle_audio); + engine->issue_command(edl, command, wait_tracking, use_inout, update_refresh, toggle_audio); } - EDL* PlayTransport::get_edl() { return mwindow->edl; @@ -514,8 +461,7 @@ int StopButton::handle_event() void PlayTransport::change_position(double position) { - EDL *edl = get_edl(); - if( !edl ) return; + if( !get_edl() ) return; int prev_command = engine->command->command; // stop transport if( prev_command != STOP && prev_command != COMMAND_NONE && diff --git a/cinelerra-5.1/cinelerra/playtransport.h b/cinelerra-5.1/cinelerra/playtransport.h index 11233b2b..62d1973a 100644 --- a/cinelerra-5.1/cinelerra/playtransport.h +++ b/cinelerra-5.1/cinelerra/playtransport.h @@ -49,6 +49,7 @@ public: static int get_transport_width(MWindow *mwindow); int flip_vertical(int vertical, int &x, int &y); int keypress_event(); + int do_keypress(int key); // Abstract TransportQue::send_command. // wait_tracking - causes stop to wail until the final tracking position // is updated before returning @@ -65,6 +66,7 @@ public: // Get the EDL to play back with default to mwindow->edl virtual EDL* get_edl(); void change_position(double position); + virtual int is_vwindow() { return 0; } // playback parameters int reverse; diff --git a/cinelerra-5.1/cinelerra/renderengine.C b/cinelerra-5.1/cinelerra/renderengine.C index 628255b5..f5c0754a 100644 --- a/cinelerra-5.1/cinelerra/renderengine.C +++ b/cinelerra-5.1/cinelerra/renderengine.C @@ -90,7 +90,7 @@ RenderEngine::~RenderEngine() delete interrupt_lock; delete first_frame_lock; delete config; - edl->Garbage::remove_user(); + if( edl ) edl->Garbage::remove_user(); } EDL* RenderEngine::get_edl() diff --git a/cinelerra-5.1/cinelerra/savefile.C b/cinelerra-5.1/cinelerra/savefile.C index 8b3bc74a..00dee981 100644 --- a/cinelerra-5.1/cinelerra/savefile.C +++ b/cinelerra-5.1/cinelerra/savefile.C @@ -132,6 +132,7 @@ int Save::save_before_quit() SaveAs::SaveAs(MWindow *mwindow) : BC_MenuItem(_("Save as..."), "Shift-S", 'S'), Thread() { + set_shift(1); this->mwindow = mwindow; quit_now = 0; } diff --git a/cinelerra-5.1/cinelerra/theme.C b/cinelerra-5.1/cinelerra/theme.C index bddba878..be8aac82 100644 --- a/cinelerra-5.1/cinelerra/theme.C +++ b/cinelerra-5.1/cinelerra/theme.C @@ -238,6 +238,8 @@ void Theme::initialize() new_image("awindow_icon", "heroine_icon.png"); new_image("record_icon", "heroine_icon.png"); new_image("clip_icon", "clip_icon.png"); + new_image_set("mixpatch_data", 5, "mixpatch_up.png", "mixpatch_hi.png", + "mixpatch_checked.png", "mixpatch_dn.png", "mixpatch_checkedhi.png"); new_image("aeffect_icon", "aeffect_icon.png"); @@ -951,8 +953,8 @@ void Theme::get_vwindow_sizes(VWindowGUI *gui) widget_border; vdivision_x = 280; - vtime_x = vdivision_x; - vtime_y = vedit_y + 20; + vtime_x = vedit_x + 20; //vdivision_x; + vtime_y = vedit_y + 30; //+ 20; } else { diff --git a/cinelerra-5.1/cinelerra/timebar.C b/cinelerra-5.1/cinelerra/timebar.C index d33d4ea3..03fa0357 100644 --- a/cinelerra-5.1/cinelerra/timebar.C +++ b/cinelerra-5.1/cinelerra/timebar.C @@ -522,8 +522,8 @@ double TimeBar::get_edl_length() edl_length = 0; if( get_edl() ) { -//printf("TimeBar::get_edl_length 1 %f\n", get_edl()->tracks->total_playable_length()); - edl_length = get_edl()->tracks->total_playable_length(); +//printf("TimeBar::get_edl_length 1 %f\n", get_edl()->tracks->total_length()); + edl_length = get_edl()->tracks->total_length(); } //printf("TimeBar::get_edl_length 2\n"); diff --git a/cinelerra-5.1/cinelerra/track.C b/cinelerra-5.1/cinelerra/track.C index f3852cf9..e3f624c0 100644 --- a/cinelerra-5.1/cinelerra/track.C +++ b/cinelerra-5.1/cinelerra/track.C @@ -66,6 +66,7 @@ Track::Track(EDL *edl, Tracks *tracks) : ListItem() track_w = edl->session->output_w; track_h = edl->session->output_h; id = EDL::next_id(); + mixer_id = -1; } Track::~Track() @@ -87,6 +88,7 @@ int Track::copy_settings(Track *track) this->gang = track->gang; this->record = track->record; this->nudge = track->nudge; + this->mixer_id = track->mixer_id; this->play = track->play; this->track_w = track->track_w; this->track_h = track->track_h; @@ -321,6 +323,7 @@ int Track::load(FileXML *file, int track_offset, uint32_t load_flags) gang = file->tag.get_property("GANG", gang); draw = file->tag.get_property("DRAW", draw); nudge = file->tag.get_property("NUDGE", nudge); + mixer_id = file->tag.get_property("MIXER_ID", mixer_id); expand_view = file->tag.get_property("EXPAND", expand_view); track_w = file->tag.get_property("TRACK_W", track_w); track_h = file->tag.get_property("TRACK_H", track_h); @@ -1068,6 +1071,7 @@ int Track::copy(double start, file->tag.set_title("TRACK"); file->tag.set_property("RECORD", record); 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("DRAW", draw); @@ -1866,3 +1870,14 @@ int Track::plugin_exists(Plugin *plugin) return 0; } +int Track::get_mixer_id() +{ + if( mixer_id < 0 ) { + int v = 0; + for( Track *track=tracks->first; track!=0; track=track->next ) + if( track->mixer_id > v ) v = track->mixer_id; + mixer_id = v + 1; + } + return mixer_id; +} + diff --git a/cinelerra-5.1/cinelerra/track.h b/cinelerra-5.1/cinelerra/track.h index c8e561ff..1f6283f3 100644 --- a/cinelerra-5.1/cinelerra/track.h +++ b/cinelerra-5.1/cinelerra/track.h @@ -69,6 +69,7 @@ public: virtual int load_header(FileXML *file, uint32_t load_flags) { return 0; }; virtual int load_derived(FileXML *file, uint32_t load_flags) { return 0; }; void equivalent_output(Track *track, double *result); + int get_mixer_id(); virtual void copy_from(Track *track); Track& operator=(Track& track); @@ -173,9 +174,6 @@ public: int plugin_used(int64_t position, int64_t direction); - - - virtual int copy_settings(Track *track); void shift_keyframes(int64_t position, int64_t length); void shift_effects(int64_t position, int64_t length, int edit_autos); @@ -213,23 +211,6 @@ public: int data_type; - - - - - - - - - - - - - - - - - int load_automation(FileXML *file); int load_edits(FileXML *file); @@ -374,9 +355,7 @@ public: int pixel; // pixel position from top of track view // Dimensions of this track if video int track_w, track_h; - - - + int mixer_id; private: // Identification of the track diff --git a/cinelerra-5.1/cinelerra/tracking.C b/cinelerra-5.1/cinelerra/tracking.C index 91609c3c..4ba197e5 100644 --- a/cinelerra-5.1/cinelerra/tracking.C +++ b/cinelerra-5.1/cinelerra/tracking.C @@ -98,6 +98,7 @@ int Tracking::stop_playback() // Thread::cancel(); Thread::join(); + mwindow->stop_mixers(); // Final position is updated continuously during playback // Get final position double position = get_tracking_position(); diff --git a/cinelerra-5.1/cinelerra/tracks.C b/cinelerra-5.1/cinelerra/tracks.C index 8db132bc..1eec0d41 100644 --- a/cinelerra-5.1/cinelerra/tracks.C +++ b/cinelerra-5.1/cinelerra/tracks.C @@ -491,15 +491,18 @@ double Tracks::total_playable_length() double total = 0; for(Track *current = first; current; current = NEXT) { - double length = current->get_length(); - if(length > total) total = length; + if( current->play ) + { + double length = current->get_length(); + if(length > total) total = length; + } } return total; } double Tracks::total_recordable_length() { - double total = 0; + double total = -1; for(Track *current = first; current; current = NEXT) { if(current->record) @@ -516,7 +519,8 @@ double Tracks::total_length() double total = 0; for(Track *current = first; current; current = NEXT) { - if(current->get_length() > total) total = current->get_length(); + double length = current->get_length(); + if(length > total) total = length; } return total; } diff --git a/cinelerra-5.1/cinelerra/transportque.C b/cinelerra-5.1/cinelerra/transportque.C index 01ba565d..a2a5160a 100644 --- a/cinelerra-5.1/cinelerra/transportque.C +++ b/cinelerra-5.1/cinelerra/transportque.C @@ -184,6 +184,9 @@ void TransportCommand::set_playback_range(EDL *edl, end_position = end; } else { +// starting play at or past end, play to end of media (for mixers) + if( start >= length ) + length = edl->tracks->total_length(); switch( command ) { case SLOW_FWD: case FAST_FWD: @@ -251,8 +254,11 @@ void TransportCommand::playback_range_inout() if(edl->local_session->outpoint_valid()) end_position = edl->local_session->get_outpoint(); - else + else { end_position = edl->tracks->total_playable_length(); + if( start_position >= end_position ) + end_position = edl->tracks->total_length(); + } } void TransportCommand::playback_range_project() diff --git a/cinelerra-5.1/cinelerra/vedit.C b/cinelerra-5.1/cinelerra/vedit.C index f8469b10..c40f72d8 100644 --- a/cinelerra-5.1/cinelerra/vedit.C +++ b/cinelerra-5.1/cinelerra/vedit.C @@ -147,7 +147,7 @@ int64_t VEdit::get_source_end(int64_t default_) if(nested_edl) { - return (int64_t)(nested_edl->tracks->total_playable_length() * + return (int64_t)(nested_edl->tracks->total_length() * edl->session->frame_rate + 0.5); } diff --git a/cinelerra-5.1/cinelerra/vmodule.C b/cinelerra-5.1/cinelerra/vmodule.C index 0c8e1b7f..28f5a6d3 100644 --- a/cinelerra-5.1/cinelerra/vmodule.C +++ b/cinelerra-5.1/cinelerra/vmodule.C @@ -293,7 +293,7 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit, } else { - max_position = Units::to_int64(nested_edl->tracks->total_playable_length() * + max_position = Units::to_int64(nested_edl->tracks->total_length() * frame_rate - 1); } diff --git a/cinelerra-5.1/cinelerra/vpatchgui.C b/cinelerra-5.1/cinelerra/vpatchgui.C index dca01ad3..8b9c0b47 100644 --- a/cinelerra-5.1/cinelerra/vpatchgui.C +++ b/cinelerra-5.1/cinelerra/vpatchgui.C @@ -40,13 +40,11 @@ #include "trackcanvas.h" #include "vpatchgui.h" #include "vtrack.h" +#include "vwindow.h" #include - - - VPatchGUI::VPatchGUI(MWindow *mwindow, PatchBay *patchbay, VTrack *track, int x, int y) : PatchGUI(mwindow, patchbay, track, x, y) { @@ -58,8 +56,8 @@ VPatchGUI::VPatchGUI(MWindow *mwindow, PatchBay *patchbay, VTrack *track, int x, VPatchGUI::~VPatchGUI() { - if(fade) delete fade; - if(mode) delete mode; + if( fade ) delete fade; + if( mode ) delete mode; } void VPatchGUI::create_objects() @@ -72,20 +70,16 @@ int VPatchGUI::reposition(int x, int y) //int x1 = 0; int y1 = PatchGUI::reposition(x, y); - if(fade) fade->reposition_window(fade->get_x(), - y1 + y); - + if( fade ) + fade->reposition_window(fade->get_x(), y1+y); y1 += mwindow->theme->fade_h; - - if(mode) mode->reposition_window(mode->get_x(), - y1 + y); - - if(nudge) nudge->reposition_window(nudge->get_x(), - y1 + y); - - + if( mix ) + mix->reposition_window(mix->get_x(), y1+y); + if( mode ) + mode->reposition_window(mode->get_x(), y1+y); + if( nudge ) + nudge->reposition_window(nudge->get_x(), y1+y); y1 += mwindow->theme->mode_h; - return y1; } @@ -95,68 +89,51 @@ int VPatchGUI::update(int x, int y) int x1 = 0; int y1 = PatchGUI::update(x, y); - if(fade) - { - if(h - y1 < mwindow->theme->fade_h) - { + if( fade ) { + if( h - y1 < mwindow->theme->fade_h ) { delete fade; fade = 0; } - else - { + else { fade->update(fade->get_w(), mwindow->get_float_auto(this, AUTOMATION_FADE)->get_value(), mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_VIDEO_FADE], mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_VIDEO_FADE]); } } else - if(h - y1 >= mwindow->theme->fade_h) - { - patchbay->add_subwindow(fade = new VFadePatch(mwindow, - this, - x1 + x, - y1 + y, + if( h - y1 >= mwindow->theme->fade_h ) { + patchbay->add_subwindow(fade = new VFadePatch(mwindow, this, x1+x, y1+y, patchbay->get_w() - 10)); } y1 += mwindow->theme->fade_h; - if(mode) - { - if(h - y1 < mwindow->theme->mode_h) - { - delete mode; - mode = 0; - delete nudge; - nudge = 0; + if( mode ) { + if( h - y1 < mwindow->theme->mode_h ) { + delete mix; mix = 0; + delete mode; mode = 0; + delete nudge; nudge = 0; } - else - { + else { + if( mwindow->session->selected_zwindow >= 0 ) { + int v = mwindow->mixer_track_active(track); + mix->update(v); + } mode->update(mwindow->get_int_auto(this, AUTOMATION_MODE)->value); nudge->update(); } } else - if(h - y1 >= mwindow->theme->mode_h) - { - patchbay->add_subwindow(mode = new VModePatch(mwindow, - this, - x1 + x, - y1 + y)); + if( h - y1 >= mwindow->theme->mode_h ) { + patchbay->add_subwindow(mix = new VMixPatch(mwindow, this, x1+x, y1+y+5)); + x1 += mix->get_w(); + patchbay->add_subwindow(mode = new VModePatch(mwindow, this, x1+x, y1+y)); mode->create_objects(); - x1 += mode->get_w() + 10; - patchbay->add_subwindow(nudge = new NudgePatch(mwindow, - this, - x1 + x, - y1 + y, - patchbay->get_w() - x1 - 10)); + x1 += mode->get_w(); + patchbay->add_subwindow(nudge = new NudgePatch(mwindow, this, x1+x, y1+y, + patchbay->get_w() - x1-x - 10)); } - - - - y1 += mwindow->theme->mode_h; - return y1; } @@ -164,8 +141,7 @@ int VPatchGUI::update(int x, int y) void VPatchGUI::synchronize_fade(float value_change) { - if(fade && !change_source) - { + if( fade && !change_source ) { fade->update(Units::to_int64(fade->get_value() + value_change)); fade->update_edl(); } @@ -203,8 +179,7 @@ float VFadePatch::update_edl() int VFadePatch::handle_event() { - if(shift_down()) - { + if( shift_down() ) { update(100); set_tooltip(get_caption()); } @@ -213,7 +188,7 @@ int VFadePatch::handle_event() float change = update_edl(); - if(patch->track->gang && patch->track->record) + if( patch->track->gang && patch->track->record ) patch->patchbay->synchronize_faders(change, TRACK_VIDEO, patch->track); patch->change_source = 0; @@ -223,8 +198,7 @@ int VFadePatch::handle_event() mwindow->restart_brender(); mwindow->sync_parameters(CHANGE_PARAMS); mwindow->gui->lock_window("VFadePatch::handle_event"); - if(mwindow->edl->session->auto_conf->autos[AUTOMATION_FADE]) - { + if( mwindow->edl->session->auto_conf->autos[AUTOMATION_FADE] ) { mwindow->gui->draw_overlays(1); } return 1; @@ -271,9 +245,6 @@ int VKeyFadeValue::handle_event() } - - - VModePatch::VModePatch(MWindow *mwindow, VPatchGUI *patch, int x, int y) : BC_PopupMenu(x, y, patch->patchbay->mode_icons[0]->get_w() + 20, "", 1, mwindow->theme->get_image_set("mode_popup", 0), 10) @@ -297,10 +268,10 @@ VModePatch::VModePatch(MWindow *mwindow, VPatchGUI *patch) int VModePatch::handle_event() { // Set menu items -// for(int i = 0; i < total_items(); i++) +// for( int i = 0; i < total_items(); i++ ) // { // VModePatchItem *item = (VModePatchItem*)get_item(i); -// if(item->mode == mode) +// if( item->mode == mode ) // item->set_checked(1); // else // item->set_checked(0); @@ -322,8 +293,7 @@ int VModePatch::handle_event() mwindow->sync_parameters(CHANGE_PARAMS); - if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MODE]) - { + if( mwindow->edl->session->auto_conf->autos[AUTOMATION_MODE] ) { mwindow->gui->draw_overlays(1); } mwindow->session->changes_made = 1; @@ -377,8 +347,7 @@ void VModePatch::create_objects() void VModePatch::update(int mode) { set_icon(patch->patchbay->mode_to_icon(mode)); - for(int i = 0; i < total_items(); i++) - { + for( int i = 0; i < total_items(); i++ ) { VModePatchItem *item = (VModePatchItem*)get_item(i); item->set_checked(item->mode == mode); VModePatchSubMenu *submenu = (VModePatchSubMenu *)item->get_submenu(); @@ -394,7 +363,7 @@ void VModePatch::update(int mode) const char* VModePatch::mode_to_text(int mode) { - switch(mode) { + switch( mode ) { case TRANSFER_NORMAL: return _("Normal"); case TRANSFER_ADDITION: return _("Addition"); case TRANSFER_SUBTRACT: return _("Subtract"); @@ -436,7 +405,7 @@ VModePatchItem::VModePatchItem(VModePatch *popup, const char *text, int mode) { this->popup = popup; this->mode = mode; - if(this->mode == popup->mode) set_checked(1); + if( this->mode == popup->mode ) set_checked(1); } int VModePatchItem::handle_event() @@ -463,7 +432,7 @@ VModeSubMenuItem::VModeSubMenuItem(VModePatchSubMenu *submenu, const char *text, this->submenu = submenu; this->mode = mode; VModePatch *popup = submenu->mode_item->popup; - if(this->mode == popup->mode) set_checked(1); + if( this->mode == popup->mode ) set_checked(1); } VModeSubMenuItem::~VModeSubMenuItem() { @@ -500,4 +469,13 @@ int VKeyModePatch::handle_event() } +VMixPatch::VMixPatch(MWindow *mwindow, VPatchGUI *patch, int x, int y) + : MixPatch(mwindow, patch, x, y) +{ + set_tooltip(_("Mixer")); +} + +VMixPatch::~VMixPatch() +{ +} diff --git a/cinelerra-5.1/cinelerra/vpatchgui.h b/cinelerra-5.1/cinelerra/vpatchgui.h index ff6b98d3..d071fb00 100644 --- a/cinelerra-5.1/cinelerra/vpatchgui.h +++ b/cinelerra-5.1/cinelerra/vpatchgui.h @@ -138,5 +138,11 @@ public: int handle_event(); }; +class VMixPatch : public MixPatch +{ +public: + VMixPatch(MWindow *mwindow, VPatchGUI *patch, int x, int y); + ~VMixPatch(); +}; #endif diff --git a/cinelerra-5.1/cinelerra/vwindowgui.C b/cinelerra-5.1/cinelerra/vwindowgui.C index f5fef954..0642dd81 100644 --- a/cinelerra-5.1/cinelerra/vwindowgui.C +++ b/cinelerra-5.1/cinelerra/vwindowgui.C @@ -879,7 +879,7 @@ void VWindowGUI::update_points() //printf("VWindowGUI::update_points 2\n"); long pixel = (long)((double)edl->local_session->in_point / - edl->tracks->total_playable_length() * + edl->tracks->total_length() * (mwindow->theme->vtimebar_w - 2 * mwindow->theme->in_point[0]->get_w())) + @@ -931,7 +931,7 @@ void VWindowGUI::update_points() //printf("VWindowGUI::update_points 10\n"); pixel = (long)((double)edl->local_session->out_point / - (edl->tracks->total_playable_length() + 0.5) * + (edl->tracks->total_length() + 0.5) * (mwindow->theme->vtimebar_w - 2 * mwindow->theme->in_point[0]->get_w())) + diff --git a/cinelerra-5.1/cinelerra/vwindowgui.h b/cinelerra-5.1/cinelerra/vwindowgui.h index 51971a8a..424e9e50 100644 --- a/cinelerra-5.1/cinelerra/vwindowgui.h +++ b/cinelerra-5.1/cinelerra/vwindowgui.h @@ -181,6 +181,7 @@ public: EDL* get_edl(); void goto_start(); void goto_end(); + int is_vwindow() { return 1; } VWindowGUI *gui; }; diff --git a/cinelerra-5.1/cinelerra/zwindow.C b/cinelerra-5.1/cinelerra/zwindow.C new file mode 100644 index 00000000..29a28a1b --- /dev/null +++ b/cinelerra-5.1/cinelerra/zwindow.C @@ -0,0 +1,261 @@ + +/* + * CINELERRA + * Copyright (C) 1997-2012 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "bcdialog.h" +#include "edl.h" +#include "filexml.h" +#include "language.h" +#include "mainsession.h" +#include "mwindow.h" +#include "mwindowgui.h" +#include "patchbay.h" +#include "patchgui.h" +#include "playbackengine.h" +#include "renderengine.h" +#include "timelinepane.h" +#include "track.h" +#include "transportque.h" +#include "zwindow.h" +#include "zwindowgui.h" + +Mixers::Mixers() +{ +} + +Mixers::~Mixers() +{ + remove_all_objects(); +} + +Mixer *Mixers::new_mixer() +{ + int idx = 0; + for( int i=0; iidx ) idx = mixer->idx; + } + return append(new Mixer(idx+1)); +} + +Mixer *Mixers::get_mixer(int idx) +{ + for( int i=0; iidx == idx ) return mixer; + } + return 0; +} + +void Mixers::del_mixer(int idx) +{ + Mixer *mixer = get_mixer(idx); + if( mixer ) remove_object(mixer); +} + +void Mixer::set_title(const char *tp) +{ + strncpy(title, tp, sizeof(title)); + title[sizeof(title)-1] = 0; +} + +void Mixers::save(FileXML *file) +{ + file->tag.set_title("MIXERS"); + file->append_tag(); + file->append_newline(); + for( int i=0; isave(file); + } + file->tag.set_title("/MIXERS"); + file->append_tag(); + file->append_newline(); +} + +int Mixers::load(FileXML *file) +{ + int result = 0; + while( !(result = file->read_tag()) ) { + if( file->tag.title_is("/MIXERS") ) break; + if( file->tag.title_is("MIXER") ) { + Mixer *mixer = new_mixer(); + file->tag.get_property("TITLE", mixer->title); + mixer->x = file->tag.get_property("X", mixer->x); + mixer->y = file->tag.get_property("Y", mixer->y); + mixer->w = file->tag.get_property("W", mixer->w); + mixer->h = file->tag.get_property("H", mixer->h); + mixer->load(file); + } + } + return 0; +} + +void Mixers::copy_from(Mixers &that) +{ + remove_all_objects(); + for( int i=0; icopy_from(*that[i]); + } +} + +void Mixer::save(FileXML *file) +{ + file->tag.set_title("MIXER"); + file->tag.set_property("TITLE",title); + file->tag.set_property("X",x); + file->tag.set_property("Y",y); + file->tag.set_property("W",w); + file->tag.set_property("H",h); + file->append_tag(); + file->append_newline(); + for( int i=0; itag.set_title("MIX"); + file->tag.set_property("ID", mixer_ids[i]); + file->append_tag(); + file->tag.set_title("/MIX"); + file->append_tag(); + file->append_newline(); + } + file->tag.set_title("/MIXER"); + file->append_tag(); + file->append_newline(); +} + +Mixer::Mixer(int idx) +{ + this->idx = idx; + title[0] = 0; + x = y = 100 + idx*64; + w = 400; h = 300; +} +void Mixer::reposition(int x, int y, int w, int h) +{ + this->x = x; this->y = y; + this->w = w; this->h = h; +} + +int Mixer::load(FileXML *file) +{ + int result = 0; + while( !(result = file->read_tag()) ) { + if( file->tag.title_is("/MIXER") ) break; + if( file->tag.title_is("MIX") ) { + mixer_ids.append(file->tag.get_property("ID", 0)); + } + } + return 0; +} + +void Mixer::copy_from(Mixer &that) +{ + mixer_ids.remove_all(); + strncpy(title, that.title, sizeof(title)); + title[sizeof(title)-1] = 0; + x = that.x; y = that.y; + w = that.w; h = that.h; + for( int i=0; imwindow = mwindow; + idx = -1; + edl = 0; + highlighted = 0; + title[0] = 0; + zgui = 0; +} + +ZWindow::~ZWindow() +{ + close_window(); + if( edl ) + edl->remove_user(); +} + +BC_Window* ZWindow::new_gui() +{ + Mixer *mixer = mwindow->edl->mixers.get_mixer(idx); + zgui = new ZWindowGUI(mwindow, this, mixer); + zgui->create_objects(); + return zgui; +} + +void ZWindow::handle_done_event(int result) +{ +} +void ZWindow::handle_close_event(int result) +{ + zgui = 0; +} + +void ZWindow::change_source(EDL *edl) +{ + if( this->edl && edl != this->edl ) + this->edl->remove_user(); + this->edl = edl; + if( edl != 0 ) { + zgui->playback_engine->que->send_command(CURRENT_FRAME, CHANGE_ALL, edl, 1); + } +} + +void ZWindow::issue_command(int command, int wait_tracking, + int use_inout, int update_refresh, int toggle_audio) +{ + zgui->playback_engine->issue_command(edl, command, + wait_tracking, use_inout, update_refresh, toggle_audio); +} + +void ZWindow::update_mixer_ids() +{ + if( !running() ) return; + Mixer *mixer = mwindow->edl->mixers.get_mixer(idx); + if( !mixer ) return; + mixer->mixer_ids.remove_all(); + PatchBay *patchbay = mwindow->gui->pane[0]->patchbay; + for( int i=0; ipatches.size(); ++i ) { + PatchGUI *patchgui = patchbay->patches[i]; + if( !patchgui->mixer ) continue; + int mixer_id = patchgui->track->get_mixer_id(); + if( mixer->mixer_ids.number_of(mixer_id) >= 0 ) continue; + mixer->mixer_ids.append(mixer_id); + } +} + +void ZWindow::set_title(const char *tp) +{ + char *cp = title, *ep = cp + sizeof(title)-1; + cp += snprintf(title, ep-cp, _("Mixer %d"), idx); + if( tp ) cp += snprintf(cp, ep-cp, ": %s", tp); + Mixer *mixer = mwindow->edl->mixers.get_mixer(idx); + if( mixer && tp != mixer->title ) mixer->set_title(tp); +} + +void ZWindow::reposition(int x, int y, int w, int h) +{ + Mixer *mixer = mwindow->edl->mixers.get_mixer(idx); + if( mixer ) mixer->reposition(x, y, w, h); +} + diff --git a/cinelerra-5.1/cinelerra/zwindow.h b/cinelerra-5.1/cinelerra/zwindow.h new file mode 100644 index 00000000..9b53e423 --- /dev/null +++ b/cinelerra-5.1/cinelerra/zwindow.h @@ -0,0 +1,89 @@ + +/* + * CINELERRA + * Copyright (C) 1997-2012 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ZWINDOW_H__ +#define __ZWINDOW_H__ + +#include "arraylist.h" +#include "bcdialog.h" +#include "bcwindow.h" +#include "edl.inc" +#include "filexml.inc" +#include "mwindow.inc" +#include "playbackengine.inc" +#include "renderengine.inc" +#include "zwindowgui.inc" + +class Mixer { +public: + int idx; + int x, y, w, h; + ArrayList mixer_ids; + char title[BCSTRLEN]; + + Mixer(int idx); + void save(FileXML *file); + int load(FileXML *file); + void copy_from(Mixer &that); + void set_title(const char *tp); + void reposition(int x, int y, int w, int h); +}; + +class Mixers : public ArrayList +{ +public: + Mixers(); + ~Mixers(); + Mixer *new_mixer(); + Mixer *get_mixer(int idx); + void del_mixer(int idx); + void save(FileXML *file); + int load(FileXML *file); + void copy_from(Mixers &that); +}; + + +class ZWindow : public BC_DialogThread +{ +public: + ZWindow(MWindow *mwindow); + ~ZWindow(); + + void handle_done_event(int result); + void handle_close_event(int result); + void change_source(EDL *edl); + void issue_command(int command, int wait_tracking, + int use_inout, int update_refresh, int toggle_audio); + void update_mixer_ids(); + void set_title(const char *tp); + void reposition(int x, int y, int w, int h); + + BC_Window *new_gui(); + MWindow *mwindow; + ZWindowGUI *zgui; + EDL* edl; + + int idx; + int highlighted; + char title[BCTEXTLEN]; +}; + +#endif diff --git a/cinelerra-5.1/cinelerra/zwindow.inc b/cinelerra-5.1/cinelerra/zwindow.inc new file mode 100644 index 00000000..c7061e53 --- /dev/null +++ b/cinelerra-5.1/cinelerra/zwindow.inc @@ -0,0 +1,29 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ZWINDOW_INC__ +#define __ZWINDOW_INC__ + +class Mixer; +class Mixers; +class ZWindow; + +#endif diff --git a/cinelerra-5.1/cinelerra/zwindowgui.C b/cinelerra-5.1/cinelerra/zwindowgui.C new file mode 100644 index 00000000..46208af4 --- /dev/null +++ b/cinelerra-5.1/cinelerra/zwindowgui.C @@ -0,0 +1,264 @@ + +/* + * CINELERRA + * Copyright (C) 1997-2011 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "bcwindow.h" +#include "canvas.h" +#include "edl.h" +#include "edlsession.h" +#include "keys.h" +#include "language.h" +#include "localsession.h" +#include "mainmenu.h" +#include "mainsession.h" +#include "mbuttons.h" +#include "mwindow.h" +#include "mwindowgui.h" +#include "playbackengine.h" +#include "playtransport.h" +#include "renderengine.h" +#include "theme.h" +#include "tracks.h" +#include "transportque.h" +#include "zwindow.h" +#include "zwindowgui.h" + +ZWindowGUI::ZWindowGUI(MWindow *mwindow, ZWindow *zwindow, Mixer *mixer) + : BC_Window(mixer->title, mixer->x, mixer->y, mixer->w, mixer->h, + 100, 100, 1, 1, 0) +{ + this->mwindow = mwindow; + this->zwindow = zwindow; + + canvas = 0; + playback_engine = 0; + highlighted = 0; +} + +ZWindowGUI::~ZWindowGUI() +{ + delete playback_engine; + delete canvas; +} + +void ZWindowGUI::create_objects() +{ + lock_window("ZWindowGUI::create_objects"); + + canvas = new ZWindowCanvas(mwindow, this, 10,10, get_w()-20,get_h()-20); + canvas->create_objects(mwindow->edl); + playback_engine = new PlaybackEngine(mwindow, canvas); + playback_engine->create_objects(); + + deactivate(); + show_window(); + unlock_window(); +} + +int ZWindowGUI::resize_event(int w, int h) +{ + canvas->reposition_window(0, 10,10, w-20,h-20); + zwindow->reposition(get_x(), get_y(), w, h); + BC_WindowBase::resize_event(w, h); + return 1; +} + +int ZWindowGUI::translation_event() +{ + zwindow->reposition(get_x(), get_y(), get_w(), get_h()); + return 0; +} + +int ZWindowGUI::close_event() +{ + mwindow->del_mixer(zwindow); + set_done(0); + return 1; +} + +int ZWindowGUI::keypress_event() +{ + int key = get_keypress(); + if( key == 'w' || key == 'W' ) { + close_event(); + return 1; + } + unlock_window(); + int result = 1; + switch( key ) { + case 'f': + if( mwindow->session->zwindow_fullscreen ) + canvas->stop_fullscreen(); + else + canvas->start_fullscreen(); + break; + case ESC: + if( mwindow->session->zwindow_fullscreen ) + canvas->stop_fullscreen(); + break; + default: + mwindow->gui->lock_window("ZWindowGUI::keypress_event"); + result = mwindow->gui->mbuttons->transport->do_keypress(key); + mwindow->gui->unlock_window(); + } + + lock_window("ZWindowGUI::keypress_event 1"); + return result; +} + +int ZWindowGUI::button_press_event() +{ + mwindow->select_zwindow(zwindow); + if( get_double_click() ) { + unlock_window(); + mwindow->gui->lock_window("ZWindowGUI::button_press_event 0"); + LocalSession *local_session = mwindow->edl->local_session; + double start = local_session->get_selectionstart(1); + double end = local_session->get_selectionend(1); + if( EQUIV(start, end) ) { + start = mwindow->edl->tracks->total_recordable_length(); + if( start < 0 ) start = end; + } + if( (end-start) > 1e-4 ) { + LocalSession *zlocal_session = zwindow->edl->local_session; + zlocal_session->set_selectionstart(end); + zlocal_session->set_selectionend(end); + zlocal_session->set_inpoint(start); + zlocal_session->set_outpoint(end); + double orig_inpoint = local_session->get_inpoint(); + double orig_outpoint = local_session->get_outpoint(); + local_session->set_selectionstart(end); + local_session->set_selectionend(end); + local_session->set_inpoint(start); + local_session->set_outpoint(end); + mwindow->overwrite(zwindow->edl); + local_session->set_inpoint(orig_inpoint); + local_session->set_outpoint(orig_outpoint); + mwindow->gui->update_timebar(1); + } + mwindow->gui->unlock_window(); + lock_window("ZWindowGUI::button_press_event 1"); + } + if( !canvas->get_canvas() ) return 0; + return canvas->button_press_event_base(canvas->get_canvas()); +} + +int ZWindowGUI::cursor_leave_event() +{ + if( !canvas->get_canvas() ) return 0; + return canvas->cursor_leave_event_base(canvas->get_canvas()); +} + +int ZWindowGUI::cursor_enter_event() +{ + if( !canvas->get_canvas() ) return 0; + return canvas->cursor_enter_event_base(canvas->get_canvas()); +} + +int ZWindowGUI::button_release_event() +{ + if( !canvas->get_canvas() ) return 0; + return canvas->button_release_event(); +} + +int ZWindowGUI::cursor_motion_event() +{ + BC_WindowBase *cvs = canvas->get_canvas(); + if( !cvs ) return 0; + cvs->unhide_cursor(); + return canvas->cursor_motion_event(); +} + +int ZWindowGUI::draw_overlays() +{ + BC_WindowBase *cvs = canvas->get_canvas(); + if( !cvs || cvs->get_video_on() ) return 0; + if( highlighted != zwindow->highlighted ) { + highlighted = zwindow->highlighted; + cvs->set_color(WHITE); + cvs->set_inverse(); + cvs->draw_rectangle(0, 0, cvs->get_w(), cvs->get_h()); + cvs->draw_rectangle(1, 1, cvs->get_w() - 2, cvs->get_h() - 2); + cvs->set_opaque(); + } + return 1; +} + +ZWindowCanvas::ZWindowCanvas(MWindow *mwindow, ZWindowGUI *gui, + int x, int y, int w, int h) + : Canvas(mwindow, gui, x,y, w,h, 0,0,0) +{ + this->mwindow = mwindow; + this->gui = gui; +} + +void ZWindowCanvas::close_source() +{ + gui->unlock_window(); + gui->zwindow->zgui->playback_engine->interrupt_playback(1); + gui->lock_window("ZWindowCanvas::close_source"); + EDL *edl = gui->zwindow->edl; + if( edl ) { + gui->zwindow->edl = 0; + edl->remove_user(); + } +} + + +void ZWindowCanvas::draw_refresh(int flush) +{ + EDL *edl = gui->zwindow->edl; + BC_WindowBase *cvs = get_canvas(); + int dirty = 0; + + if( !cvs->get_video_on() ) { + cvs->clear_box(0, 0, cvs->get_w(), cvs->get_h()); + gui->highlighted = 0; + dirty = 1; + } + if( !cvs->get_video_on() && refresh_frame && edl ) { + float in_x1, in_y1, in_x2, in_y2; + float out_x1, out_y1, out_x2, out_y2; + get_transfers(edl, + in_x1, in_y1, in_x2, in_y2, + out_x1, out_y1, out_x2, out_y2); + cvs->draw_vframe(refresh_frame, + (int)out_x1, (int)out_y1, (int)(out_x2 - out_x1), (int)(out_y2 - out_y1), + (int)in_x1, (int)in_y1, (int)(in_x2 - in_x1), (int)(in_y2 - in_y1), 0); + dirty = 1; + } + + if( gui->draw_overlays() ) + dirty = 1; + + if( dirty ) + cvs->flash(flush); +} + +int ZWindowCanvas::get_fullscreen() +{ + return mwindow->session->zwindow_fullscreen; +} + +void ZWindowCanvas::set_fullscreen(int value) +{ + mwindow->session->zwindow_fullscreen = value; +} + diff --git a/cinelerra-5.1/cinelerra/zwindowgui.h b/cinelerra-5.1/cinelerra/zwindowgui.h new file mode 100644 index 00000000..ab658a91 --- /dev/null +++ b/cinelerra-5.1/cinelerra/zwindowgui.h @@ -0,0 +1,77 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ZWINDOWGUI_H__ +#define __ZWINDOWGUI_H__ + +#include "bcwindow.h" +#include "canvas.h" +#include "mwindow.h" +#include "renderengine.inc" + +class ZWindowGUI; +class ZWindowCanvas; + +class ZWindowGUI : public BC_Window +{ +public: + ZWindowGUI(MWindow *mwindow, ZWindow *vwindow, Mixer *mixer); + ~ZWindowGUI(); + + void create_objects(); + int resize_event(int w, int h); + int translation_event(); + int close_event(); + int keypress_event(); + int button_press_event(); + int cursor_leave_event(); + int cursor_enter_event(); + int button_release_event(); + int cursor_motion_event(); + int select_window(int n); + int draw_overlays(); + + MWindow *mwindow; + ZWindow *zwindow; + ZWindowCanvas *canvas; + + TransportCommand *command; + PlaybackEngine *playback_engine; + RenderEngine *render_engine; + int highlighted; +}; + +class ZWindowCanvas : public Canvas +{ +public: + ZWindowCanvas(MWindow *mwindow, ZWindowGUI *gui, + int x, int y, int w, int h); + + void draw_refresh(int flush = 1); + void close_source(); + int get_fullscreen(); + void set_fullscreen(int value); + + MWindow *mwindow; + ZWindowGUI *gui; +}; + +#endif diff --git a/cinelerra-5.1/cinelerra/zwindowgui.inc b/cinelerra-5.1/cinelerra/zwindowgui.inc new file mode 100644 index 00000000..1fcb5d0c --- /dev/null +++ b/cinelerra-5.1/cinelerra/zwindowgui.inc @@ -0,0 +1,27 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ZWINDOWGUI_INC__ +#define __ZWINDOWGUI_INC__ + +class ZWindowGUI; + +#endif diff --git a/cinelerra-5.1/guicast/bcwindowbase.C b/cinelerra-5.1/guicast/bcwindowbase.C index d8c60421..54a14796 100644 --- a/cinelerra-5.1/guicast/bcwindowbase.C +++ b/cinelerra-5.1/guicast/bcwindowbase.C @@ -431,7 +431,7 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window, const char *title else this->display_name[0] = 0; - put_title(_(title)); + put_title(title); if(bg_pixmap) shared_bg_pixmap = 1; subwindows = new BC_SubWindowList; @@ -4148,7 +4148,7 @@ void BC_WindowBase::put_title(const char *text) void BC_WindowBase::set_title(const char *text, int utf8) { // utf8>0: wm + net_wm, utf8=0: wm only, utf<0: net_wm only - put_title(_(text)); + put_title(text); const unsigned char *wm_title = (const unsigned char *)title; int title_len = strlen((const char *)title); if( utf8 >= 0 ) { diff --git a/cinelerra-5.1/picon/cinfinity/mixpatch.png b/cinelerra-5.1/picon/cinfinity/mixpatch.png new file mode 100644 index 00000000..b5067efe Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/mixpatch.png differ diff --git a/cinelerra-5.1/picon/cinfinity/mixpatch_checked.png b/cinelerra-5.1/picon/cinfinity/mixpatch_checked.png new file mode 100644 index 00000000..a71c5ce0 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/mixpatch_checked.png differ diff --git a/cinelerra-5.1/picon/cinfinity/mixpatch_checkedhi.png b/cinelerra-5.1/picon/cinfinity/mixpatch_checkedhi.png new file mode 100644 index 00000000..16b14a6a Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/mixpatch_checkedhi.png differ diff --git a/cinelerra-5.1/picon/cinfinity/mixpatch_dn.png b/cinelerra-5.1/picon/cinfinity/mixpatch_dn.png new file mode 100644 index 00000000..215bd1b8 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/mixpatch_dn.png differ diff --git a/cinelerra-5.1/picon/cinfinity/mixpatch_hi.png b/cinelerra-5.1/picon/cinfinity/mixpatch_hi.png new file mode 100644 index 00000000..4d8c09b2 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/mixpatch_hi.png differ diff --git a/cinelerra-5.1/picon/cinfinity/mixpatch_up.png b/cinelerra-5.1/picon/cinfinity/mixpatch_up.png new file mode 100644 index 00000000..6a1de5e7 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/mixpatch_up.png differ