upgrade libvpx+lv2, fix dbl tap play bug, add multi nest/unnest clips, add del top...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / mainmenu.C
index a94fb5894819aa649def542713bb147a18b5bc3f..bc12bed7d7e7ca95f9c4f3bf9a265892eb91c70a 100644 (file)
@@ -36,6 +36,7 @@
 #include "dvdcreate.h"
 #include "edl.h"
 #include "edlsession.h"
+#include "file.h"
 #include "filesystem.h"
 #include "filexml.h"
 #include "floatauto.h"
@@ -54,6 +55,7 @@
 #include "menueditlength.h"
 #include "menutransitionlength.h"
 #include "menuveffects.h"
+#include "mixersalign.h"
 #include "mwindowgui.h"
 #include "mwindow.h"
 #include "new.h"
@@ -133,8 +135,8 @@ void MainMenu::create_objects()
        filemenu->add_item(new BC_MenuItem("-"));
        filemenu->add_item(quit_program = new Quit(mwindow));
        quit_program->create_objects(save);
-       filemenu->add_item(new DumpEDL(mwindow));
-       filemenu->add_item(new DumpPlugins(mwindow));
+       filemenu->add_item(dump_menu = new MainDumpsMenu(mwindow));
+       dump_menu->create_objects();
        filemenu->add_item(new LoadBackup(mwindow));
        filemenu->add_item(new SaveBackup(mwindow));
 
@@ -201,7 +203,8 @@ void MainMenu::create_objects()
        trackmenu->add_item(new MoveTracksUp(mwindow));
        trackmenu->add_item(new MoveTracksDown(mwindow));
        trackmenu->add_item(new DeleteTracks(mwindow));
-       trackmenu->add_item(new DeleteTrack(mwindow));
+       trackmenu->add_item(new DeleteFirstTrack(mwindow));
+       trackmenu->add_item(new DeleteLastTrack(mwindow));
        trackmenu->add_item(new ConcatenateTracks(mwindow));
        AppendTracks *append_tracks;
        trackmenu->add_item(append_tracks = new AppendTracks(mwindow));
@@ -216,10 +219,10 @@ void MainMenu::create_objects()
        settingsmenu->add_item(proxy = new ProxyMenuItem(mwindow));
        proxy->create_objects();
        mwindow->preferences_thread = preferences->thread;
+       settingsmenu->add_item(cursor_on_frames = new CursorOnFrames(mwindow));
        settingsmenu->add_item(labels_follow_edits = new LabelsFollowEdits(mwindow));
        settingsmenu->add_item(plugins_follow_edits = new PluginsFollowEdits(mwindow));
        settingsmenu->add_item(keyframes_follow_edits = new KeyframesFollowEdits(mwindow));
-       settingsmenu->add_item(cursor_on_frames = new CursorOnFrames(mwindow));
        settingsmenu->add_item(typeless_keyframes = new TypelessKeyframes(mwindow));
        settingsmenu->add_item(new BC_MenuItem("-"));
        settingsmenu->add_item(new SaveSettingsNow(mwindow));
@@ -248,11 +251,11 @@ void MainMenu::create_objects()
        viewmenu->add_item(mask_automation = new ShowAutomation(mwindow, _("Mask"), "8", AUTOMATION_MASK));
        viewmenu->add_item(speed_automation = new ShowAutomation(mwindow, _("Speed"), "9", AUTOMATION_SPEED));
 
-       camera_x = new ShowAutomation(mwindow, _("Camera X"), "Ctl-Shift-X", AUTOMATION_CAMERA_X);
+       camera_x = new ShowAutomation(mwindow, _("Camera X"), "Ctrl-Shift-X", AUTOMATION_CAMERA_X);
        camera_x->set_ctrl();  camera_x->set_shift();   viewmenu->add_item(camera_x);
-       camera_y = new ShowAutomation(mwindow, _("Camera Y"), "Ctl-Shift-Y", AUTOMATION_CAMERA_Y);
+       camera_y = new ShowAutomation(mwindow, _("Camera Y"), "Ctrl-Shift-Y", AUTOMATION_CAMERA_Y);
        camera_y->set_ctrl();  camera_y->set_shift();   viewmenu->add_item(camera_y);
-       camera_z = new ShowAutomation(mwindow, _("Camera Z"), "Ctl-Shift-Z", AUTOMATION_CAMERA_Z);
+       camera_z = new ShowAutomation(mwindow, _("Camera Z"), "Ctrl-Shift-Z", AUTOMATION_CAMERA_Z);
        camera_z->set_ctrl();  camera_z->set_shift();  viewmenu->add_item(camera_z);
        project_x = new ShowAutomation(mwindow, _("Projector X"), "Alt-Shift-X", AUTOMATION_PROJECTOR_X);
        project_x->set_alt();  project_x->set_shift();  viewmenu->add_item(project_x);
@@ -270,11 +273,17 @@ 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 TileMixers(mwindow));
-       windowmenu->add_item(new TileWindows(mwindow,_("Default positions"),-1,_("Ctrl-P"),'p'));
+       windowmenu->add_item(mixer_items = new MixerItems(mwindow));
+       mixer_items->create_objects();
        windowmenu->add_item(new TileWindows(mwindow,_("Tile left"),0));
        windowmenu->add_item(new TileWindows(mwindow,_("Tile right"),1));
+       windowmenu->add_item(new BC_MenuItem("-"));
+
+       windowmenu->add_item(new TileWindows(mwindow,_("Default positions"),-1,_("Ctrl-P"),'p'));
+       windowmenu->add_item(load_layout = new LoadLayout(mwindow, _("Load layout..."),LAYOUT_LOAD));
+       load_layout->create_objects();
+       windowmenu->add_item(save_layout = new LoadLayout(mwindow, _("Save layout..."),LAYOUT_SAVE));
+       save_layout->create_objects();
 }
 
 int MainMenu::load_defaults(BC_Hash *defaults)
@@ -578,6 +587,36 @@ int MainMenu::add_load(char *path)
 
 // ================================== menu items
 
+MainDumpsSubMenu::MainDumpsSubMenu(BC_MenuItem *menu_item)
+ : BC_SubMenu()
+{
+       this->menu_item = menu_item;
+}
+MainDumpsSubMenu::~MainDumpsSubMenu()
+{
+}
+
+
+MainDumpsMenu::MainDumpsMenu(MWindow *mwindow)
+ : BC_MenuItem(_("Dumps..."))
+{
+       this->mwindow = mwindow;
+       this->dumps_menu = 0;
+}
+MainDumpsMenu::~MainDumpsMenu()
+{
+}
+
+void MainDumpsMenu::create_objects()
+{
+       add_submenu(dumps_menu = new MainDumpsSubMenu(this));
+//     dumps_menu->add_item(new DumpCICache(mwindow));
+       dumps_menu->add_item(new DumpEDL(mwindow));
+       dumps_menu->add_item(new DumpPlugins(mwindow));
+       dumps_menu->add_item(new DumpAssets(mwindow));
+       dumps_menu->add_item(new DumpUndo(mwindow));
+};
+
 
 DumpCICache::DumpCICache(MWindow *mwindow)
  : BC_MenuItem(_("Dump CICache"))
@@ -597,9 +636,7 @@ DumpEDL::DumpEDL(MWindow *mwindow)
 
 int DumpEDL::handle_event()
 {
-//printf("DumpEDL::handle_event 1\n");
        mwindow->dump_edl();
-//printf("DumpEDL::handle_event 2\n");
        return 1;
 }
 
@@ -611,20 +648,29 @@ DumpPlugins::DumpPlugins(MWindow *mwindow)
 
 int DumpPlugins::handle_event()
 {
-//printf("DumpEDL::handle_event 1\n");
        mwindow->dump_plugins();
-//printf("DumpEDL::handle_event 2\n");
        return 1;
 }
 
-
 DumpAssets::DumpAssets(MWindow *mwindow)
  : BC_MenuItem(_("Dump Assets"))
 { this->mwindow = mwindow; }
 
 int DumpAssets::handle_event()
 {
-       mwindow->assets->dump();
+       mwindow->edl->assets->dump();
+       return 1;
+}
+
+DumpUndo::DumpUndo(MWindow *mwindow)
+ : BC_MenuItem(_("Dump Undo"))
+{
+       this->mwindow = mwindow;
+}
+
+int DumpUndo::handle_event()
+{
+       mwindow->dump_undo();
        return 1;
 }
 
@@ -1176,23 +1222,42 @@ int DeleteTracks::handle_event()
        return 1;
 }
 
-DeleteTrack::DeleteTrack(MWindow *mwindow)
+DeleteFirstTrack::DeleteFirstTrack(MWindow *mwindow)
+ : BC_MenuItem(_("Delete first track"), "Shift-D", 'D')
+{
+       set_shift(1);
+       this->mwindow = mwindow;
+}
+
+int DeleteFirstTrack::handle_event()
+{
+       if( mwindow->session->current_operation == NO_OPERATION ) {
+               Track *track = mwindow->edl->tracks->first;
+               if( track ) mwindow->delete_track(track);
+       }
+       return 1;
+}
+
+DeleteLastTrack::DeleteLastTrack(MWindow *mwindow)
  : BC_MenuItem(_("Delete last track"), "d", 'd')
 {
        this->mwindow = mwindow;
 }
 
-int DeleteTrack::handle_event()
+int DeleteLastTrack::handle_event()
 {
-       if( mwindow->session->current_operation == NO_OPERATION )
-               mwindow->delete_track();
+       if( mwindow->session->current_operation == NO_OPERATION ) {
+               Track *track = mwindow->edl->tracks->last;
+               if( track ) mwindow->delete_track(track);
+       }
        return 1;
 }
 
 MoveTracksUp::MoveTracksUp(MWindow *mwindow)
  : BC_MenuItem(_("Move tracks up"), _("Shift-Up"), UP)
 {
-       set_shift(); this->mwindow = mwindow;
+       this->mwindow = mwindow;
+       set_shift();
 }
 
 int MoveTracksUp::handle_event()
@@ -1353,10 +1418,11 @@ int KeyframesFollowEdits::handle_event()
 
 
 CursorOnFrames::CursorOnFrames(MWindow *mwindow)
- : BC_MenuItem(_("Align cursor on frames"))
+ : BC_MenuItem(_("Align cursor on frames"),_("Ctrl-a"),'a')
 {
        this->mwindow = mwindow;
        set_checked(mwindow->edl->session->cursor_on_frames);
+       set_ctrl(1);
 }
 
 int CursorOnFrames::handle_event()
@@ -1382,7 +1448,8 @@ int TypelessKeyframes::handle_event()
 }
 
 
-ScrubSpeed::ScrubSpeed(MWindow *mwindow) : BC_MenuItem(_("Slow Shuttle"))
+ScrubSpeed::ScrubSpeed(MWindow *mwindow)
+ : BC_MenuItem(_("Slow Shuttle"))
 {
        this->mwindow = mwindow;
 }
@@ -1402,9 +1469,11 @@ int ScrubSpeed::handle_event()
        return 1;
 }
 
-SaveSettingsNow::SaveSettingsNow(MWindow *mwindow) : BC_MenuItem(_("Save settings now"))
+SaveSettingsNow::SaveSettingsNow(MWindow *mwindow)
+ : BC_MenuItem(_("Save settings now"),_("Ctrl-s"),'s')
 {
        this->mwindow = mwindow;
+       set_ctrl(1);
 }
 
 int SaveSettingsNow::handle_event()
@@ -1542,6 +1611,21 @@ int SplitY::handle_event()
 }
 
 
+MixerItems::MixerItems(MWindow *mwindow)
+ : BC_MenuItem(_("Mixers..."))
+{
+       this->mwindow = mwindow;
+}
+
+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));
+}
+
 MixerViewer::MixerViewer(MWindow *mwindow)
  : BC_MenuItem(_("Mixer Viewer"), _("Shift-M"), 'M')
 {
@@ -1568,3 +1652,237 @@ int TileMixers::handle_event()
        return 1;
 }
 
+AlignMixers::AlignMixers(MWindow *mwindow)
+ : BC_MenuItem(_("Align mixers"))
+{
+       this->mwindow = mwindow;
+}
+
+int AlignMixers::handle_event()
+{
+       int wx, wy;
+       mwindow->gui->get_abs_cursor(wx, wy);
+       mwindow->mixers_align->start_dialog(wx, wy);
+       return 1;
+}
+
+
+LoadLayoutItem::LoadLayoutItem(LoadLayout *load_layout, const char *text, int idx, int hotkey)
+ : BC_MenuItem(text, "", hotkey)
+{
+       this->idx = idx;
+       this->load_layout = load_layout;
+       if( hotkey ) {
+               char hot_txt[BCSTRLEN];
+               sprintf(hot_txt, _("Ctrl-Shift+F%d"), hotkey-KEY_F1+1);
+               set_ctrl();  set_shift();
+               set_hotkey_text(hot_txt);
+       }
+}
+
+
+int LoadLayoutItem::handle_event()
+{
+// key_press hotkey skips over activate_submenu
+       load_layout->update();
+       MWindow *mwindow = load_layout->mwindow;
+       switch( load_layout->action ) {
+       case LAYOUT_LOAD:
+               mwindow->load_layout(layout_file);
+               break;
+       case LAYOUT_SAVE: {
+               int wx = 0, wy = 0;
+               mwindow->gui->get_abs_cursor(wx, wy);
+               load_layout->layout_dialog->start_confirm_dialog(wx, wy, idx);
+               break; }
+       }
+       return 1;
+}
+
+LoadLayout::LoadLayout(MWindow *mwindow, const char *text, int action)
+ : BC_MenuItem(text)
+{
+       this->mwindow = mwindow;
+       this->action = action;
+       this->layout_dialog = new LoadLayoutDialog(this);
+}
+
+LoadLayout::~LoadLayout()
+{
+       delete layout_dialog;
+}
+
+void LoadLayout::create_objects()
+{
+       BC_SubMenu *layout_submenu = new BC_SubMenu();
+       add_submenu(layout_submenu);
+
+       for( int i=0; i<LAYOUTS_MAX; ++i ) {
+               char text[BCSTRLEN];
+               sprintf(text, _("Layout %d"), i+1);
+               LoadLayoutItem *item = new LoadLayoutItem(this, text, i,
+                               action==LAYOUT_LOAD ? KEY_F1+i : 0);
+               layout_submenu->add_submenuitem(item);
+       }
+}
+
+int LoadLayout::activate_submenu()
+{
+       update();
+       return BC_MenuItem::activate_submenu();
+}
+
+void LoadLayout::update()
+{
+       FileSystem fs;
+       fs.set_filter("layout*_rc");
+       int ret = fs.update(File::get_config_path());
+       int sz = !ret ? fs.dir_list.size() : 0;
+       BC_SubMenu *layout_submenu = get_submenu();
+
+       for( int i=0; i<LAYOUTS_MAX; ++i ) {
+               LoadLayoutItem* item = (LoadLayoutItem *)
+                       layout_submenu->get_item(i);
+               char layout_text[BCSTRLEN];  layout_text[0] = 0;
+               int n = sz, id = i+1;
+               while( --n >= 0 ) {
+                       char *np = fs.dir_list[n]->name;
+                       char *cp = strrchr(np, '_'), *bp = 0;
+                       int no = strtol(np+6, &bp, 10);
+                       if( no != id || !bp ) continue;
+                       if( bp == cp ) {  n = -1;  break; }
+                       if( *bp++ == '_' && bp < cp && !strcmp(cp, "_rc") ) {
+                               int k = cp - bp;  char *tp = layout_text;
+                               if( k > LAYOUT_NAME_LEN ) k = LAYOUT_NAME_LEN;
+                               while( --k >= 0 ) *tp++ = *bp++;
+                               *tp = 0;
+                               break;
+                       }
+               }
+               strcpy(item->layout_text, layout_text);
+               char *lp = item->layout_file;
+               int k = sprintf(lp, LAYOUT_FILE, id);
+               if( n >= 0 && layout_text[0] )
+                       sprintf(lp + k-2, "%s_rc", layout_text);
+               else
+                       sprintf(layout_text, _("Layout %d"), id);
+               item->set_text(layout_text);
+       }
+}
+
+LoadLayoutDialog::LoadLayoutDialog(LoadLayout *load_layout)
+{
+       this->load_layout = load_layout;
+       wx = 0;  wy = 0;
+       idx = -1;
+       lgui = 0;
+}
+
+LoadLayoutDialog::~LoadLayoutDialog()
+{
+       close_window();
+}
+
+void LoadLayoutDialog::handle_done_event(int result)
+{
+       if( result ) return;
+       char layout_file[BCSTRLEN];
+       BC_SubMenu *layout_submenu = load_layout->get_submenu();
+       LoadLayoutItem* item =
+               (LoadLayoutItem *) layout_submenu->get_item(idx);
+       snprintf(layout_file, sizeof(layout_file), "%s", item->layout_file);
+       load_layout->mwindow->delete_layout(layout_file);
+       int k = sprintf(layout_file, LAYOUT_FILE, idx+1);
+       const char *text = lgui->name_text->get_text();
+       if( text[0] )
+               snprintf(layout_file + k-2, sizeof(layout_file)-k+2, "%s_rc", text);
+       load_layout->mwindow->save_layout(layout_file);
+}
+
+void LoadLayoutDialog::handle_close_event(int result)
+{
+       lgui = 0;
+}
+
+BC_Window *LoadLayoutDialog::new_gui()
+{
+       lgui = new LoadLayoutConfirm(this, wx, wy);
+       lgui->create_objects();
+       return lgui;
+}
+
+void LoadLayoutDialog::start_confirm_dialog(int wx, int wy, int idx)
+{
+       close_window();
+       this->wx = wx;  this->wy = wy;
+       this->idx = idx;
+       start();
+}
+
+LoadLayoutNameText::LoadLayoutNameText(LoadLayoutConfirm *confirm,
+               int x, int y, int w, const char *text)
+ : BC_TextBox(x, y, w, 1, text)
+{
+       this->confirm = confirm;
+}
+
+LoadLayoutNameText::~LoadLayoutNameText()
+{
+}
+
+int LoadLayoutNameText::handle_event()
+{
+       const char *text = get_text();
+       int len = strlen(text), k = 0;
+       char new_text[BCTEXTLEN];
+       for( int i=0; i<len; ++i ) {
+               int ch = text[i];
+               if( (ch>='A' && ch<='Z') || (ch>='a' && ch<='z') ||
+                   (ch>='0' && ch<='9') || ch=='_' )
+                       new_text[k++] = ch;
+       }
+       new_text[k] = 0;  len = k;
+       int i = len - LAYOUT_NAME_LEN;
+       if( i >= 0 ) {
+               k = 0;
+               while( i < len ) new_text[k++] = new_text[i++];
+               new_text[k] = 0;
+       }
+       update(new_text);
+       return 1;
+}
+
+LoadLayoutConfirm::LoadLayoutConfirm(LoadLayoutDialog *layout_dialog, int x, int y)
+ : BC_Window(_(PROGRAM_NAME ": Layout"), x, y, 300,140, 300,140, 0)
+{
+       this->layout_dialog = layout_dialog;
+}
+
+LoadLayoutConfirm::~LoadLayoutConfirm()
+{
+}
+
+void LoadLayoutConfirm::create_objects()
+{
+       lock_window("LoadLayoutConfirm::create_objects");
+       int x = 10, y = 10, pad = 10;
+       BC_SubMenu *layout_submenu = layout_dialog->load_layout->get_submenu();
+       LoadLayoutItem *item = (LoadLayoutItem *)
+               layout_submenu->get_item(layout_dialog->idx);
+       BC_Title *title;
+       add_subwindow(title = new BC_Title(x, y, _("Layout Name:")));
+       int x1 = x + title->get_w() + 10;
+       add_subwindow(title = new BC_Title(x1, y, item->get_text()));
+       y += title->get_h() + pad;
+       add_subwindow(name_text = new LoadLayoutNameText(this,
+               x, y, get_w()-x-20, item->layout_text));
+       y += name_text->get_h();
+       x1 = x + 80;
+       char legend[BCTEXTLEN];
+       sprintf(legend, _("a-z,A-Z,0-9_ only, %dch max"), LAYOUT_NAME_LEN);
+       add_subwindow(title = new BC_Title(x1, y, legend));
+       add_subwindow(new BC_OKButton(this));
+       add_subwindow(new BC_CancelButton(this));
+       unlock_window();
+}
+