From 9a5e5ce31710aff1017ffcbb3ea223fa32c31a9d Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 21 Apr 2010 02:24:38 +0000 Subject: [PATCH] commits 6001-6525 inclusive from 2.X applied to 3.0 git-svn-id: http://subversion.ardour.org/svn/ardour2/ardour2/branches/3.0@6942 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardour.menus.in | 1 + gtk2_ardour/ardour_ui.cc | 89 +++++++++++++++++++++--------- gtk2_ardour/ardour_ui.h | 9 +-- gtk2_ardour/ardour_ui2.cc | 30 +++++++++- gtk2_ardour/ardour_ui_ed.cc | 8 ++- gtk2_ardour/editor.cc | 4 +- gtk2_ardour/gettext.h | 2 +- gtk2_ardour/plugin_selector.cc | 2 +- gtk2_ardour/processor_box.cc | 26 +++++++-- gtk2_ardour/utils.cc | 113 ++++++++++++++++++++++++++++---------- libs/ardour/ardour/audioengine.h | 3 +- libs/ardour/ardour/route.h | 1 + libs/ardour/ardour/session.h | 3 +- libs/ardour/audioengine.cc | 52 +++++++++++++++++- libs/ardour/gettext.h | 2 +- libs/ardour/ladspa_plugin.cc | 1 + libs/ardour/playlist.cc | 48 ++++++++++++---- libs/ardour/route.cc | 20 ++++++- libs/ardour/session.cc | 18 ++++++ libs/ardour/session_state.cc | 6 +- libs/ardour/session_transport.cc | 5 +- libs/ardour/wscript | 8 ++- libs/gtkmm2ext/gettext.h | 2 +- libs/gtkmm2ext/gtk_ui.cc | 2 +- libs/gtkmm2ext/gtkmm2ext/gtk_ui.h | 2 +- libs/gtkmm2ext/keyboard.cc | 3 +- 26 files changed, 361 insertions(+), 99 deletions(-) diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index f52152416..f7234ed8c 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -8,6 +8,7 @@ + diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index c24d16bcd..0944686f4 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -343,9 +343,10 @@ ARDOUR_UI::create_engine () engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context()); engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context()); - engine->Halted.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_halted, this), gui_context()); engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context()); + engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); + post_engine (); return 0; @@ -726,10 +727,11 @@ void ARDOUR_UI::finish() { if (_session) { + int tries = 0; - if (_session->transport_rolling()) { - _session->request_stop (); - usleep (250000); + if (_session->transport_rolling() && (++tries < 8)) { + _session->request_stop (false, true); + usleep (10000); } if (_session->dirty()) { @@ -1444,14 +1446,14 @@ ARDOUR_UI::transport_stop () return; } - _session->request_stop (); + _session->request_stop (false, true); } void ARDOUR_UI::transport_stop_and_forget_capture () { if (_session) { - _session->request_stop (true); + _session->request_stop (true, true); } } @@ -1519,7 +1521,12 @@ ARDOUR_UI::transport_roll () bool rolling = _session->transport_rolling(); if (_session->get_play_loop()) { - _session->request_play_loop (false, true); + /* XXX it is not possible to just leave seamless loop and keep + playing at present (nov 4th 2009) + */ + if (!Config->get_seamless_loop()) { + _session->request_play_loop (false, true); + } } else if (_session->get_play_range () && !join_play_range_button.get_active()) { /* stop playing a range if we currently are */ _session->request_play_range (0, true); @@ -1576,7 +1583,7 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode) _session->request_play_loop (false, true); } else if (_session->get_play_range ()) { affect_transport = false; - _session->request_play_range (0, true); + _session->request_play_range (0, true); } } @@ -1826,23 +1833,46 @@ ARDOUR_UI::engine_running () } void -ARDOUR_UI::engine_halted () +ARDOUR_UI::engine_halted (const char* reason, bool free_reason) { - ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_halted) + if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { + /* we can't rely on the original string continuing to exist when we are called + again in the GUI thread, so make a copy and note that we need to + free it later. + */ + char *copy = strdup (reason); + Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true)); + return; + } ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false); ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true); update_sample_rate (0); - MessageDialog msg (*editor, - _("\ + string msgstr; + + /* if the reason is a non-empty string, it means that the backend was shutdown + rather than just Ardour. + */ + + if (strlen (reason)) { + msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason); + } else { + msgstr = _("\ JACK has either been shutdown or it\n\ disconnected Ardour because Ardour\n\ was not fast enough. Try to restart\n\ -JACK, reconnect and save the session.")); +JACK, reconnect and save the session."); + } + + MessageDialog msg (*editor, msgstr); pop_back_splash (); msg.run (); + + if (free_reason) { + free ((char*) reason); + } } int32_t @@ -1940,24 +1970,29 @@ ARDOUR_UI::stop_blinking () /** Ask the user for the name of a new shapshot and then take it. */ + void -ARDOUR_UI::snapshot_session () +ARDOUR_UI::snapshot_session (bool switch_to_it) { ArdourPrompter prompter (true); string snapname; - char timebuf[128]; - time_t n; - struct tm local_time; - - time (&n); - localtime_r (&n, &local_time); - strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time); prompter.set_name ("Prompter"); prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT); prompter.set_title (_("Take Snapshot")); + prompter.set_title (_("Take Snapshot")); prompter.set_prompt (_("Name of New Snapshot")); - prompter.set_initial_text (timebuf); + + if (!switch_to_it) { + char timebuf[128]; + time_t n; + struct tm local_time; + + time (&n); + localtime_r (&n, &local_time); + strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time); + prompter.set_initial_text (timebuf); + } again: switch (prompter.run()) { @@ -2000,7 +2035,7 @@ ARDOUR_UI::snapshot_session () } if (do_save) { - save_state (snapname); + save_state (snapname, switch_to_it); } break; } @@ -2011,13 +2046,13 @@ ARDOUR_UI::snapshot_session () } void -ARDOUR_UI::save_state (const string & name) +ARDOUR_UI::save_state (const string & name, bool switch_to_it) { - save_state_canfail (name); + save_state_canfail (name, switch_to_it); } int -ARDOUR_UI::save_state_canfail (string name) +ARDOUR_UI::save_state_canfail (string name, bool switch_to_it) { if (_session) { int ret; @@ -2026,7 +2061,7 @@ ARDOUR_UI::save_state_canfail (string name) name = _session->snap_name(); } - if ((ret = _session->save_state (name)) != 0) { + if ((ret = _session->save_state (name, false, switch_to_it)) != 0) { return ret; } } diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 6699b423c..f8b8ec040 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -147,8 +147,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr int unload_session (bool hide_stuff = false); void close_session(); - int save_state_canfail (std::string state_name = ""); - void save_state (const std::string & state_name = ""); + int save_state_canfail (std::string state_name = "", bool switch_to_it = false); + void save_state (const std::string & state_name = "", bool switch_to_it = false); static double gain_to_slider_position (ARDOUR::gain_t g); static ARDOUR::gain_t slider_position_to_gain (double pos); @@ -282,7 +282,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void map_transport_state (); int32_t do_engine_start (); - void engine_halted (); + void engine_halted (const char* reason, bool free_reason); void engine_stopped (); void engine_running (); @@ -567,7 +567,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr guint32 last_key_press_time; - void snapshot_session (); + void snapshot_session (bool switch_to_it); Mixer_UI *mixer; int create_mixer (); @@ -694,6 +694,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr Glib::RefPtr ptag, Glib::RefPtr mtag, const char *msg); Gtk::Label status_bar_label; + bool status_bar_button_press (GdkEventButton*); Gtk::ToggleButton error_log_button; void loading_message (const std::string& msg); diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc index 543ff7aee..8aa28e268 100644 --- a/gtk2_ardour/ardour_ui2.cc +++ b/gtk2_ardour/ardour_ui2.cc @@ -76,12 +76,21 @@ ARDOUR_UI::setup_windows () #ifdef TOP_MENUBAR HBox* status_bar_packer = manage (new HBox); + EventBox* status_bar_event_box = manage (new EventBox); + status_bar_event_box->add (status_bar_label); + status_bar_event_box->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK); status_bar_label.set_size_request (300, -1); - status_bar_packer->pack_start (status_bar_label, true, true, 6); + status_bar_packer->pack_start (*status_bar_event_box, true, true, 6); status_bar_packer->pack_start (error_log_button, false, false); - error_log_button.signal_clicked().connect (sigc::mem_fun (*this, &UI::toggle_errors)); + status_bar_label.show (); + status_bar_event_box->show (); + status_bar_packer->show (); + error_log_button.show (); + + error_log_button.signal_clicked().connect (mem_fun (*this, &UI::toggle_errors)); + status_bar_event_box->signal_button_press_event().connect (mem_fun (*this, &ARDOUR_UI::status_bar_button_press)); editor->get_status_bar_packer().pack_start (*status_bar_packer, true, true); editor->get_status_bar_packer().pack_start (menu_bar_base, false, false, 6); @@ -133,6 +142,23 @@ ARDOUR_UI::setup_tooltips () editor->setup_tooltips (); } +bool +ARDOUR_UI::status_bar_button_press (GdkEventButton* ev) +{ + bool handled = false; + + switch (ev->button) { + case 1: + status_bar_label.set_text (""); + handled = true; + break; + default: + break; + } + + return handled; +} + void ARDOUR_UI::display_message (const char *prefix, gint prefix_len, RefPtr ptag, RefPtr mtag, const char *msg) { diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index f3bc96c6c..49b6629c7 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -136,7 +136,11 @@ ARDOUR_UI::install_actions () #endif - act = ActionManager::register_action (main_actions, X_("Snapshot"), _("Snapshot..."), sigc::mem_fun(*this, &ARDOUR_UI::snapshot_session)); + act = ActionManager::register_action (main_actions, X_("Snapshot"), _("Snapshot..."), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::snapshot_session), false)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::write_sensitive_actions.push_back (act); + + act = ActionManager::register_action (main_actions, X_("SaveAs"), _("SaveAs ..."), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::snapshot_session), true)); ActionManager::session_sensitive_actions.push_back (act); ActionManager::write_sensitive_actions.push_back (act); @@ -237,7 +241,7 @@ ARDOUR_UI::install_actions () //act = ActionManager::register_action (common_actions, X_("AddMidiBus"), _("Add Midi Bus"), sigc::mem_fun(*this, &ARDOUR_UI::session_add_midi_bus)); //ActionManager::session_sensitive_actions.push_back (act); #endif - act = ActionManager::register_action (common_actions, X_("Save"), _("Save"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_state), string(""))); + act = ActionManager::register_action (common_actions, X_("Save"), _("Save"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_state), string(""), false)); ActionManager::session_sensitive_actions.push_back (act); ActionManager::write_sensitive_actions.push_back (act); act = ActionManager::register_action (common_actions, X_("RemoveLastCapture"), _("Remove Last Capture"), sigc::mem_fun(*this, &ARDOUR_UI::remove_last_capture)); diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index d9ca85b93..bb8996ba9 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1493,7 +1493,7 @@ Editor::build_track_region_context_menu (nframes64_t frame) boost::shared_ptr dummy_region; // = NULL add_region_context_items (rtv->view(), dummy_region, edit_items); } else { - for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + for (Playlist::RegionList::reverse_iterator i = regions->rbegin(); i != regions->rend(); ++i) { add_region_context_items (rtv->view(), (*i), edit_items); } } @@ -1541,7 +1541,7 @@ Editor::build_track_crossfade_context_menu (nframes64_t frame) boost::shared_ptr dummy_region; // = NULL add_region_context_items (atv->audio_view(), dummy_region, edit_items); } else { - for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + for (Playlist::RegionList::reverse_iterator i = regions->rbegin(); i != regions->rend(); ++i) { add_region_context_items (atv->audio_view(), (*i), edit_items); } } diff --git a/gtk2_ardour/gettext.h b/gtk2_ardour/gettext.h index 339c74ffe..2645402e9 100644 --- a/gtk2_ardour/gettext.h +++ b/gtk2_ardour/gettext.h @@ -20,7 +20,7 @@ #define _LIBGETTEXT_H 1 /* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS +#ifdef ENABLE_NLS /* Get declarations of GNU message catalog functions. */ # include diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc index 9c0ab70a2..890c09ede 100644 --- a/gtk2_ardour/plugin_selector.cc +++ b/gtk2_ardour/plugin_selector.cc @@ -586,7 +586,7 @@ PluginSelector::build_plugin_menu () delete _plugin_menu; - _plugin_menu = new Menu; + _plugin_menu = manage (new Menu); _plugin_menu->set_name("ArdourContextMenu"); MenuList& items = _plugin_menu->items(); diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc index add816e40..42711b493 100644 --- a/gtk2_ardour/processor_box.cc +++ b/gtk2_ardour/processor_box.cc @@ -1242,11 +1242,27 @@ ProcessorBox::rename_processor (boost::shared_ptr processor) case Gtk::RESPONSE_ACCEPT: name_prompter.get_result (result); if (result.length()) { - if (_session->route_by_name (result)) { - ARDOUR_UI::instance()->popup_error (_("A track already exists with that name.")); - return; - } - processor->set_name (result); + + int tries = 0; + string test = result; + + while (tries < 100) { + if (_session->io_name_is_legal (test)) { + result = test; + break; + } + tries++; + + test = string_compose ("%1-%2", result, tries); + } + + if (tries < 100) { + processor->set_name (result); + } else { + /* unlikely! */ + ARDOUR_UI::instance()->popup_error + (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result)); + } } break; } diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index aa57a3b77..e96137ee2 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -504,12 +504,6 @@ set_color (Gdk::Color& c, int rgb) c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256); } -#ifdef GTKOSX -extern "C" { - gboolean gdk_quartz_possibly_forward (GdkEvent*); -} -#endif - bool relay_key_press (GdkEventKey* ev, Gtk::Window* win) { @@ -526,6 +520,73 @@ forward_key_press (GdkEventKey* ev) return PublicEditor::instance().on_key_press_event(ev); } +#ifdef GTKOSX +static guint +osx_keyval_without_alt (guint accent_keyval) +{ + switch (accent_keyval) { + case GDK_oe: + return GDK_q; + case GDK_registered: + return GDK_r; + case GDK_dagger: + return GDK_t; + case GDK_yen: + return GDK_y; + case GDK_diaeresis: + return GDK_u; + case GDK_oslash: + return GDK_o; + case GDK_Greek_pi: + return GDK_p; + case GDK_leftdoublequotemark: + return GDK_bracketleft; + case GDK_leftsinglequotemark: + return GDK_bracketright; + case GDK_guillemotleft: + return GDK_backslash; + case GDK_aring: + return GDK_a; + case GDK_ssharp: + return GDK_s; + case GDK_partialderivative: + return GDK_d; + case GDK_function: + return GDK_f; + case GDK_copyright: + return GDK_g; + case GDK_abovedot: + return GDK_h; + case GDK_notsign: + return GDK_l; + case GDK_ellipsis: + return GDK_semicolon; + case GDK_ae: + return GDK_apostrophe; + case GDK_Greek_OMEGA: + return GDK_z; + case GDK_ccedilla: + return GDK_c; + case GDK_radical: + return GDK_v; + case GDK_integral: + return GDK_b; + case GDK_mu: + return GDK_m; + case GDK_lessthanequal: + return GDK_comma; + case GDK_greaterthanequal: + return GDK_period; + case GDK_division: + return GDK_slash; + default: + break; + } + + return GDK_VoidSymbol; +} +#endif + bool key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) { @@ -595,6 +656,24 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) all "normal text" accelerators. */ +#ifdef GTKOSX + if (!special_handling_of_unmodified_accelerators) { + if (ev->state & GDK_MOD1_MASK) { + /* we're not in a text entry or "magic focus" widget so we don't want OS X "special-character" + text-style handling of alt-. change the keyval back to what it would be without + the alt key. this way, we see -v rather than -radical and so on. + */ + guint keyval_without_alt = osx_keyval_without_alt (ev->keyval); + + if (keyval_without_alt != GDK_VoidSymbol) { +#ifdef DEBUG_ACCELERATOR_HANDLING + cerr << "Remapped " << gdk_keyval_name (ev->keyval) << " to " << gdk_keyval_name (keyval_without_alt) << endl; + +#endif ev->keyval = keyval_without_alt; + } + } + } +#endif if (!special_handling_of_unmodified_accelerators) { @@ -609,17 +688,6 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) { return true; } - -#ifdef GTKOSX - if (allow_activating) { - int oldval = ev->keyval; - ev->keyval = fakekey; - if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) { - return true; - } - ev->keyval = oldval; - } -#endif } } @@ -638,11 +706,6 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) #endif if (allow_activating) { -#ifdef GTKOSX - if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) { - return true; - } -#endif if (gtk_window_activate_key (win, ev)) { return true; } @@ -671,12 +734,6 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) #endif if (allow_activating) { - -#ifdef GTKOSX - if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) { - return true; - } -#endif return gtk_window_activate_key (win, ev); } diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 63f9afeb2..5e2657c56 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -224,7 +224,7 @@ _ the regular process() call to session->process() is not made. /* this signal is sent if JACK ever disconnects us */ - PBD::Signal0 Halted; + PBD::Signal1 Halted; /* these two are emitted when the engine itself is started and stopped @@ -306,6 +306,7 @@ _ the regular process() call to session->process() is not made. int connect_to_jack (std::string client_name, std::string session_uuid); static void halted (void *); + static void halted_info (jack_status_t,const char*,void *); void meter_thread (); void start_metering_thread (); diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index e5a1a4a14..ae514e2f1 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -188,6 +188,7 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou bool processor_is_prefader (boost::shared_ptr p); + bool has_io_processor_named (const std::string&); ChanCount max_processor_streams () const { return processor_max_streams; } /* special processors */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 81536169a..ed1dc68f4 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -240,6 +240,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi template void foreach_route (T *obj, void (T::*func)(boost::shared_ptr)); template void foreach_route (T *obj, void (T::*func)(Route&, A), A arg); + bool io_name_is_legal (const std::string&); boost::shared_ptr route_by_name (std::string); boost::shared_ptr route_by_id (PBD::ID); boost::shared_ptr route_by_remote_id (uint32_t id); @@ -356,7 +357,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi #ifdef HAVE_JACK_SESSION void jack_session_event (jack_session_event_t* event); #endif - int save_state (std::string snapshot_name, bool pending = false); + int save_state (std::string snapshot_name, bool pending = false, bool switch_to_snapshot = false); int restore_state (std::string snapshot_name); int save_template (std::string template_name); int save_history (std::string snapshot_name = ""); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 47704224c..a16f268ed 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -145,6 +145,19 @@ _thread_init_callback (void * /*arg*/) MIDI::JACK_MidiPort::set_process_thread (pthread_self()); } +typedef void (*_JackInfoShutdownCallback)(jack_status_t code, const char* reason, void *arg); + +static void (*on_info_shutdown)(jack_client_t*, _JackInfoShutdownCallback, void *); +extern void jack_on_info_shutdown (jack_client_t*, _JackInfoShutdownCallback, void *) __attribute__((weak)); + +static void check_jack_symbols () __attribute__((constructor)); + +void check_jack_symbols () +{ + /* use weak linking to see if we really have various late-model JACK function */ + on_info_shutdown = jack_on_info_shutdown; +} + static void ardour_jack_error (const char* msg) { @@ -183,7 +196,11 @@ AudioEngine::start () _processed_frames = 0; last_monitor_check = 0; - jack_on_shutdown (_priv_jack, halted, this); + if (on_info_shutdown) { + jack_on_info_shutdown (_priv_jack, halted_info, this); + } else { + jack_on_shutdown (_priv_jack, halted, this); + } jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this); jack_set_thread_init_callback (_priv_jack, _thread_init_callback, this); // jack_set_process_callback (_priv_jack, _process_callback, this); @@ -969,6 +986,36 @@ AudioEngine::get_ports (const string& port_name_pattern, const string& type_name } void +AudioEngine::halted_info (jack_status_t code, const char* reason, void *arg) +{ + /* called from jack shutdown handler */ + + AudioEngine* ae = static_cast (arg); + bool was_running = ae->_running; + + ae->stop_metering_thread (); + + ae->_running = false; + ae->_buffer_size = 0; + ae->_frame_rate = 0; + ae->_jack = 0; + + if (was_running) { +#ifdef HAVE_JACK_ON_INFO_SHUTDOWN + switch (code) { + case JackBackendError: + ae->Halted(reason); /* EMIT SIGNAL */ + break; + default: + ae->Halted(""); /* EMIT SIGNAL */ + } +#else + ae->Halted(""); /* EMIT SIGNAL */ +#endif + } +} + +void AudioEngine::halted (void *arg) { cerr << "HALTED by JACK\n"; @@ -983,9 +1030,10 @@ AudioEngine::halted (void *arg) ae->_running = false; ae->_buffer_size = 0; ae->_frame_rate = 0; + ae->_jack = 0; if (was_running) { - ae->Halted(); /* EMIT SIGNAL */ + ae->Halted(""); /* EMIT SIGNAL */ MIDI::JACK_MidiPort::JackHalted (); /* EMIT SIGNAL */ } } diff --git a/libs/ardour/gettext.h b/libs/ardour/gettext.h index 339c74ffe..2645402e9 100644 --- a/libs/ardour/gettext.h +++ b/libs/ardour/gettext.h @@ -20,7 +20,7 @@ #define _LIBGETTEXT_H 1 /* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS +#ifdef ENABLE_NLS /* Get declarations of GNU message catalog functions. */ # include diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index 81cdff961..d9a1ad074 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -691,6 +691,7 @@ LadspaPluginInfo::load (Session& session) if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) { error << string_compose(_("LADSPA: cannot load module from \"%1\""), path) << endmsg; error << dlerror() << endmsg; + return PluginPtr ((Plugin*) 0); } else { plugin.reset (new LadspaPlugin (module, session.engine(), session, index, session.frame_rate())); } diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 57f49a68d..6fc7fdc2c 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -1004,7 +1004,7 @@ Playlist::partition_internal (framepos_t start, framepos_t end, bool cutting, Re current->suspend_property_changes (); thawlist.push_back (current); - current->cut_end (pos2, this); + current->cut_end (pos2 - 1, this); } else if (overlap == OverlapEnd) { @@ -1043,7 +1043,7 @@ Playlist::partition_internal (framepos_t start, framepos_t end, bool cutting, Re current->suspend_property_changes (); thawlist.push_back (current); - current->cut_end (pos2, this); + current->cut_end (pos2 - 1, this); } else if (overlap == OverlapStart) { @@ -2490,22 +2490,48 @@ void Playlist::raise_region_to_top (boost::shared_ptr region) { /* does nothing useful if layering mode is later=higher */ - if ((_session.config.get_layer_model() == MoveAddHigher) || - (_session.config.get_layer_model() == AddHigher)) { - timestamp_layer_op (region); - relayer (); + switch (_session.config.get_layer_model()) { + case LaterHigher: + return; + default: + break; } + + layer_t top = regions.size() - 1; + + if (region->layer() >= top) { + /* already on the top */ + return; + } + + move_region_to_layer (top, region, 1); + /* mark the region's last_layer_op as now, so that it remains on top when + doing future relayers (until something else takes over) + */ + timestamp_layer_op (region); } void Playlist::lower_region_to_bottom (boost::shared_ptr region) { /* does nothing useful if layering mode is later=higher */ - if ((_session.config.get_layer_model() == MoveAddHigher) || - (_session.config.get_layer_model() == AddHigher)) { - region->set_last_layer_op (0); - relayer (); + switch (_session.config.get_layer_model()) { + case LaterHigher: + return; + default: + break; + } + + if (region->layer() == 0) { + /* already on the bottom */ + return; } + + move_region_to_layer (0, region, -1); + /* force region's last layer op to zero so that it stays at the bottom + when doing future relayers + */ + region->set_last_layer_op (0); } int @@ -2688,8 +2714,6 @@ Playlist::set_frozen (bool yn) void Playlist::timestamp_layer_op (boost::shared_ptr region) { -// struct timeval tv; -// gettimeofday (&tv, 0); region->set_last_layer_op (++layer_op_counter); } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index a29dab536..01242cd80 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -269,7 +269,7 @@ Route::ensure_track_or_route_name(string name, Session &session) { string newname = name; - while (session.route_by_name (newname) != NULL) { + while (!session.io_name_is_legal (newname)) { newname = bump_name_once (newname); } @@ -3252,3 +3252,21 @@ Route::nth_send (uint32_t n) return boost::shared_ptr (); } + +bool +Route::has_io_processor_named (const string& name) +{ + Glib::RWLock::ReaderLock lm (_processor_lock); + ProcessorList::iterator i; + + for (i = _processors.begin(); i != _processors.end(); ++i) { + if (boost::dynamic_pointer_cast (*i) || + boost::dynamic_pointer_cast (*i)) { + if ((*i)->name() == name) { + return true; + } + } + } + + return false; +} diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 90e580989..7f316c953 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -2304,6 +2304,24 @@ Session::get_routes_with_internal_returns() const return rl; } +bool +Session::io_name_is_legal (const std::string& name) +{ + shared_ptr r = routes.reader (); + + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + if ((*i)->name() == name) { + return false; + } + + if ((*i)->has_io_processor_named (name)) { + return false; + } + } + + return true; +} + shared_ptr Session::route_by_name (string name) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index d32f61774..9f1adcfe9 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -748,7 +748,7 @@ Session::jack_session_event (jack_session_event_t * event) #endif int -Session::save_state (string snapshot_name, bool pending) +Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot) { XMLTree tree; sys::path xml_path(_session_dir->root_path()); @@ -773,7 +773,9 @@ Session::save_state (string snapshot_name, bool pending) if (snapshot_name.empty()) { snapshot_name = _current_snapshot_name; - } + } else if (switch_to_snapshot) { + _current_snapshot_name = snapshot_name; + } if (!pending) { diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 686ca4ce7..c5e679532 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -230,8 +230,9 @@ Session::realtime_stop (bool abort, bool clear_state) _clear_event_type (SessionEvent::RangeStop); _clear_event_type (SessionEvent::RangeLocate); - disable_record (true); - + /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */ + disable_record (true, (!Config->get_latched_record_enable() && clear_state)); + reset_slave_state (); _transport_speed = 0; diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 32127b6f7..1aceb24e5 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -244,7 +244,13 @@ def configure(conf): conf.check(header_name='wordexp.h', define_name='HAVE_WORDEXP') conf.check(header_name='jack/session.h', define_name='HAVE_JACK_SESSION') - + + conf.check_cc(fragment = "#include \nvoid callback (int code, const char* reason, void* arg) { return; }\nint main(int argc, char **argv) { jack_client_t* c; jack_on_info_shutdown (c, callback, (void*) 0); return 0; }\n", + linkflags = ['-ljack'], + msg = 'Checking for jack_on_info_shutdown', + define_name = 'HAVE_JACK_ON_INFO_SHUTDOWN', + okmsg = 'ok') + if flac_supported(): conf.define ('HAVE_FLAC', 1) autowaf.display_msg(conf, 'Checking for FLAC support', True) diff --git a/libs/gtkmm2ext/gettext.h b/libs/gtkmm2ext/gettext.h index 339c74ffe..2645402e9 100644 --- a/libs/gtkmm2ext/gettext.h +++ b/libs/gtkmm2ext/gettext.h @@ -20,7 +20,7 @@ #define _LIBGETTEXT_H 1 /* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS +#ifdef ENABLE_NLS /* Get declarations of GNU message catalog functions. */ # include diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc index 7695892a8..cfcc0df91 100644 --- a/libs/gtkmm2ext/gtk_ui.cc +++ b/libs/gtkmm2ext/gtk_ui.cc @@ -602,7 +602,7 @@ UI::handle_fatal (const char *message) } void -UI::popup_error (const char *text) +UI::popup_error (const string& text) { PopUp *pup; diff --git a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h index 2484b1e62..a0ea1e86a 100644 --- a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h +++ b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h @@ -109,7 +109,7 @@ class UI : public Receiver, public AbstractUI void run (Receiver &old_receiver); void set_state (Gtk::Widget *w, Gtk::StateType state); - void popup_error (const char *text); + void popup_error (const std::string& text); void flush_pending (); void toggle_errors (); void touch_display (Touchable *); diff --git a/libs/gtkmm2ext/keyboard.cc b/libs/gtkmm2ext/keyboard.cc index da51d4e41..8c13e2e18 100644 --- a/libs/gtkmm2ext/keyboard.cc +++ b/libs/gtkmm2ext/keyboard.cc @@ -81,7 +81,7 @@ std::string Keyboard::user_keybindings_path; bool Keyboard::can_save_keybindings = false; bool Keyboard::bindings_changed_after_save_became_legal = false; map Keyboard::binding_files; -string Keyboard::_current_binding_name = _("Unknown"); +string Keyboard::_current_binding_name; map,Keyboard::AccelKeyLess> Keyboard::release_keys; /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */ @@ -110,6 +110,7 @@ Keyboard::Keyboard () { if (_the_keyboard == 0) { _the_keyboard = this; + _current_binding_name = _("Unknown"); } RelevantModifierKeyMask = (GdkModifierType) gtk_accelerator_get_default_mod_mask (); -- 2.11.4.GIT