diff --git a/gtk2_ardour/ardour-sae.menus b/gtk2_ardour/ardour-sae.menus index 382a02d74e..06a5dde056 100644 --- a/gtk2_ardour/ardour-sae.menus +++ b/gtk2_ardour/ardour-sae.menus @@ -197,6 +197,7 @@ + diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index 953254b07c..d1e7171059 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -208,6 +208,7 @@ + diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 5e27900f6b..6651387f6b 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -740,8 +740,7 @@ If you still wish to quit, please use the\n\n\ session->set_deletion_in_progress (); } engine->stop (true); - Config->save_state(); - ARDOUR_UI::config()->save_state(); + save_ardour_state (); quit (); } @@ -3010,3 +3009,4 @@ void ARDOUR_UI::audioengine_setup () { } + diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 4d4ec911be..f28d960186 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -688,6 +688,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI void set_remote_model (ARDOUR::RemoteModel); void set_denormal_model (ARDOUR::DenormalModel); + void toggle_sync_order_keys (); void toggle_StopPluginsWithTransport(); void toggle_DoNotRunPluginsWhileRecording(); void toggle_VerifyRemoveLastCapture(); diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 114d40b121..b5a6281c1b 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -408,6 +408,7 @@ ARDOUR_UI::install_actions () act->set_sensitive (false); #endif + ActionManager::register_toggle_action (option_actions, X_("SyncEditorAndMixerTrackOrder"), _("Sync Editor and Mixer track order"), mem_fun (*this, &ARDOUR_UI::toggle_sync_order_keys)); ActionManager::register_toggle_action (option_actions, X_("StopPluginsWithTransport"), _("Stop plugins with transport"), mem_fun (*this, &ARDOUR_UI::toggle_StopPluginsWithTransport)); ActionManager::register_toggle_action (option_actions, X_("VerifyRemoveLastCapture"), _("Verify remove last capture"), mem_fun (*this, &ARDOUR_UI::toggle_VerifyRemoveLastCapture)); ActionManager::register_toggle_action (option_actions, X_("PeriodicSafetyBackups"), _("Make periodic safety backups"), mem_fun (*this, &ARDOUR_UI::toggle_PeriodicSafetyBackups)); diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc index c2669d1884..6a7dcbc194 100644 --- a/gtk2_ardour/ardour_ui_options.cc +++ b/gtk2_ardour/ardour_ui_options.cc @@ -458,6 +458,12 @@ ARDOUR_UI::toggle_StopRecordingOnXrun() ActionManager::toggle_config_state ("options", "StopRecordingOnXrun", &Configuration::set_stop_recording_on_xrun, &Configuration::get_stop_recording_on_xrun); } +void +ARDOUR_UI::toggle_sync_order_keys () +{ + ActionManager::toggle_config_state ("options", "SyncEditorAndMixerTrackOrder", &Configuration::set_sync_all_route_ordering, &Configuration::get_sync_all_route_ordering); +} + void ARDOUR_UI::toggle_StopTransportAtEndOfSession() { @@ -1008,6 +1014,8 @@ ARDOUR_UI::parameter_changed (const char* parameter_name) ActionManager::map_some_state ("options", "PeriodicSafetyBackups", &Configuration::get_periodic_safety_backups); } else if (PARAM_IS ("stop-recording-on-xrun")) { ActionManager::map_some_state ("options", "StopRecordingOnXrun", &Configuration::get_stop_recording_on_xrun); + } else if (PARAM_IS ("sync-all-route-ordering")) { + ActionManager::map_some_state ("options", "SyncEditorAndMixerTrackOrder", &Configuration::get_sync_all_route_ordering); } else if (PARAM_IS ("stop-at-session-end")) { ActionManager::map_some_state ("options", "StopTransportAtEndOfSession", &Configuration::get_stop_at_session_end); } else if (PARAM_IS ("monitoring-model")) { diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index 1d24e6e48f..1766da943c 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -451,7 +451,6 @@ AudioTimeAxisView::update_pans () void AudioTimeAxisView::toggle_gain_track () { - bool showit = gain_automation_item->get_active(); if (showit != gain_track->marked_for_display()) { diff --git a/gtk2_ardour/axis_view.cc b/gtk2_ardour/axis_view.cc index 0c57eebfca..66388dd4f6 100644 --- a/gtk2_ardour/axis_view.cc +++ b/gtk2_ardour/axis_view.cc @@ -48,6 +48,7 @@ AxisView::AxisView (ARDOUR::Session& sess) : _session(sess) { _selected = false; _marked_for_display = true; + _old_order_key = 0; } AxisView::~AxisView() diff --git a/gtk2_ardour/axis_view.h b/gtk2_ardour/axis_view.h index 51f744c4e5..11ee9c9377 100644 --- a/gtk2_ardour/axis_view.h +++ b/gtk2_ardour/axis_view.h @@ -62,6 +62,9 @@ class AxisView : public virtual Selectable sigc::signal Hiding; sigc::signal GoingAway; + void set_old_order_key (uint32_t ok) { _old_order_key = ok; } + uint32_t old_order_key() const { return _old_order_key; } + protected: AxisView (ARDOUR::Session& sess); @@ -84,6 +87,7 @@ class AxisView : public virtual Selectable Gtk::Label name_label; bool _marked_for_display; + uint32_t _old_order_key; }; /* class AxisView */ diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index c2ce0c55d1..2387d9a2ec 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -315,6 +315,7 @@ Editor::Editor () _dragging_hscrollbar = false; _scrubbing = false; sfbrowser = 0; + ignore_route_order_sync = false; location_marker_color = ARDOUR_UI::config()->canvasvar_LocationMarker.get(); location_range_color = ARDOUR_UI::config()->canvasvar_LocationRange.get(); @@ -480,6 +481,7 @@ Editor::Editor () route_display_model->signal_row_deleted().connect (mem_fun (*this, &Editor::route_list_delete)); route_display_model->signal_row_changed().connect (mem_fun (*this, &Editor::route_list_change)); + route_display_model->signal_rows_reordered().connect (mem_fun (*this, &Editor::track_list_reorder)); route_list_display.signal_button_press_event().connect (mem_fun (*this, &Editor::route_list_display_button_press), false); @@ -739,6 +741,7 @@ Editor::Editor () ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll)); Config->ParameterChanged.connect (mem_fun (*this, &Editor::parameter_changed)); + Route::SyncOrderKeys.connect (mem_fun (*this, &Editor::sync_order_keys)); constructed = true; instant_save (); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index fcaed5b513..0b7e0c4a4c 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1494,10 +1494,12 @@ class Editor : public PublicEditor add (text); add (visible); add (tv); + add (route); } Gtk::TreeModelColumn text; Gtk::TreeModelColumn visible; Gtk::TreeModelColumn tv; + Gtk::TreeModelColumn > route; }; RouteDisplayModelColumns route_display_columns; @@ -1508,14 +1510,18 @@ class Editor : public PublicEditor Gtk::ScrolledWindow route_list_scroller; Gtk::Menu* route_list_menu; + void sync_order_keys (); + bool ignore_route_order_sync; + bool route_list_display_button_press (GdkEventButton*); bool route_list_selection_filter (const Glib::RefPtr& model, const Gtk::TreeModel::Path& path, bool yn); void route_list_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&); void route_list_delete (const Gtk::TreeModel::Path&); + void track_list_reorder (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order); + void initial_route_list_display (); void redisplay_route_list(); - void route_list_reordered (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* what); bool ignore_route_list_reorder; bool no_route_list_redisplay; diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc index e2ed6f7191..44806f0263 100644 --- a/gtk2_ardour/editor_route_list.cc +++ b/gtk2_ardour/editor_route_list.cc @@ -49,6 +49,10 @@ Editor::handle_new_route (Session::RouteList& routes) TreeModel::Row parent; TreeModel::Row row; + ignore_route_list_reorder = true; + ignore_route_order_sync = true; + no_route_list_redisplay = true; + for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { boost::shared_ptr route = (*x); @@ -58,58 +62,33 @@ Editor::handle_new_route (Session::RouteList& routes) tv = new AudioTimeAxisView (*this, *session, route, track_canvas); -#if 0 - if (route_display_model->children().size() == 0) { - - /* set up basic entries */ - - TreeModel::Row row; - - row = *(route_display_model->append()); // path = "0" - row[route_display_columns.text] = _("Busses"); - row[route_display_columns.tv] = 0; - row = *(route_display_model->append()); // path = "1" - row[route_display_columns.text] = _("Tracks"); - row[route_display_columns.tv] = 0; - - } - - if (dynamic_cast(route.get()) != 0) { - TreeModel::iterator iter = route_display_model->get_iter ("1"); // audio tracks - parent = *iter; - } else { - TreeModel::iterator iter = route_display_model->get_iter ("0"); // busses - parent = *iter; - } - - - row = *(route_display_model->append (parent.children())); -#else row = *(route_display_model->append ()); -#endif + row[route_display_columns.route] = route; row[route_display_columns.text] = route->name(); row[route_display_columns.visible] = tv->marked_for_display(); row[route_display_columns.tv] = tv; - + track_views.push_back (tv); - ignore_route_list_reorder = true; - if ((atv = dynamic_cast (tv)) != 0) { /* added a new fresh one at the end */ if (atv->route()->order_key(N_("editor")) == -1) { atv->route()->set_order_key (N_("editor"), route_display_model->children().size()-1); } } - - ignore_route_list_reorder = false; - + + tv->set_old_order_key (route_display_model->children().size() - 1); route->gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes)); - tv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), tv)); } + ignore_route_list_reorder = false; + ignore_route_order_sync = false; + no_route_list_redisplay = false; + + redisplay_route_list (); + if (show_editor_mixer_when_tracks_arrive) { show_editor_mixer (true); } @@ -127,7 +106,6 @@ Editor::handle_gui_changes (const string & what, void *src) } } - void Editor::remove_route (TimeAxisView *tv) { @@ -216,9 +194,29 @@ Editor::show_track_in_display (TimeAxisView& tv) } void -Editor::route_list_reordered (const TreeModel::Path& path,const TreeModel::iterator& iter,int* what) +Editor::sync_order_keys () { - redisplay_route_list (); + vector neworder; + TreeModel::Children rows = route_display_model->children(); + TreeModel::Children::iterator ri; + + if (ignore_route_order_sync || !session || (session->state_of_the_state() & Session::Loading) || rows.empty()) { + return; + } + + for (ri = rows.begin(); ri != rows.end(); ++ri) { + neworder.push_back (0); + } + + for (ri = rows.begin(); ri != rows.end(); ++ri) { + TimeAxisView* tv = (*ri)[route_display_columns.tv]; + boost::shared_ptr route = (*ri)[route_display_columns.route]; + neworder[route->order_key (X_("signal"))] = tv->old_order_key (); + } + + ignore_route_list_reorder = true; + route_display_model->reorder (neworder); + ignore_route_list_reorder = false; } void @@ -229,14 +227,19 @@ Editor::redisplay_route_list () uint32_t position; uint32_t order; int n; - + if (no_route_list_redisplay) { return; } + if (session && (rows.size() > session->nroutes())) { + /* temporary condition during a drag-n-drop */ + return; + } + for (n = 0, order = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) { TimeAxisView *tv = (*i)[route_display_columns.tv]; - AudioTimeAxisView* at; + boost::shared_ptr route = (*i)[route_display_columns.route]; if (tv == 0) { // just a "title" row @@ -249,12 +252,11 @@ Editor::redisplay_route_list () to tracks. */ - if ((at = dynamic_cast (tv)) != 0) { - at->route()->set_order_key (N_("editor"), order); - ++order; - } + route->set_order_key (N_("editor"), order); } + tv->set_old_order_key (order); + bool visible = (*i)[route_display_columns.visible]; if (visible) { @@ -264,8 +266,8 @@ Editor::redisplay_route_list () tv->hide (); } - n++; - + ++order; + ++n; } full_canvas_height = position; @@ -275,6 +277,12 @@ Editor::redisplay_route_list () cursor_group->raise_to_top (); reset_scrolling_region (); + + if (Config->get_sync_all_route_ordering() && !ignore_route_list_reorder) { + ignore_route_order_sync = true; + Route::SyncOrderKeys (); // EMIT SIGNAL + ignore_route_order_sync = false; + } } void @@ -510,6 +518,13 @@ Editor::initial_route_list_display () redisplay_route_list (); } +void +Editor::track_list_reorder (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter, int* new_order) +{ + session->set_remote_control_ids(); + redisplay_route_list (); +} + void Editor::route_list_change (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter) { diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc index 90fea321de..cc94dc155f 100644 --- a/gtk2_ardour/keyboard.cc +++ b/gtk2_ardour/keyboard.cc @@ -48,13 +48,14 @@ uint32_t Keyboard::Shift = GDK_SHIFT_MASK; uint32_t Keyboard::Alt = GDK_MOD1_MASK; uint32_t Keyboard::Meta; -Keyboard* Keyboard::_the_keyboard = 0; +Keyboard* Keyboard::_the_keyboard = 0; +Gtk::Window* Keyboard::current_window = 0; +bool Keyboard::_some_magic_widget_has_focus = false; /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */ GdkModifierType Keyboard::RelevantModifierKeyMask; -bool Keyboard::_some_magic_widget_has_focus = false; void Keyboard::magic_widget_grab_focus () @@ -199,6 +200,13 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) } + if (event->type == GDK_KEY_RELEASE && event->keyval == GDK_w && modifier_state_equals (event->state, Control)) { + if (current_window) { + current_window->hide (); + current_window = 0; + } + } + return false; } @@ -211,6 +219,7 @@ Keyboard::key_is_down (uint32_t keyval) bool Keyboard::enter_window (GdkEventCrossing *ev, Gtk::Window* win) { + current_window = win; return false; } @@ -236,6 +245,7 @@ Keyboard::leave_window (GdkEventCrossing *ev, Gtk::Window* win) cerr << "clearing current target\n"; } state.clear (); + current_window = 0; } return false; diff --git a/gtk2_ardour/keyboard.h b/gtk2_ardour/keyboard.h index c1351bfaf6..a4904f770b 100644 --- a/gtk2_ardour/keyboard.h +++ b/gtk2_ardour/keyboard.h @@ -105,6 +105,7 @@ class Keyboard : public sigc::trackable, Stateful static guint delete_but; static guint delete_mod; static guint snap_mod; + static Gtk::Window* current_window; static gint _snooper (GtkWidget*, GdkEventKey*, gpointer); gint snooper (GtkWidget*, GdkEventKey*); diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index b40ace3766..8648574600 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -58,15 +59,21 @@ using namespace std; using PBD::atoi; + Mixer_UI::Mixer_UI () : Window (Gtk::WINDOW_TOPLEVEL) { + session = 0; _strip_width = Wide; track_menu = 0; mix_group_context_menu = 0; no_track_list_redisplay = false; in_group_row_change = false; _visible = false; + ignore_route_reorder = false; + ignore_sync = false; + + Route::SyncOrderKeys.connect (mem_fun (*this, &Mixer_UI::sync_order_keys)); scroller_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK); scroller_base.set_name ("MixerWindow"); @@ -92,6 +99,7 @@ Mixer_UI::Mixer_UI () track_model->signal_row_deleted().connect (mem_fun (*this, &Mixer_UI::track_list_delete)); track_model->signal_row_changed().connect (mem_fun (*this, &Mixer_UI::track_list_change)); + track_model->signal_rows_reordered().connect (mem_fun (*this, &Mixer_UI::track_list_reorder)); CellRendererToggle* track_list_visible_cell = dynamic_cast(track_display.get_column_cell_renderer (1)); track_list_visible_cell->property_activatable() = true; @@ -277,7 +285,7 @@ Mixer_UI::add_strip (Session::RouteList& routes) strip = new MixerStrip (*this, *session, route); strips.push_back (strip); - + if (strip->width_owner() != strip) { strip->set_width (_strip_width, this); } @@ -292,11 +300,14 @@ Mixer_UI::add_strip (Session::RouteList& routes) row[track_columns.visible] = strip->marked_for_display(); row[track_columns.route] = route; row[track_columns.strip] = strip; - + + strip->set_old_order_key (track_model->children().size() - 1); + no_track_list_redisplay = false; redisplay_track_list (); route->name_changed.connect (bind (mem_fun(*this, &Mixer_UI::strip_name_changed), strip)); + strip->GoingAway.connect (bind (mem_fun(*this, &Mixer_UI::remove_strip), strip)); strip->signal_button_release_event().connect (bind (mem_fun(*this, &Mixer_UI::strip_button_release_event), strip)); @@ -324,6 +335,33 @@ Mixer_UI::remove_strip (MixerStrip* strip) } } +void +Mixer_UI::sync_order_keys () +{ + vector neworder; + TreeModel::Children rows = track_model->children(); + TreeModel::Children::iterator ri; + + if (ignore_sync || !session || (session->state_of_the_state() & Session::Loading) || rows.empty()) { + return; + } + + for (ri = rows.begin(); ri != rows.end(); ++ri) { + neworder.push_back (0); + } + + for (ri = rows.begin(); ri != rows.end(); ++ri) { + boost::shared_ptr route = (*ri)[track_columns.route]; + MixerStrip* strip = (*ri)[track_columns.strip]; + neworder[route->order_key (X_("signal"))] = strip->old_order_key (); + } + + ignore_route_reorder = true; + track_model->reorder (neworder); + ignore_route_reorder = false; +} + + void Mixer_UI::follow_strip_selection () { @@ -359,7 +397,6 @@ Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip) void Mixer_UI::connect_to_session (Session* sess) { - session = sess; XMLNode* node = ARDOUR_UI::instance()->mixer_settings(); @@ -568,6 +605,13 @@ Mixer_UI::hide_all_audiotracks () set_all_audio_visibility (1, false); } +void +Mixer_UI::track_list_reorder (const TreeModel::Path& path, const TreeModel::iterator& iter, int* new_order) +{ + session->set_remote_control_ids(); + redisplay_track_list (); +} + void Mixer_UI::track_list_change (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter) { @@ -602,10 +646,17 @@ Mixer_UI::redisplay_track_list () } bool visible = (*i)[track_columns.visible]; + + boost::shared_ptr route = (*i)[track_columns.route]; if (visible) { strip->set_marked_for_display (true); - strip->route()->set_order_key (N_("signal"), order); + + if (!ignore_route_reorder) { + strip->route()->set_order_key (N_("signal"), order); + } + + strip->set_old_order_key (order); if (strip->packed()) { @@ -638,6 +689,12 @@ Mixer_UI::redisplay_track_list () } } } + + if (Config->get_sync_all_route_ordering() && !ignore_route_reorder) { + ignore_sync = true; + Route::SyncOrderKeys (); // EMIT SIGNAL + ignore_sync = false; + } } struct SignalOrderRouteSorter { diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h index caecf243f5..6f5c382876 100644 --- a/gtk2_ardour/mixer_ui.h +++ b/gtk2_ardour/mixer_ui.h @@ -148,6 +148,7 @@ class Mixer_UI : public Gtk::Window void track_list_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&); void track_list_delete (const Gtk::TreeModel::Path&); + void track_list_reorder (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order); void initial_track_display (); void show_track_list_menu (); @@ -234,6 +235,10 @@ class Mixer_UI : public Gtk::Window Width _strip_width; + void sync_order_keys (); + bool ignore_route_reorder; + bool ignore_sync; + static const int32_t default_width = 478; static const int32_t default_height = 765; }; diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc index d43c15bbae..862b22850c 100644 --- a/gtk2_ardour/option_editor.cc +++ b/gtk2_ardour/option_editor.cc @@ -42,6 +42,7 @@ #include "editing.h" #include "option_editor.h" #include "midi_port_dialog.h" +#include "gui_thread.h" #include "i18n.h" @@ -55,7 +56,7 @@ using namespace std; static vector positional_sync_strings; OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui) - : Dialog ("options editor"), + : ArdourDialog ("options editor", false), ui (uip), editor (ed), mixer (mixui), @@ -74,6 +75,7 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui) smpte_offset_clock (X_("smpteoffset"), false, X_("SMPTEOffsetClock"), true, true), smpte_offset_negative_button (_("SMPTE offset is negative")), + synced_timecode_button (_("Timecode source is sample-clock synced")), /* MIDI */ @@ -145,6 +147,9 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui) set_session (0); show_all_children(); + + Config->map_parameters (mem_fun (*this, &OptionEditor::parameter_changed)); + Config->ParameterChanged.connect (mem_fun (*this, &OptionEditor::parameter_changed)); } void @@ -326,8 +331,10 @@ OptionEditor::setup_sync_options () hbox->pack_start (smpte_offset_negative_button, false, false); sync_packer.pack_start (*hbox, false, false); + sync_packer.pack_start (synced_timecode_button, false, false); smpte_offset_negative_button.signal_clicked().connect (mem_fun(*this, &OptionEditor::smpte_offset_negative_clicked)); + synced_timecode_button.signal_toggled().connect (mem_fun(*this, &OptionEditor::synced_timecode_toggled)); } void @@ -338,6 +345,17 @@ OptionEditor::smpte_offset_negative_clicked () } } +void +OptionEditor::synced_timecode_toggled () +{ + bool x; + + if ((x = synced_timecode_button.get_active()) != Config->get_timecode_source_is_synced()) { + Config->set_timecode_source_is_synced (x); + Config->save_state(); + } +} + void OptionEditor::smpte_offset_chosen() { @@ -1161,3 +1179,14 @@ OptionEditor::fixup_combo_size (Gtk::ComboBoxText& combo, vector& string set_size_request_to_display_given_text (combo, maxstring.c_str(), 10 + FUDGE, 10); } +void +OptionEditor::parameter_changed (const char* parameter_name) +{ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &OptionEditor::parameter_changed), parameter_name)); + +#define PARAM_IS(x) (!strcmp (parameter_name, (x))) + + if (PARAM_IS ("timecode-source-is-synced")) { + synced_timecode_button.set_active (Config->get_timecode_source_is_synced()); + } +} diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h index a234f1d752..3881687d5c 100644 --- a/gtk2_ardour/option_editor.h +++ b/gtk2_ardour/option_editor.h @@ -45,7 +45,7 @@ class IOSelector; class GainMeter; class PannerUI; -class OptionEditor : public Gtk::Dialog +class OptionEditor : public ArdourDialog { public: OptionEditor (ARDOUR_UI&, PublicEditor&, Mixer_UI&); @@ -66,6 +66,7 @@ class OptionEditor : public Gtk::Dialog gint wm_close (GdkEventAny *); bool focus_out_event_handler (GdkEventFocus*, void (OptionEditor::*pmf)()); + void parameter_changed (const char* name); /* paths */ @@ -96,11 +97,13 @@ class OptionEditor : public Gtk::Dialog Gtk::ComboBoxText slave_type_combo; AudioClock smpte_offset_clock; Gtk::CheckButton smpte_offset_negative_button; + Gtk::CheckButton synced_timecode_button; void setup_sync_options (); void smpte_offset_chosen (); void smpte_offset_negative_clicked (); + void synced_timecode_toggled (); /* MIDI */ diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index d3e2ac5159..7ee00fc8ee 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -144,6 +144,7 @@ CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", false CONFIG_VARIABLE (bool, periodic_safety_backups, "periodic-safety-backups", true) CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-backup-interval", 120) CONFIG_VARIABLE (float, automation_interval, "automation-interval", 50) +CONFIG_VARIABLE (bool, sync_all_route_ordering, "sync-all-route-ordering", true) /* denormal management */ diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 8f3cae0db1..a0f5319576 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -243,6 +243,9 @@ class Route : public IO uint32_t remote_control_id () const; sigc::signal RemoteControlIDChanged; + void sync_order_keys (); + static sigc::signal SyncOrderKeys; + protected: friend class Session; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 302799565a..2dde901708 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1717,6 +1717,7 @@ class Session : public PBD::StatefulDestructible XMLNode& get_control_protocol_state (); void set_history_depth (uint32_t depth); + void sync_order_keys (); }; } // namespace ARDOUR diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 10f9978f96..7a4f1e1cbf 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -48,7 +48,8 @@ gint AudioEngine::m_meter_exit; static void ardour_jack_error (const char* msg) { - error << "JACK: " << msg << endmsg; + // throw JACK errors away - they cause visual clutter + // error << "JACK: " << msg << endmsg; } AudioEngine::AudioEngine (string client_name) diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 84712851eb..2cd4cb70cf 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -49,7 +49,7 @@ using namespace ARDOUR; using namespace PBD; uint32_t Route::order_key_cnt = 0; - +sigc::signal Route::SyncOrderKeys; Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type) : IO (sess, name, input_min, input_max, output_min, output_max, default_type), @@ -157,9 +157,34 @@ void Route::set_order_key (const char* name, long n) { order_keys[strdup(name)] = n; + + if (Config->get_sync_all_route_ordering()) { + for (OrderKeys::iterator x = order_keys.begin(); x != order_keys.end(); ++x) { + x->second = n; + } + } + _session.set_dirty (); } +void +Route::sync_order_keys () +{ + uint32_t key; + + if (order_keys.empty()) { + return; + } + + OrderKeys::iterator x = order_keys.begin(); + key = x->second; + ++x; + + for (; x != order_keys.end(); ++x) { + x->second = key; + } +} + void Route::inc_gain (gain_t fraction, void *src) { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 901e1d182b..3b54e324d3 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -4052,3 +4052,19 @@ Session::compute_initial_length () return _engine.frame_rate() * 60 * 5; } +void +Session::sync_order_keys () +{ + if (!Config->get_sync_all_route_ordering()) { + /* leave order keys as they are */ + return; + } + + boost::shared_ptr r = routes.reader (); + + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + (*i)->sync_order_keys (); + } + + Route::SyncOrderKeys (); // EMIT SIGNAL +} diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index c21bae5cc9..77c5c2c002 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -3290,6 +3290,8 @@ Session::config_changed (const char* parameter_name) setup_fpu (); } else if (PARAM_IS ("history-depth")) { set_history_depth (Config->get_history_depth()); + } else if (PARAM_IS ("sync-all-route-ordering")) { + sync_order_keys (); } set_dirty ();