X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_ui.cc;h=fe9a5c3713ee85b9aa4d8f8f9b574e9387146ad2;hb=569b0bbcb49a0b132603ab347af9fa59729cefc1;hp=8f05f6077770bfe951c57ac5a9d9c82de3c12e97;hpb=949163f80610af76edc2c1878dfb00bae2de316a;p=ardour.git diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 8f05f60777..fe9a5c3713 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -71,6 +71,7 @@ #include "ardour/ardour.h" #include "ardour/audio_backend.h" +#include "ardour/audio_track.h" #include "ardour/audioengine.h" #include "ardour/audiofilesource.h" #include "ardour/automation_watch.h" @@ -78,6 +79,7 @@ #include "ardour/filename_extensions.h" #include "ardour/filesystem_paths.h" #include "ardour/ltc_file_reader.h" +#include "ardour/midi_track.h" #include "ardour/port.h" #include "ardour/plugin_manager.h" #include "ardour/process_thread.h" @@ -91,6 +93,8 @@ #include "ardour/slave.h" #include "ardour/system_exec.h" +#include "LuaBridge/LuaBridge.h" + #ifdef WINDOWS_VST_SUPPORT #include #endif @@ -98,6 +102,11 @@ #include "ardour/audio_unit.h" #endif +// fix for OSX (nsm.h has a check function, AU/Apple defines check) +#ifdef check +#undef check +#endif + #include "timecode/time.h" typedef uint64_t microseconds_t; @@ -124,6 +133,8 @@ typedef uint64_t microseconds_t; #include "keyboard.h" #include "keyeditor.h" #include "location_ui.h" +#include "lua_script_manager.h" +#include "luawindow.h" #include "main_clock.h" #include "missing_file_dialog.h" #include "missing_plugin_dialog.h" @@ -140,6 +151,7 @@ typedef uint64_t microseconds_t; #include "route_time_axis.h" #include "route_params_ui.h" #include "save_as_dialog.h" +#include "script_selector.h" #include "session_dialog.h" #include "session_metadata_dialog.h" #include "session_option_editor.h" @@ -226,18 +238,14 @@ libxml_structured_error_func (void* /* parsing_context*/, ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) -<<<<<<< HEAD - : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp) -======= - : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp) ->>>>>>> first compilable version of tabbable design. , session_loaded (false) , gui_object_state (new GUIObjectState) , primary_clock (new MainClock (X_("primary"), X_("transport"), true )) , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false)) , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false)) , video_timeline(0) + , global_actions (X_("global")) , ignore_dual_punch (false) , editor (0) , mixer (0) @@ -267,6 +275,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , last_key_press_time (0) , save_as_dialog (0) , meterbridge (0) + , luawindow (0) , rc_option_editor (0) , speaker_config_window (X_("speaker-config"), _("Speaker Configuration")) , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses")) @@ -275,6 +284,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , route_params (X_("inspector"), _("Tracks and Busses")) , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup")) , export_video_dialog (X_("video-export"), _("Video Export Dialog")) + , lua_script_window (X_("script-manager"), _("Script Manager")) , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this)) , add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this)) , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this)) @@ -292,6 +302,9 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , _feedback_exists (false) , _log_not_acknowledged (LogLevelNone) , duplicate_routes_dialog (0) + , editor_visibility_button (S_("Window|Editor")) + , mixer_visibility_button (S_("Window|Mixer")) + , prefs_visibility_button (S_("Window|Preferences")) { Gtkmm2ext::init (localedir); @@ -397,9 +410,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) keyboard->set_state (*node, Stateful::loading_state_version); } - /* we don't like certain modifiers */ - Bindings::set_ignored_state (GDK_LOCK_MASK|GDK_MOD2_MASK|GDK_MOD3_MASK); - UIConfiguration::instance().reset_dpi (); TimeAxisViewItem::set_constant_heights (); @@ -426,10 +436,11 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) audio_port_matrix.set_state (*ui_xml, 0); midi_port_matrix.set_state (*ui_xml, 0); export_video_dialog.set_state (*ui_xml, 0); + lua_script_window.set_state (*ui_xml, 0); } /* Separate windows */ - + WM::Manager::instance().register_window (&key_editor); WM::Manager::instance().register_window (&session_option_editor); WM::Manager::instance().register_window (&speaker_config_window); @@ -439,6 +450,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) WM::Manager::instance().register_window (&route_params); WM::Manager::instance().register_window (&audio_midi_setup); WM::Manager::instance().register_window (&export_video_dialog); + WM::Manager::instance().register_window (&lua_script_window); WM::Manager::instance().register_window (&bundle_manager); WM::Manager::instance().register_window (&location_ui); WM::Manager::instance().register_window (&big_clock_window); @@ -591,20 +603,24 @@ ARDOUR_UI::post_engine () if (ARDOUR_COMMAND_LINE::show_key_actions) { - for (list::const_iterator mb = Bindings::bindings.begin(); mb != Bindings::bindings.end(); ++mb) { - vector names; - vector paths; - vector keys; + vector paths; + vector labels; + vector tooltips; + vector keys; + vector > actions; + + Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions); + + vector::iterator k; + vector::iterator p; -#warning Paul fix this before tabbed is merged - // mb->second->get_all_actions (names, paths, keys); - - vector::iterator n; - vector::iterator k; - vector::iterator p; - for (n = names.begin(), k = keys.begin(), p = paths.begin(); n != names.end(); ++n, ++k, ++p) { - cout << "Action: '" << (*n) << "' bound to '" << (*k) << "' Path: '" << (*p) << "'" << endl; + for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) { + + if ((*k).empty()) { + cout << *p << endl; + } else { + cout << *p << " => " << *k << endl; } } @@ -612,7 +628,7 @@ ARDOUR_UI::post_engine () AudioEngine::instance()->stop (); exit (0); } - + /* this being a GUI and all, we want peakfiles */ AudioFileSource::set_build_peakfiles (true); @@ -620,17 +636,12 @@ ARDOUR_UI::post_engine () /* set default clock modes */ - if (Profile->get_sae()) { - primary_clock->set_mode (AudioClock::BBT); - secondary_clock->set_mode (AudioClock::MinSec); - } else { - primary_clock->set_mode (AudioClock::Timecode); - secondary_clock->set_mode (AudioClock::BBT); - } + primary_clock->set_mode (AudioClock::Timecode); + secondary_clock->set_mode (AudioClock::BBT); /* start the time-of-day-clock */ -#ifndef GTKOSX +#ifndef __APPLE__ /* OS X provides a nearly-always visible wallclock, so don't be stupid */ update_wall_clock (); Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1); @@ -654,15 +665,16 @@ ARDOUR_UI::~ARDOUR_UI () if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) { // don't bother at 'real' exit. the OS cleans up for us. - delete big_clock; - delete primary_clock; - delete secondary_clock; - delete _process_thread; - delete meterbridge; - delete editor; - delete mixer; - delete nsm; - delete gui_object_state; + delete big_clock; big_clock = 0; + delete primary_clock; primary_clock = 0; + delete secondary_clock; secondary_clock = 0; + delete _process_thread; _process_thread = 0; + delete meterbridge; meterbridge = 0; + delete luawindow; luawindow = 0; + delete editor; editor = 0; + delete mixer; mixer = 0; + delete nsm; nsm = 0; + delete gui_object_state; gui_object_state = 0; FastMeter::flush_pattern_cache (); PixFader::flush_pattern_cache (); } @@ -1701,8 +1713,8 @@ ARDOUR_UI::check_audioengine (Gtk::Window& parent) { if (!AudioEngine::instance()->connected()) { MessageDialog msg (parent, string_compose ( - _("%1 is not connected to any audio backend.\n" - "You cannot open or close sessions in this condition"), + _("%1 is not connected to any audio backend.\n" + "You cannot open or close sessions in this condition"), PROGRAM_NAME)); pop_back_splash (msg); msg.run (); @@ -1714,7 +1726,7 @@ ARDOUR_UI::check_audioengine (Gtk::Window& parent) void ARDOUR_UI::open_session () { - if (!check_audioengine(*editor)) { + if (!check_audioengine (_main_window)) { return; } @@ -1766,10 +1778,15 @@ ARDOUR_UI::open_session () } } - void -ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& output, RouteGroup* route_group, - uint32_t how_many, const string& name_template, PluginInfoPtr instrument) +ARDOUR_UI::session_add_mixed_track ( + const ChanCount& input, + const ChanCount& output, + RouteGroup* route_group, + uint32_t how_many, + const string& name_template, + bool strict_io, + PluginInfoPtr instrument) { list > tracks; @@ -1787,24 +1804,67 @@ ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& out } catch (...) { - MessageDialog msg (_main_window, - string_compose (_("There are insufficient ports available\n\ -to create a new track or bus.\n\ -You should save %1, exit and\n\ -restart with more ports."), PROGRAM_NAME)); - msg.run (); + display_insufficient_ports_message (); + return; + } + + if (strict_io) { + for (list >::iterator i = tracks.begin(); i != tracks.end(); ++i) { + (*i)->set_strict_io (true); + } } } +void +ARDOUR_UI::session_add_midi_bus ( + RouteGroup* route_group, + uint32_t how_many, + const string& name_template, + bool strict_io, + PluginInfoPtr instrument) +{ + RouteList routes; + + if (_session == 0) { + warning << _("You cannot add a track without a session already loaded.") << endmsg; + return; + } + + try { + routes = _session->new_midi_route (route_group, how_many, name_template, instrument); + if (routes.size() != how_many) { + error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg; + } + + } + catch (...) { + display_insufficient_ports_message (); + return; + } + + if (strict_io) { + for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) { + (*i)->set_strict_io (true); + } + } +} void -ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, const string& name_template, PluginInfoPtr instrument) +ARDOUR_UI::session_add_midi_route ( + bool disk, + RouteGroup* route_group, + uint32_t how_many, + const string& name_template, + bool strict_io, + PluginInfoPtr instrument) { ChanCount one_midi_channel; one_midi_channel.set (DataType::MIDI, 1); if (disk) { - session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, instrument); + session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, instrument); + } else { + session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument); } } @@ -1816,7 +1876,8 @@ ARDOUR_UI::session_add_audio_route ( ARDOUR::TrackMode mode, RouteGroup* route_group, uint32_t how_many, - string const & name_template + string const & name_template, + bool strict_io ) { list > tracks; @@ -1848,14 +1909,30 @@ ARDOUR_UI::session_add_audio_route ( } catch (...) { - MessageDialog msg (_main_window, - string_compose (_("There are insufficient ports available\n\ + display_insufficient_ports_message (); + return; + } + + if (strict_io) { + for (list >::iterator i = tracks.begin(); i != tracks.end(); ++i) { + (*i)->set_strict_io (true); + } + for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) { + (*i)->set_strict_io (true); + } + } +} + +void +ARDOUR_UI::display_insufficient_ports_message () +{ + MessageDialog msg (_main_window, + string_compose (_("There are insufficient ports available\n\ to create a new track or bus.\n\ You should save %1, exit and\n\ restart with more ports."), PROGRAM_NAME)); - pop_back_splash (msg); - msg.run (); - } + pop_back_splash (msg); + msg.run (); } void @@ -2768,7 +2845,7 @@ ARDOUR_UI::save_template () { ArdourPrompter prompter (true); - if (!check_audioengine(*editor)) { + if (!check_audioengine (_main_window)) { return; } @@ -2840,7 +2917,7 @@ ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& sess { BusProfile bus_profile; - if (nsm || Profile->get_sae()) { + if (nsm) { bus_profile.master_out_channels = 2; bus_profile.input_ac = AutoConnectPhysical; @@ -2928,8 +3005,6 @@ ARDOUR_UI::load_from_application_api (const std::string& path) if (get_session_parameters (true, false)) { exit (1); } - - goto_editor_window (); } } @@ -3176,7 +3251,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri void ARDOUR_UI::close_session() { - if (!check_audioengine(*editor)) { + if (!check_audioengine (_main_window)) { return; } @@ -3889,7 +3964,6 @@ ARDOUR_UI::add_route (Gtk::Window* /* ignored */) } setup_order_hint(add_route_dialog->insert_at()); - string template_path = add_route_dialog->track_template(); DisplaySuspender ds; @@ -3908,6 +3982,7 @@ ARDOUR_UI::add_route (Gtk::Window* /* ignored */) PluginInfoPtr instrument = add_route_dialog->requested_instrument (); RouteGroup* route_group = add_route_dialog->route_group (); AutoConnectOption oac = Config->get_output_auto_connect(); + bool strict_io = add_route_dialog->use_strict_io (); if (oac & AutoConnectMaster) { output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio())); @@ -3920,20 +3995,106 @@ ARDOUR_UI::add_route (Gtk::Window* /* ignored */) switch (add_route_dialog->type_wanted()) { case AddRouteDialog::AudioTrack: - session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template); + session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io); break; case AddRouteDialog::MidiTrack: - session_add_midi_track (route_group, count, name_template, instrument); + session_add_midi_track (route_group, count, name_template, strict_io, instrument); break; case AddRouteDialog::MixedTrack: - session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, instrument); + session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument); break; case AddRouteDialog::AudioBus: - session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template); + session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io); + break; + case AddRouteDialog::MidiBus: + session_add_midi_bus (route_group, count, name_template, strict_io, instrument); break; } } +void +ARDOUR_UI::add_lua_script () +{ + if (!_session) { + return; + } + + LuaScriptInfoPtr spi; + ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session); + switch (ss.run ()) { + case Gtk::RESPONSE_ACCEPT: + spi = ss.script(); + break; + default: + return; + } + ss.hide(); + + std::string script = ""; + + try { + script = Glib::file_get_contents (spi->path); + } catch (Glib::FileError e) { + string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what()); + MessageDialog am (msg); + am.run (); + return; + } + + LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params"); + std::vector reg = _session->registered_lua_functions (); + + ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp); + switch (spd.run ()) { + case Gtk::RESPONSE_ACCEPT: + break; + default: + return; + } + + try { + _session->register_lua_function (spd.name(), script, lsp); + } catch (luabridge::LuaException const& e) { + string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ()); + MessageDialog am (msg); + am.run (); + } catch (SessionException e) { + string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ()); + MessageDialog am (msg); + am.run (); + } +} + +void +ARDOUR_UI::remove_lua_script () +{ + if (!_session) { + return; + } + if (_session->registered_lua_function_count () == 0) { + string msg = _("There are no active Lua session scripts present in this session."); + MessageDialog am (msg); + am.run (); + return; + } + + std::vector reg = _session->registered_lua_functions (); + SessionScriptManager sm ("Remove Lua Session Script", reg); + switch (sm.run ()) { + case Gtk::RESPONSE_ACCEPT: + break; + default: + return; + } + try { + _session->unregister_lua_function (sm.name()); + } catch (luabridge::LuaException const& e) { + string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ()); + MessageDialog am (msg); + am.run (); + } +} + void ARDOUR_UI::stop_video_server (bool ask_confirm) { @@ -4830,11 +4991,6 @@ ARDOUR_UI::setup_profile () Profile->set_small_screen (); } - if (g_getenv ("ARDOUR_SAE")) { - Profile->set_sae (); - Profile->set_single_package (); - } - if (g_getenv ("TRX")) { Profile->set_trx (); } @@ -5125,7 +5281,7 @@ ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* if (!window_icons.empty()) { window.set_default_icon_list (window_icons); } - + Gtkmm2ext::WindowTitle title (Glib::get_application_name()); if (!name.empty()) { @@ -5159,15 +5315,15 @@ ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window) /* until we get ardour bindings working, we are not handling key * releases yet. */ - + if (ev->type != GDK_KEY_PRESS) { return false; } - + if (event_window == &_main_window) { window = event_window; - + /* find current tab contents */ Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page()); @@ -5179,61 +5335,80 @@ ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window) } DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings)); - - } else if (event_window != 0) { + + } else { window = event_window; - + /* see if window uses ardour binding system */ bindings = reinterpret_cast(window->get_data ("ardour-bindings")); - } + } /* An empty binding set is treated as if it doesn't exist */ - + if (bindings && bindings->empty()) { bindings = 0; } - + return key_press_focus_accelerator_handler (*window, ev, bindings); } - + +static Gtkmm2ext::Bindings* +get_bindings_from_widget_heirarchy (GtkWidget* w) +{ + void* p; + + while (w) { + if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) { + break; + } + w = gtk_widget_get_parent (w); + } + + return reinterpret_cast (p); +} + bool ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings) { GtkWindow* win = window.gobj(); GtkWidget* focus = gtk_window_get_focus (win); bool special_handling_of_unmodified_accelerators = false; - /* consider all relevant modifiers but not LOCK or SHIFT */ const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK)); - GdkModifierType modifier = GdkModifierType (ev->state); - modifier = GdkModifierType (modifier & gtk_accelerator_get_default_mod_mask()); - Gtkmm2ext::possibly_translate_mod_to_make_legal_accelerator(modifier); - if (focus) { - + /* some widget has keyboard focus */ if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) { /* A particular kind of focusable widget currently has keyboard * focus. All unmodified key events should go to that widget - * first and not be used as an accelerator by default + * first and not be used as an accelerator by default */ special_handling_of_unmodified_accelerators = true; + + } else { + + Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus); + if (focus_bindings) { + bindings = focus_bindings; + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name())); + } } } - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7\n", + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n", win, ev->keyval, show_gdk_event_state (ev->state), special_handling_of_unmodified_accelerators, Keyboard::some_magic_widget_has_focus(), focus, - (focus ? gtk_widget_get_name (focus) : "no focus widget"))); + (focus ? gtk_widget_get_name (focus) : "no focus widget"), + ((ev->state & mask) ? "yes" : "no"))); /* This exists to allow us to override the way GTK handles key events. The normal sequence is: @@ -5266,9 +5441,9 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey all "normal text" accelerators. */ - + if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) { - + /* no special handling or there are modifiers in effect: accelerate first */ DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n"); @@ -5280,8 +5455,8 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey if (bindings) { - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 for this event\n", bindings)); - + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings)); + if (bindings->activate (k, Bindings::Press)) { DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); return true; @@ -5289,48 +5464,48 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey } DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n"); - - if (global_bindings->activate (k, Bindings::Press)) { + + if (global_bindings && global_bindings->activate (k, Bindings::Press)) { DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); return true; } DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n"); - + if (gtk_window_propagate_key_event (win, ev)) { DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n"); return true; } } else { - + /* no modifiers, propagate first */ - + DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n"); - + if (gtk_window_propagate_key_event (win, ev)) { DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n"); return true; } DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n"); - KeyboardKey k (ev->state, ev->keyval); + KeyboardKey k (ev->state, ev->keyval); if (bindings) { - + DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n"); - + if (bindings->activate (k, Bindings::Press)) { DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); return true; } - - } - + + } + DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n"); - - if (global_bindings->activate (k, Bindings::Press)) { + + if (global_bindings && global_bindings->activate (k, Bindings::Press)) { DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); return true; } @@ -5343,8 +5518,21 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey void ARDOUR_UI::load_bindings () { - if ((global_bindings = Bindings::get_bindings ("global", global_actions)) == 0) { + if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) { error << _("Global keybindings are missing") << endmsg; } } +void +ARDOUR_UI::cancel_solo () +{ + if (_session) { + if (_session->soloing()) { + _session->set_solo (_session->get_routes(), false); + } else if (_session->listening()) { + _session->set_listen (_session->get_routes(), false); + } + + _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window + } +}