Add GUI to instantiate session-scripts
[ardour.git] / gtk2_ardour / ardour_ui_ed.cc
index a0836f41d71da717b6009db4f5e08b1d08f187cd..03ad92e183d1cef619e3f0debbbd69b927fda5df 100644 (file)
@@ -51,6 +51,7 @@
 #include "editor.h"
 #include "actions.h"
 #include "meterbridge.h"
+#include "luawindow.h"
 #include "mixer_ui.h"
 #include "startup.h"
 #include "window_manager.h"
@@ -88,7 +89,21 @@ ARDOUR_UI::create_editor ()
                return -1;
        }
 
-        editor->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), editor));
+       // editor->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), editor));
+
+       return 0;
+}
+
+int
+ARDOUR_UI::create_luawindow ()
+
+{
+       try {
+               luawindow = LuaWindow::instance ();
+       }
+       catch (failed_constructor& err) {
+               return -1;
+       }
 
        return 0;
 }
@@ -113,7 +128,7 @@ ARDOUR_UI::install_actions ()
        global_actions.register_action (main_menu_actions, X_("PrefsMenu"), _("Preferences"));
        global_actions.register_action (main_menu_actions, X_("DetachMenu"), _("Detach"));
        global_actions.register_action (main_menu_actions, X_("Help"), _("Help"));
-       global_actions.register_action (main_menu_actions, X_("KeyMouseActions"), _("Misc. Shortcuts"));
+       global_actions.register_action (main_menu_actions, X_("KeyMouseActions"), _("Misc. Shortcuts"));
        global_actions.register_action (main_menu_actions, X_("AudioFileFormat"), _("Audio File Format"));
        global_actions.register_action (main_menu_actions, X_("AudioFileFormatHeader"), _("File Type"));
        global_actions.register_action (main_menu_actions, X_("AudioFileFormatData"), _("Sample Format"));
@@ -138,16 +153,27 @@ ARDOUR_UI::install_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::write_sensitive_actions.push_back (act);
 
-       act = Actions.register_action (main_actions, X_("duplicate-routes"), _("Duplicate Tracks/Busses..."),
+       act = global_actions.register_action (main_actions, X_("duplicate-routes"), _("Duplicate Tracks/Busses..."),
                                              sigc::mem_fun(*this, &ARDOUR_UI::start_duplicate_routes));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::write_sensitive_actions.push_back (act);
        ActionManager::track_selection_sensitive_actions.push_back (act);
 
-       act = Actions.register_action (main_actions, X_("cancel-solo"), _("Cancel Solo"), sigc::mem_fun(*this, &ARDOUR_UI::cancel_solo));
+       act = global_actions.register_action (main_actions, X_("cancel-solo"), _("Cancel Solo"), sigc::mem_fun(*this, &ARDOUR_UI::cancel_solo));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::write_sensitive_actions.push_back (act);
 
+       act = global_actions.register_action (main_actions, X_("Scripting"), S_("Session|Scripting"));
+       ActionManager::session_sensitive_actions.push_back (act);
+
+       act = global_actions.register_action (main_actions, X_("AddLuaScript"), _("Add Lua Script"),
+                     sigc::mem_fun (*this, &ARDOUR_UI::add_lua_script));
+       ActionManager::session_sensitive_actions.push_back (act);
+
+       act = global_actions.register_action (main_actions, X_("RemoveLuaScript"), _("Remove Lua Script"),
+                     sigc::mem_fun (*this, &ARDOUR_UI::remove_lua_script));
+       ActionManager::session_sensitive_actions.push_back (act);
+
        act = global_actions.register_action (main_actions, X_("OpenVideo"), _("Open Video"),
                                              sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::add_video), (Gtk::Window*) 0));
        ActionManager::session_sensitive_actions.push_back (act);
@@ -166,11 +192,11 @@ ARDOUR_UI::install_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::write_sensitive_actions.push_back (act);
 
-       act = global_actions::register_action (main_actions, X_("QuickSnapshotStay"), _("Quick Snapshot(& keep working on current version) ..."), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::quick_snapshot_session), false));
+       act = global_actions.register_action (main_actions, X_("QuickSnapshotStay"), _("Quick Snapshot(& keep working on current version) ..."), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::quick_snapshot_session), false));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::write_sensitive_actions.push_back (act);
 
-       act = global_actions::register_action (main_actions, X_("QuickSnapshotSwitch"), _("Quick Snapshot (& switch to new version) ..."), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::quick_snapshot_session), true));
+       act = global_actions.register_action (main_actions, X_("QuickSnapshotSwitch"), _("Quick Snapshot (& switch to new version) ..."), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::quick_snapshot_session), true));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::write_sensitive_actions.push_back (act);
 
@@ -225,6 +251,7 @@ ARDOUR_UI::install_actions ()
        global_actions.register_action (common_actions, X_("show-editor"), _("Show"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::show_tabbable), editor));
        global_actions.register_action (common_actions, X_("show-mixer"), _("Show"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::show_tabbable), mixer));
        global_actions.register_action (common_actions, X_("show-preferences"), _("Show"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::show_tabbable), rc_option_editor));
+       global_actions.register_action (common_actions, X_("menu-show-preferences"), _("Preferences"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::show_tabbable), rc_option_editor));
 
        global_actions.register_action (common_actions, X_("hide-editor"), _("Hide"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::hide_tabbable), editor));
        global_actions.register_action (common_actions, X_("hide-mixer"), _("Hide"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::hide_tabbable), mixer));
@@ -238,21 +265,41 @@ ARDOUR_UI::install_actions ()
        global_actions.register_action (common_actions, X_("detach-mixer"), _("Detach"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::detach_tabbable), mixer));
        global_actions.register_action (common_actions, X_("detach-preferences"), _("Detach"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::detach_tabbable), rc_option_editor));
 
+       /* These "change" actions are not intended to be used inside menus, but
+          are for the tab/window control buttons, which have somewhat odd
+          semantics.
+       */
+       global_actions.register_action (common_actions, X_("change-editor-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::button_change_tabbable_visibility), editor));
+       global_actions.register_action (common_actions, X_("change-mixer-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::button_change_tabbable_visibility), mixer));
+       global_actions.register_action (common_actions, X_("change-preferences-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::button_change_tabbable_visibility), rc_option_editor));
+
+       /* These "change" actions are not intended to be used inside menus, but
+          are for the tab/window control key bindings, which have somewhat odd
+          semantics.
+       */
+       global_actions.register_action (common_actions, X_("key-change-editor-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_change_tabbable_visibility), editor));
+       global_actions.register_action (common_actions, X_("key-change-mixer-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_change_tabbable_visibility), mixer));
+       global_actions.register_action (common_actions, X_("key-change-preferences-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_change_tabbable_visibility), rc_option_editor));
+
+       global_actions.register_action (common_actions, X_("toggle-editor-and-mixer"), _("Toggle Editor & Mixer"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_editor_and_mixer));
+
        /* windows visibility actions */
 
        global_actions.register_toggle_action (common_actions, X_("ToggleMaximalEditor"), _("Maximise Editor Space"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_editing_space));
        global_actions.register_toggle_action (common_actions, X_("ToggleMaximalMixer"), _("Maximise Mixer Space"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_mixer_space));
        ActionManager::session_sensitive_actions.push_back (act);
 
-       act = ActionManager::register_toggle_action (common_actions, X_("ToggleMixerList"), _("Toggle Mixer List"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_mixer_list));
+       act = global_actions.register_toggle_action (common_actions, X_("ToggleMixerList"), _("Toggle Mixer List"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_mixer_list));
        ActionManager::session_sensitive_actions.push_back (act);
 
-       act = ActionManager::register_toggle_action (common_actions, X_("ToggleMonitorSection"), _("Toggle Monitor Section Visibility"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_monitor_section_visibility));
+       act = global_actions.register_toggle_action (common_actions, X_("ToggleMonitorSection"), _("Toggle Monitor Section Visibility"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_monitor_section_visibility));
        act->set_sensitive (false);
 
-if (Profile->get_mixbus())
-       global_actions.register_action (common_actions, X_("show-ui-prefs"), _("Show more UI preferences"), sigc::mem_fun (*this, &ARDOUR_UI::show_ui_prefs));
+       if (Profile->get_mixbus()) {
+               global_actions.register_action (common_actions, X_("show-ui-prefs"), _("Show more UI preferences"), sigc::mem_fun (*this, &ARDOUR_UI::show_ui_prefs));
+       }
 
+       global_actions.register_action (common_actions, X_("toggle-luawindow"), S_("Window|Scripting"),  sigc::mem_fun(*this, &ARDOUR_UI::toggle_luawindow));
        global_actions.register_action (common_actions, X_("toggle-meterbridge"), S_("Window|Meterbridge"),  sigc::mem_fun(*this, &ARDOUR_UI::toggle_meterbridge));
 
        act = global_actions.register_action (common_actions, X_("NewMIDITracer"), _("MIDI Tracer"), sigc::mem_fun(*this, &ARDOUR_UI::new_midi_tracer_window));
@@ -499,6 +546,16 @@ if (Profile->get_mixbus())
        global_actions.register_action (midi_actions, X_("panic"), _("Panic"), sigc::mem_fun(*this, &ARDOUR_UI::midi_panic));
 }
 
+static
+bool drag_failed (const Glib::RefPtr<Gdk::DragContext>& context, DragResult result, Tabbable* tab)
+{
+       if (result == Gtk::DRAG_RESULT_NO_TARGET) {
+               tab->detach ();
+               return true;
+       }
+       return false;
+}
+
 void
 ARDOUR_UI::build_menu_bar ()
 {
@@ -538,15 +595,52 @@ ARDOUR_UI::build_menu_bar ()
        format_label.set_use_markup ();
 
 #ifndef TOP_MENUBAR
-       menu_hbox.pack_start (*menu_bar, false, false);
+       menu_hbox.pack_start (*menu_bar, false, false);
 #else
        use_menubar_as_top_menubar ();
 #endif
 
+       Gtk::HBox*   window_button_box = manage (new Gtk::HBox);
+
+       editor_visibility_button.signal_drag_failed().connect (sigc::bind (sigc::ptr_fun (drag_failed), editor));
+       mixer_visibility_button.signal_drag_failed().connect (sigc::bind (sigc::ptr_fun (drag_failed), mixer));
+       prefs_visibility_button.signal_drag_failed().connect (sigc::bind (sigc::ptr_fun (drag_failed), rc_option_editor));
+
+       /* catch context clicks so that we can show a menu on these buttons */
+
+       editor_visibility_button.signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_visibility_button_press), X_("editor")), false);
+       mixer_visibility_button.signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_visibility_button_press), X_("mixer")), false);
+       prefs_visibility_button.signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_visibility_button_press), X_("preferences")), false);
+
+       editor_visibility_button.set_related_action (ActionManager::get_action (X_("Common"), X_("change-editor-visibility")));
+       editor_visibility_button.set_name (X_("page switch button"));
+       mixer_visibility_button.set_related_action (ActionManager::get_action (X_("Common"), X_("change-mixer-visibility")));
+       mixer_visibility_button.set_name (X_("page switch button"));
+       prefs_visibility_button.set_related_action (ActionManager::get_action (X_("Common"), X_("change-preferences-visibility")));
+       prefs_visibility_button.set_name (X_("page switch button"));
+
+       Gtkmm2ext::UI::instance()->set_tip (editor_visibility_button,
+                                           string_compose (_("Drag this tab to the desktop to show %1 in its own window\n\n"
+                                                             "To put the window back, use the Window > %1 > Attach menu action"), editor->name()));
+
+       Gtkmm2ext::UI::instance()->set_tip (mixer_visibility_button,
+                                           string_compose (_("Drag this tab to the desktop to show %1 in its own window\n\n"
+                                                             "To put the window back, use the Window > %1 > Attach menu action"), mixer->name()));
+
+       Gtkmm2ext::UI::instance()->set_tip (prefs_visibility_button,
+                                           string_compose (_("Drag this tab to the desktop to show %1 in its own window\n\n"
+                                                             "To put the window back, use the Window > %1 > Attach menu action"), rc_option_editor->name()));
+
+       window_button_box->pack_start (editor_visibility_button, false, false);
+       window_button_box->pack_start (mixer_visibility_button, false, false);
+       window_button_box->pack_start (prefs_visibility_button, false, false);
+
+       menu_hbox.pack_start (*window_button_box, false, false, 20);
+
        bool wall_clock = false;
        bool disk_space = false;
 
-       if (!Profile->get_small_screen()) {
+       if (!Profile->get_small_screen()) {
 #ifndef __APPLE__
                // OSX provides its own wallclock, thank you very much
                wall_clock = true;
@@ -554,6 +648,7 @@ ARDOUR_UI::build_menu_bar ()
                disk_space = true;
        }
 
+
        hbox->pack_end (error_alert_button, false, false, 2);
 
        hbox->pack_end (wall_clock_label, false, false, 2);
@@ -744,3 +839,21 @@ ARDOUR_UI::tabs()
 {
        return _tabs;
 }
+
+bool
+ARDOUR_UI::tabbable_visibility_button_press (GdkEventButton* ev, string const& tabbable_name)
+{
+       if (ev->button != 3) {
+               return false;
+       }
+
+       /* context menu is defined in *.menus.in
+        */
+
+       string menu_name = string ("/ui/") + tabbable_name + X_("TabbableButtonMenu");
+       Gtk::Menu* menu = dynamic_cast<Gtk::Menu*> (ActionManager::get_widget (menu_name.c_str()));
+       if (menu) {
+               menu->popup (3, ev->time);
+       }
+       return true;
+}