diff options
Diffstat (limited to 'gtk2_ardour')
39 files changed, 1385 insertions, 1642 deletions
diff --git a/gtk2_ardour/actions.cc b/gtk2_ardour/actions.cc index 3b0133b535..cefaeeb4cf 100644 --- a/gtk2_ardour/actions.cc +++ b/gtk2_ardour/actions.cc @@ -58,8 +58,8 @@ vector<RefPtr<Gtk::Action> > ActionManager::playlist_selection_sensitive_actions vector<RefPtr<Gtk::Action> > ActionManager::mouse_edit_point_requires_canvas_actions; vector<RefPtr<Gtk::Action> > ActionManager::range_sensitive_actions; -vector<RefPtr<Gtk::Action> > ActionManager::jack_sensitive_actions; -vector<RefPtr<Gtk::Action> > ActionManager::jack_opposite_sensitive_actions; +vector<RefPtr<Gtk::Action> > ActionManager::engine_sensitive_actions; +vector<RefPtr<Gtk::Action> > ActionManager::engine_opposite_sensitive_actions; vector<RefPtr<Gtk::Action> > ActionManager::transport_sensitive_actions; vector<RefPtr<Gtk::Action> > ActionManager::edit_point_in_region_sensitive_actions; diff --git a/gtk2_ardour/actions.h b/gtk2_ardour/actions.h index 20c0532636..f3fba51de5 100644 --- a/gtk2_ardour/actions.h +++ b/gtk2_ardour/actions.h @@ -46,8 +46,8 @@ namespace ActionManager { extern std::vector<Glib::RefPtr<Gtk::Action> > range_sensitive_actions; extern std::vector<Glib::RefPtr<Gtk::Action> > transport_sensitive_actions; - extern std::vector<Glib::RefPtr<Gtk::Action> > jack_sensitive_actions; - extern std::vector<Glib::RefPtr<Gtk::Action> > jack_opposite_sensitive_actions; + extern std::vector<Glib::RefPtr<Gtk::Action> > engine_sensitive_actions; + extern std::vector<Glib::RefPtr<Gtk::Action> > engine_opposite_sensitive_actions; extern std::vector<Glib::RefPtr<Gtk::Action> > edit_point_in_region_sensitive_actions; extern void map_some_state (const char* group, const char* action, bool (ARDOUR::RCConfiguration::*get)() const); diff --git a/gtk2_ardour/ardev_common.sh.in b/gtk2_ardour/ardev_common.sh.in index 897bfcf7c2..850a83c954 100644 --- a/gtk2_ardour/ardev_common.sh.in +++ b/gtk2_ardour/ardev_common.sh.in @@ -17,6 +17,7 @@ export ARDOUR_DATA_PATH=$TOP:$TOP/build:$TOP/gtk2_ardour:$TOP/build/gtk2_ardour: export ARDOUR_MIDIMAPS_PATH=$TOP/midi_maps:. export ARDOUR_MCP_PATH=$TOP/mcp:. export ARDOUR_EXPORT_FORMATS_PATH=$TOP/export:. +export ARDOUR_BACKEND_PATH=$libs/backends/jack # # even though we set the above variables, ardour requires that these diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index 15f1bde1b6..197b484698 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -495,27 +495,27 @@ <menuitem action='show-marker-lines'/> </menu> <menu name='JACK' action='JACK'> - <menuitem action='JACKDisconnect'/> - <menuitem action='JACKReconnect'/> + <menuitem action='EngineDisconnect'/> + <menuitem action='EngineReconnect'/> <menu name='Latency' action='Latency'> - <menuitem action='JACKLatency32'/> - <menuitem action='JACKLatency64'/> - <menuitem action='JACKLatency128'/> - <menuitem action='JACKLatency256'/> - <menuitem action='JACKLatency512'/> - <menuitem action='JACKLatency1024'/> - <menuitem action='JACKLatency2048'/> - <menuitem action='JACKLatency4096'/> - <menuitem action='JACKLatency8192'/> + <menuitem action='EngineLatency32'/> + <menuitem action='EngineLatency64'/> + <menuitem action='EngineLatency128'/> + <menuitem action='EngineLatency256'/> + <menuitem action='EngineLatency512'/> + <menuitem action='EngineLatency1024'/> + <menuitem action='EngineLatency2048'/> + <menuitem action='EngineLatency4096'/> + <menuitem action='EngineLatency8192'/> </menu> </menu> <menu action = 'WindowMenu'> + <menuitem action='toggle-audio-midi-setup'/> + <separator/> <menuitem action='toggle-mixer'/> <menuitem action='toggle-meterbridge'/> <menuitem action='toggle-editor-mixer'/> - <separator/> - <menuitem action='toggle-inspector'/> <menuitem action='toggle-locations'/> <menuitem action='toggle-key-editor'/> diff --git a/gtk2_ardour/ardour3_fonts.rc.in b/gtk2_ardour/ardour3_fonts.rc.in index 7d017df4b3..8d09ff0f1d 100644 --- a/gtk2_ardour/ardour3_fonts.rc.in +++ b/gtk2_ardour/ardour3_fonts.rc.in @@ -50,6 +50,11 @@ style "large_bold_text" font_name = "bold @FONT_LARGE@" } +style "big_text" +{ + font_name = "@FONT_BIG@" +} + style "bigger_mono_text" { font_name = "@MONOSPACE@ @FONT_BIGGER@" diff --git a/gtk2_ardour/ardour3_styles.rc.in b/gtk2_ardour/ardour3_styles.rc.in index e3978d063a..8b5b5e4c99 100644 --- a/gtk2_ardour/ardour3_styles.rc.in +++ b/gtk2_ardour/ardour3_styles.rc.in @@ -1011,3 +1011,8 @@ style "meter_strip_sep" = "default" { bg[NORMAL] = { 0.0, 0.0, 0.0 } } + +style "settings_notebook" = "big_text" +{ + +} diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 33f5a5099e..307eb925b3 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -62,9 +62,8 @@ #include "gtkmm2ext/popup.h" #include "gtkmm2ext/window_title.h" -#include "midi++/manager.h" - #include "ardour/ardour.h" +#include "ardour/audio_backend.h" #include "ardour/audioengine.h" #include "ardour/audiofilesource.h" #include "ardour/automation_watch.h" @@ -162,10 +161,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) /* start of private members */ , _startup (0) - , engine (0) , nsm (0) , _was_dirty (false) , _mixer_on_top (false) + , first_time_engine_run (true) /* transport */ @@ -207,7 +206,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , _status_bar_visibility (X_("status-bar")) , _feedback_exists (false) - + , _audio_midi_setup (0) { Gtkmm2ext::init(localedir); @@ -218,12 +217,12 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) } ui_config = new UIConfiguration(); + _audio_midi_setup = new EngineControl; editor = 0; mixer = 0; meterbridge = 0; editor = 0; - engine = 0; _session_is_new = false; session_selector_window = 0; last_key_press_time = 0; @@ -271,6 +270,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this)); + /* handle Audio/MIDI setup when session requires it */ + + ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1)); + /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */ ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2)); @@ -369,6 +372,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) _process_thread->init (); DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets)); + + attach_to_engine (); } GlobalPortMatrixWindow* @@ -380,42 +385,146 @@ ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type) return new GlobalPortMatrixWindow (_session, type); } -int -ARDOUR_UI::create_engine () +void +ARDOUR_UI::attach_to_engine () { - // this gets called every time by new_session() + AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context()); + AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context()); + AudioEngine::instance()->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context()); - if (engine) { - return 0; + AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); + + ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports); + + /* if there is only one audio/midi backend, and it does not require setup, get our use of it underway + * right here (we need to know the client name and potential session ID + * to do this, which is why this is here, rather than in, say, + * ARDOUR::init(). + */ + + if (!AudioEngine::instance()->setup_required()) { + const AudioBackendInfo* backend = AudioEngine::instance()->available_backends().front(); + AudioEngine::instance()->set_backend (backend->name, ARDOUR_COMMAND_LINE::backend_client_name, ARDOUR_COMMAND_LINE::backend_session_uuid); + AudioEngine::instance()->start (); } +} - loading_message (_("Starting audio engine")); +void +ARDOUR_UI::engine_stopped () +{ + ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped) + ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false); + ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true); +} - try { - engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name, ARDOUR_COMMAND_LINE::jack_session_uuid); +void +ARDOUR_UI::engine_running () +{ + if (first_time_engine_run) { + post_engine(); + first_time_engine_run = false; + } + + ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, true); + ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, false); - } catch (...) { + Glib::RefPtr<Action> action; + const char* action_name = 0; - return -1; + switch (AudioEngine::instance()->samples_per_cycle()) { + case 32: + action_name = X_("JACKLatency32"); + break; + case 64: + action_name = X_("JACKLatency64"); + break; + case 128: + action_name = X_("JACKLatency128"); + break; + case 512: + action_name = X_("JACKLatency512"); + break; + case 1024: + action_name = X_("JACKLatency1024"); + break; + case 2048: + action_name = X_("JACKLatency2048"); + break; + case 4096: + action_name = X_("JACKLatency4096"); + break; + case 8192: + action_name = X_("JACKLatency8192"); + break; + default: + /* XXX can we do anything useful ? */ + break; } - 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->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context()); + if (action_name) { - engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); + action = ActionManager::get_action (X_("JACK"), action_name); - ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports); + if (action) { + Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action); + ract->set_active (); + } - post_engine (); + update_disk_space (); + update_cpu_load (); + update_sample_rate (AudioEngine::instance()->sample_rate()); + update_timecode_format (); + } +} - return 0; +void +ARDOUR_UI::engine_halted (const char* reason, bool free_reason) +{ + 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::engine_sensitive_actions, false); + ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true); + + update_sample_rate (0); + + 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 = string_compose (_("\ +JACK has either been shutdown or it\n\ +disconnected %1 because %1\n\ +was not fast enough. Try to restart\n\ +JACK, reconnect and save the session."), PROGRAM_NAME); + } + + MessageDialog msg (*editor, msgstr); + pop_back_splash (msg); + msg.set_keep_above (true); + msg.run (); + + if (free_reason) { + free (const_cast<char*> (reason)); + } } void ARDOUR_UI::post_engine () { - /* Things to be done once we create the AudioEngine + /* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine */ ARDOUR::init_post_engine (); @@ -481,25 +590,9 @@ ARDOUR_UI::post_engine () Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1); #endif - update_disk_space (); - update_cpu_load (); - update_sample_rate (engine->frame_rate()); - update_timecode_format (); - Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context()); boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1)); Config->map_parameters (pc); - - /* now start and maybe save state */ - - if (do_engine_start () == 0) { - if (_session && _session_is_new) { - /* we need to retain initial visual - settings for a new session - */ - _session->save_state (""); - } - } } ARDOUR_UI::~ARDOUR_UI () @@ -685,6 +778,7 @@ ARDOUR_UI::startup () { Application* app = Application::instance (); char *nsm_url; + app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish)); app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load)); @@ -779,7 +873,7 @@ ARDOUR_UI::check_memory_locking () XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning")); - if (engine->is_realtime() && memory_warning_node == 0) { + if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) { struct rlimit limits; int64_t ram; @@ -919,7 +1013,8 @@ If you still wish to quit, please use the\n\n\ _session = 0; } - engine->stop (true); + halt_connection.disconnect (); + AudioEngine::instance()->stop (); quit (); } @@ -1048,22 +1143,28 @@ ARDOUR_UI::update_sample_rate (framecnt_t) ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored) - if (!engine->connected()) { + if (!AudioEngine::instance()->connected()) { - snprintf (buf, sizeof (buf), "%s", _("disconnected")); + snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"red\">none</span>")); } else { - framecnt_t rate = engine->frame_rate(); + framecnt_t rate = AudioEngine::instance()->sample_rate(); - if (fmod (rate, 1000.0) != 0.0) { - snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"), - (float) rate/1000.0f, - (engine->frames_per_cycle() / (float) rate) * 1000.0f); + if (rate == 0) { + /* no sample rate available */ + snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"red\">none</span>")); } else { - snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"), - rate/1000, - (engine->frames_per_cycle() / (float) rate) * 1000.0f); + + if (fmod (rate, 1000.0) != 0.0) { + snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"), + (float) rate / 1000.0f, + (AudioEngine::instance()->usecs_per_cycle() / 1000.0f)); + } else { + snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"), + rate/1000, + (AudioEngine::instance()->usecs_per_cycle() / 1000.0f)); + } } } @@ -1133,7 +1234,7 @@ ARDOUR_UI::update_cpu_load () should also be changed. */ - float const c = engine->get_cpu_load (); + float const c = AudioEngine::instance()->get_cpu_load (); snprintf (buf, sizeof (buf), _("DSP: <span foreground=\"%s\">%5.1f%%</span>"), c >= 90 ? X_("red") : X_("green"), c); cpu_load_label.set_markup (buf); } @@ -1187,6 +1288,11 @@ ARDOUR_UI::update_disk_space() char buf[64]; framecnt_t fr = _session->frame_rate(); + if (fr == 0) { + /* skip update - no SR available */ + return; + } + if (!opt_frames) { /* Available space is unknown */ snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>")); @@ -1449,20 +1555,16 @@ ARDOUR_UI::open_recent_session () bool ARDOUR_UI::check_audioengine () { - if (engine) { - if (!engine->connected()) { - MessageDialog msg (string_compose ( - _("%1 is not connected to JACK\n" - "You cannot open or close sessions in this condition"), - PROGRAM_NAME)); - pop_back_splash (msg); - msg.run (); - return false; - } - return true; - } else { + if (!AudioEngine::instance()->connected()) { + MessageDialog msg (string_compose ( + _("%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 (); return false; } + return true; } void @@ -1668,10 +1770,17 @@ ARDOUR_UI::transport_goto_wallclock () time (&now); localtime_r (&now, &tmnow); + + int frame_rate = _session->frame_rate(); + + if (frame_rate == 0) { + /* no frame rate available */ + return; + } - frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate()); - frames += tmnow.tm_min * (60 * _session->frame_rate()); - frames += tmnow.tm_sec * _session->frame_rate(); + frames = tmnow.tm_hour * (60 * 60 * frame_rate); + frames += tmnow.tm_min * (60 * frame_rate); + frames += tmnow.tm_sec * frame_rate; _session->request_locate (frames, _session->transport_rolling ()); @@ -2032,127 +2141,6 @@ ARDOUR_UI::map_transport_state () } void -ARDOUR_UI::engine_stopped () -{ - ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped) - ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false); - ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true); -} - -void -ARDOUR_UI::engine_running () -{ - ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running) - ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true); - ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false); - - Glib::RefPtr<Action> action; - const char* action_name = 0; - - switch (engine->frames_per_cycle()) { - case 32: - action_name = X_("JACKLatency32"); - break; - case 64: - action_name = X_("JACKLatency64"); - break; - case 128: - action_name = X_("JACKLatency128"); - break; - case 512: - action_name = X_("JACKLatency512"); - break; - case 1024: - action_name = X_("JACKLatency1024"); - break; - case 2048: - action_name = X_("JACKLatency2048"); - break; - case 4096: - action_name = X_("JACKLatency4096"); - break; - case 8192: - action_name = X_("JACKLatency8192"); - break; - default: - /* XXX can we do anything useful ? */ - break; - } - - if (action_name) { - - action = ActionManager::get_action (X_("JACK"), action_name); - - if (action) { - Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action); - ract->set_active (); - } - } -} - -void -ARDOUR_UI::engine_halted (const char* reason, bool free_reason) -{ - 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); - - 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 = string_compose (_("\ -JACK has either been shutdown or it\n\ -disconnected %1 because %1\n\ -was not fast enough. Try to restart\n\ -JACK, reconnect and save the session."), PROGRAM_NAME); - } - - MessageDialog msg (*editor, msgstr); - pop_back_splash (msg); - msg.set_keep_above (true); - msg.run (); - - if (free_reason) { - free (const_cast<char*> (reason)); - } -} - -int32_t -ARDOUR_UI::do_engine_start () -{ - try { - engine->start(); - } - - catch (...) { - engine->stop (); - error << _("Unable to start the session running") - << endmsg; - unload_session (); - return -2; - } - - return 0; -} - -void ARDOUR_UI::update_clocks () { if (!editor || !editor->dragging_playhead()) { @@ -2702,10 +2690,6 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri } } - if (create_engine ()) { - break; - } - if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { if (likely_new && !nsm) { @@ -2801,25 +2785,23 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, int unload_status; int retval = -1; - session_loaded = false; - - if (!check_audioengine()) { - return -2; + if (_session) { + unload_status = unload_session (); + + if (unload_status < 0) { + goto out; + } else if (unload_status > 0) { + retval = 0; + goto out; + } } - unload_status = unload_session (); - - if (unload_status < 0) { - goto out; - } else if (unload_status > 0) { - retval = 0; - goto out; - } + session_loaded = false; loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME)); try { - new_session = new Session (*engine, path, snap_name, 0, mix_template); + new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template); } /* this one is special */ @@ -2920,12 +2902,7 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, Session *new_session; int x; - if (!check_audioengine()) { - return -1; - } - session_loaded = false; - x = unload_session (); if (x < 0) { @@ -2937,7 +2914,7 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, _session_is_new = true; try { - new_session = new Session (*engine, path, snap_name, &bus_profile); + new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile); } catch (...) { @@ -3832,31 +3809,33 @@ audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual return 1; } - void -ARDOUR_UI::disconnect_from_jack () +ARDOUR_UI::disconnect_from_engine () { - if (engine) { - if (engine->disconnect_from_jack ()) { - MessageDialog msg (*editor, _("Could not disconnect from JACK")); - msg.run (); - } - - update_sample_rate (0); + /* drop connection to AudioEngine::Halted so that we don't act + * as if the engine unexpectedly shut down + */ + halt_connection.disconnect (); + + if (AudioEngine::instance()->stop ()) { + MessageDialog msg (*editor, _("Could not disconnect from JACK")); + msg.run (); + } else { + AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); } + + update_sample_rate (0); } void -ARDOUR_UI::reconnect_to_jack () +ARDOUR_UI::reconnect_to_engine () { - if (engine) { - if (engine->reconnect_to_jack ()) { - MessageDialog msg (*editor, _("Could not reconnect to JACK")); - msg.run (); - } - - update_sample_rate (0); + if (AudioEngine::instance()->start ()) { + MessageDialog msg (*editor, _("Could not reconnect to JACK")); + msg.run (); } + + update_sample_rate (0); } void @@ -4163,3 +4142,49 @@ ARDOUR_UI::reset_route_peak_display (Route* route) reset_peak_display (); } } + +void +ARDOUR_UI::toggle_audio_midi_setup () +{ + Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-audio-midi-setup")); + if (!act) { + return; + } + + Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act); + + if (tact->get_active()) { + launch_audio_midi_setup (); + } else { + _audio_midi_setup->hide (); + } +} + +void +ARDOUR_UI::launch_audio_midi_setup () +{ + if (!_audio_midi_setup) { + _audio_midi_setup = new EngineControl (); + } + + _audio_midi_setup->present (); +} + +int +ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate) +{ + launch_audio_midi_setup (); + + _audio_midi_setup->set_desired_sample_rate (desired_sample_rate); + + int r = _audio_midi_setup->run (); + + switch (r) { + case Gtk::RESPONSE_OK: + return 0; + case Gtk::RESPONSE_APPLY: + return 0; + default: + return -1; + } +} diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 15413b5ac9..64309c7e38 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -90,6 +90,7 @@ class BigClockWindow; class BundleManager; class ButtonJoiner; class ConnectionEditor; +class EngineControl; class KeyEditor; class LocationUIWindow; class MainClock; @@ -264,7 +265,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr session_add_midi_route (false); }*/ - int create_engine (); + void attach_to_engine (); void post_engine (); gint exit_on_main_window_close (GdkEventAny *); @@ -302,19 +303,18 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void reenable_hide_loop_punch_ruler_if_appropriate (); void toggle_auto_return (); void toggle_click (); - + void toggle_audio_midi_setup (); void toggle_session_auto_loop (); - void toggle_rc_options_window (); void toggle_session_options_window (); private: ArdourStartup* _startup; - ARDOUR::AudioEngine *engine; Gtk::Tooltips _tooltips; NSM_Client *nsm; bool _was_dirty; bool _mixer_on_top; + bool first_time_engine_run; void goto_editor_window (); void goto_mixer_window (); @@ -667,9 +667,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr int pending_state_dialog (); int sr_mismatch_dialog (ARDOUR::framecnt_t, ARDOUR::framecnt_t); - void disconnect_from_jack (); - void reconnect_to_jack (); - void set_jack_buffer_size (ARDOUR::pframes_t); + void disconnect_from_engine (); + void reconnect_to_engine (); + void set_engine_buffer_size (ARDOUR::pframes_t); Gtk::MenuItem* jack_disconnect_item; Gtk::MenuItem* jack_reconnect_item; @@ -710,6 +710,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void loading_message (const std::string& msg); PBD::ScopedConnectionList forever_connections; + PBD::ScopedConnection halt_connection; void step_edit_status_change (bool); @@ -746,6 +747,10 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr std::string _announce_string; void check_announcements (); + + EngineControl* _audio_midi_setup; + void launch_audio_midi_setup (); + int do_audio_midi_setup (uint32_t); }; #endif /* __ardour_gui_h__ */ diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index bca762569f..a0d61afdff 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -165,10 +165,6 @@ ARDOUR_UI::set_session (Session *s) _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context()); _session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ()); -#ifdef HAVE_JACK_SESSION - engine->JackSessionEvent.connect (*_session, MISSING_INVALIDATOR, boost::bind (&Session::jack_session_event, _session, _1), gui_context()); -#endif - /* Clocks are on by default after we are connected to a session, so show that here. */ @@ -283,7 +279,10 @@ ARDOUR_UI::unload_session (bool hide_stuff) rec_button.set_sensitive (false); WM::Manager::instance().set_session ((ARDOUR::Session*) 0); - ARDOUR_UI::instance()->video_timeline->close_session(); + + if (ARDOUR_UI::instance()->video_timeline) { + ARDOUR_UI::instance()->video_timeline->close_session(); + } stop_blinking (); stop_clocking (); diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 6c050578ec..53ea7c02de 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -183,38 +183,38 @@ ARDOUR_UI::install_actions () ActionManager::write_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act); - /* JACK actions for controlling ... JACK */ - - Glib::RefPtr<ActionGroup> jack_actions = ActionGroup::create (X_("JACK")); - ActionManager::register_action (jack_actions, X_("JACK"), _("JACK")); - ActionManager::register_action (jack_actions, X_("Latency"), _("Latency")); - - act = ActionManager::register_action (jack_actions, X_("JACKReconnect"), _("Reconnect"), sigc::mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::reconnect_to_jack)); - ActionManager::jack_opposite_sensitive_actions.push_back (act); - - act = ActionManager::register_action (jack_actions, X_("JACKDisconnect"), _("Disconnect"), sigc::mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::disconnect_from_jack)); - ActionManager::jack_sensitive_actions.push_back (act); - - RadioAction::Group jack_latency_group; - - act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency32"), X_("32"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (pframes_t) 32)); - ActionManager::jack_sensitive_actions.push_back (act); - act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency64"), X_("64"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (pframes_t) 64)); - ActionManager::jack_sensitive_actions.push_back (act); - act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency128"), X_("128"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (pframes_t) 128)); - ActionManager::jack_sensitive_actions.push_back (act); - act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency256"), X_("256"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (pframes_t) 256)); - ActionManager::jack_sensitive_actions.push_back (act); - act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency512"), X_("512"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (pframes_t) 512)); - ActionManager::jack_sensitive_actions.push_back (act); - act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency1024"), X_("1024"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (pframes_t) 1024)); - ActionManager::jack_sensitive_actions.push_back (act); - act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency2048"), X_("2048"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (pframes_t) 2048)); - ActionManager::jack_sensitive_actions.push_back (act); - act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency4096"), X_("4096"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (pframes_t) 4096)); - ActionManager::jack_sensitive_actions.push_back (act); - act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency8192"), X_("8192"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (pframes_t) 8192)); - ActionManager::jack_sensitive_actions.push_back (act); + /* AudioEngine actions */ + + Glib::RefPtr<ActionGroup> engine_actions = ActionGroup::create (X_("Audio")); + ActionManager::register_action (engine_actions, X_("JACK"), _("JACK")); + ActionManager::register_action (engine_actions, X_("Latency"), _("Latency")); + + act = ActionManager::register_action (engine_actions, X_("EngineReconnect"), _("Reconnect"), sigc::mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::reconnect_to_engine)); + ActionManager::engine_opposite_sensitive_actions.push_back (act); + + act = ActionManager::register_action (engine_actions, X_("EngineDisconnect"), _("Disconnect"), sigc::mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::disconnect_from_engine)); + ActionManager::engine_sensitive_actions.push_back (act); + + RadioAction::Group latency_group; + + act = ActionManager::register_radio_action (engine_actions, latency_group, X_("EngineLatency32"), X_("32"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_engine_buffer_size), (pframes_t) 32)); + ActionManager::engine_sensitive_actions.push_back (act); + act = ActionManager::register_radio_action (engine_actions, latency_group, X_("EngineLatency64"), X_("64"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_engine_buffer_size), (pframes_t) 64)); + ActionManager::engine_sensitive_actions.push_back (act); + act = ActionManager::register_radio_action (engine_actions, latency_group, X_("EngineLatency128"), X_("128"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_engine_buffer_size), (pframes_t) 128)); + ActionManager::engine_sensitive_actions.push_back (act); + act = ActionManager::register_radio_action (engine_actions, latency_group, X_("EngineLatency256"), X_("256"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_engine_buffer_size), (pframes_t) 256)); + ActionManager::engine_sensitive_actions.push_back (act); + act = ActionManager::register_radio_action (engine_actions, latency_group, X_("EngineLatency512"), X_("512"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_engine_buffer_size), (pframes_t) 512)); + ActionManager::engine_sensitive_actions.push_back (act); + act = ActionManager::register_radio_action (engine_actions, latency_group, X_("EngineLatency1024"), X_("1024"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_engine_buffer_size), (pframes_t) 1024)); + ActionManager::engine_sensitive_actions.push_back (act); + act = ActionManager::register_radio_action (engine_actions, latency_group, X_("EngineLatency2048"), X_("2048"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_engine_buffer_size), (pframes_t) 2048)); + ActionManager::engine_sensitive_actions.push_back (act); + act = ActionManager::register_radio_action (engine_actions, latency_group, X_("EngineLatency4096"), X_("4096"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_engine_buffer_size), (pframes_t) 4096)); + ActionManager::engine_sensitive_actions.push_back (act); + act = ActionManager::register_radio_action (engine_actions, latency_group, X_("EngineLatency8192"), X_("8192"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::set_engine_buffer_size), (pframes_t) 8192)); + ActionManager::engine_sensitive_actions.push_back (act); /* these actions are intended to be shared across all windows */ @@ -230,6 +230,7 @@ ARDOUR_UI::install_actions () ActionManager::register_toggle_action (common_actions, X_("toggle-mixer"), S_("Window|Mixer"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_mixer_window)); ActionManager::register_action (common_actions, X_("toggle-editor-mixer"), _("Toggle Editor+Mixer"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_editor_mixer)); ActionManager::register_toggle_action (common_actions, X_("toggle-meterbridge"), S_("Window|Meterbridge"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_meterbridge)); + ActionManager::register_toggle_action (common_actions, X_("toggle-audio-midi-setup"), S_("Window|Audio/MIDI Setup"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_audio_midi_setup)); act = ActionManager::register_action (common_actions, X_("NewMIDITracer"), _("MIDI Tracer"), sigc::mem_fun(*this, &ARDOUR_UI::new_midi_tracer_window)); ActionManager::session_sensitive_actions.push_back (act); @@ -421,7 +422,7 @@ ARDOUR_UI::install_actions () ActionManager::add_action_group (shuttle_actions); ActionManager::add_action_group (option_actions); - ActionManager::add_action_group (jack_actions); + ActionManager::add_action_group (engine_actions); ActionManager::add_action_group (transport_actions); ActionManager::add_action_group (main_actions); ActionManager::add_action_group (main_menu_actions); @@ -430,38 +431,38 @@ ARDOUR_UI::install_actions () } void -ARDOUR_UI::set_jack_buffer_size (pframes_t nframes) +ARDOUR_UI::set_engine_buffer_size (pframes_t nframes) { Glib::RefPtr<Action> action; const char* action_name = 0; switch (nframes) { case 32: - action_name = X_("JACKLatency32"); + action_name = X_("EngineLatency32"); break; case 64: - action_name = X_("JACKLatency64"); + action_name = X_("EngineLatency64"); break; case 128: - action_name = X_("JACKLatency128"); + action_name = X_("EngineLatency128"); break; case 256: - action_name = X_("JACKLatency256"); + action_name = X_("EngineLatency256"); break; case 512: - action_name = X_("JACKLatency512"); + action_name = X_("EngineLatency512"); break; case 1024: - action_name = X_("JACKLatency1024"); + action_name = X_("EngineLatency1024"); break; case 2048: - action_name = X_("JACKLatency2048"); + action_name = X_("EngineLatency2048"); break; case 4096: - action_name = X_("JACKLatency4096"); + action_name = X_("EngineLatency4096"); break; case 8192: - action_name = X_("JACKLatency8192"); + action_name = X_("EngineLatency8192"); break; default: /* XXX can we do anything useful ? */ @@ -476,7 +477,7 @@ ARDOUR_UI::set_jack_buffer_size (pframes_t nframes) Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action); if (ract && ract->get_active()) { - engine->request_buffer_size (nframes); + AudioEngine::instance()->request_buffer_size (nframes); update_sample_rate (0); } } @@ -647,11 +648,10 @@ ARDOUR_UI::save_ardour_state () window_node->add_child_nocopy (*tearoff_node); Config->add_extra_xml (*window_node); + Config->add_extra_xml (_audio_midi_setup->get_state()); - if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) { - Config->add_extra_xml (_startup->engine_control()->get_state()); - } Config->save_state(); + if (ui_config->dirty()) { ui_config->save_state (); } diff --git a/gtk2_ardour/arval b/gtk2_ardour/arval index 6503bc1ede..2209dcb110 100755 --- a/gtk2_ardour/arval +++ b/gtk2_ardour/arval @@ -10,5 +10,6 @@ LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH export ARDOUR_RUNNING_UNDER_VALGRIND=TRUE exec valgrind --tool=memcheck \ $VALGRIND_OPTIONS \ + --track-origins=yes \ --suppressions=`dirname "$0"`/../tools/valgrind.supp \ $TOP/$EXECUTABLE --novst "$@" diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 300e317a38..a0418892e7 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1258,7 +1258,8 @@ Editor::set_session (Session *t) /* These signals can all be emitted by a non-GUI thread. Therefore the handlers for them must not attempt to directly interact with the GUI, - but use Gtkmm2ext::UI::instance()->call_slot(); + but use PBD::Signal<T>::connect() which accepts an event loop + ("context") where the handler will be asked to run. */ _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context()); diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index b083e851c5..9c65892ebd 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -2371,9 +2371,14 @@ CursorDrag::fake_locate (framepos_t t) Session* s = _editor->session (); if (s->timecode_transmission_suspended ()) { framepos_t const f = _editor->playhead_cursor->current_frame; + /* This is asynchronous so it will be sent "now" + */ s->send_mmc_locate (f); - s->send_full_time_code (f); - s->send_song_position_pointer (f); + /* These are synchronous and will be sent during the next + process cycle + */ + s->queue_full_time_code (); + s->queue_song_position_pointer (); } show_verbose_cursor_time (t); diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc index 05cd9a661e..873498f6ec 100644 --- a/gtk2_ardour/engine_dialog.cc +++ b/gtk2_ardour/engine_dialog.cc @@ -17,6 +17,7 @@ */ +#include <exception> #include <vector> #include <cmath> #include <fstream> @@ -24,37 +25,26 @@ #include <boost/scoped_ptr.hpp> -#include <glibmm.h> #include <gtkmm/messagedialog.h> -#include "pbd/epa.h" +#include "pbd/error.h" #include "pbd/xml++.h" -#ifdef __APPLE__ -#include <CoreAudio/CoreAudio.h> -#include <CoreFoundation/CFString.h> -#include <sys/param.h> -#include <mach-o/dyld.h> -#elif !defined(__FreeBSD__) -#include <alsa/asoundlib.h> -#endif - -#include <jack/jack.h> - #include <gtkmm/stock.h> +#include <gtkmm/notebook.h> #include <gtkmm2ext/utils.h> +#include "ardour/audio_backend.h" +#include "ardour/audioengine.h" +#include "ardour/mtdm.h" #include "ardour/rc_configuration.h" +#include "ardour/types.h" #include "pbd/convert.h" #include "pbd/error.h" -#include "pbd/pathscanner.h" - -#ifdef __APPLE -#include <CFBundle.h> -#endif #include "engine_dialog.h" +#include "gui_thread.h" #include "i18n.h" using namespace std; @@ -64,322 +54,236 @@ using namespace PBD; using namespace Glib; EngineControl::EngineControl () - : periods_adjustment (2, 2, 16, 1, 2), - periods_spinner (periods_adjustment), - ports_adjustment (128, 8, 1024, 1, 16), - ports_spinner (ports_adjustment), - input_latency_adjustment (0, 0, 99999, 1), - input_latency (input_latency_adjustment), - output_latency_adjustment (0, 0, 99999, 1), - output_latency (output_latency_adjustment), - realtime_button (_("Realtime")), - no_memory_lock_button (_("Do not lock memory")), - unlock_memory_button (_("Unlock memory")), - soft_mode_button (_("No zombies")), - monitor_button (_("Provide monitor ports")), - force16bit_button (_("Force 16 bit")), - hw_monitor_button (_("H/W monitoring")), - hw_meter_button (_("H/W metering")), - verbose_output_button (_("Verbose output")), - start_button (_("Start")), - stop_button (_("Stop")), -#ifdef __APPLE___ - basic_packer (5, 2), - options_packer (4, 2), - device_packer (4, 2) -#else - basic_packer (8, 2), - options_packer (14, 2), - device_packer (6, 2) -#endif + : ArdourDialog (_("Audio/MIDI Setup")) + , input_latency_adjustment (0, 0, 99999, 1) + , input_latency (input_latency_adjustment) + , output_latency_adjustment (0, 0, 99999, 1) + , output_latency (output_latency_adjustment) + , input_channels_adjustment (0, 0, 256, 1) + , input_channels (input_channels_adjustment) + , output_channels_adjustment (0, 0, 256, 1) + , output_channels (output_channels_adjustment) + , ports_adjustment (128, 8, 1024, 1, 16) + , ports_spinner (ports_adjustment) + , control_app_button (_("Launch Control App")) + , lm_measure_button (_("Measure latency")) + , lm_use_button (_("Use results")) + , lm_table (5, 2) + , basic_packer (9, 3) + , ignore_changes (0) + , _desired_sample_rate (0) +{ + build_notebook (); + + get_vbox()->set_border_width (12); + get_vbox()->pack_start (notebook); + + control_app_button.signal_clicked().connect (mem_fun (*this, &EngineControl::control_app_button_clicked)); + manage_control_app_sensitivity (); + + add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); + add_button (Gtk::Stock::APPLY, Gtk::RESPONSE_APPLY); + + /* Pick up any existing audio setup configuration, if appropriate */ + + XMLNode* audio_setup = ARDOUR::Config->extra_xml ("AudioMIDISetup"); + + /* push a change as if we altered the backend */ + backend_changed (); + + if (audio_setup) { + set_state (*audio_setup); + } + + ARDOUR::AudioEngine::instance()->Stopped.connect (*this, MISSING_INVALIDATOR, boost::bind (&EngineControl::disable_latency_tab, this), gui_context()); + + if (!ARDOUR::AudioEngine::instance()->connected()) { + ARDOUR::AudioEngine::instance()->Running.connect (*this, MISSING_INVALIDATOR, boost::bind (&EngineControl::enable_latency_tab, this), gui_context()); + disable_latency_tab (); + } else { + enable_latency_tab (); + } +} + +void +EngineControl::on_response (int response_id) +{ + ArdourDialog::on_response (response_id); + + switch (response_id) { + case RESPONSE_APPLY: + push_state_to_backend (true); + break; + case RESPONSE_OK: + push_state_to_backend (true); + hide (); + break; + default: + hide (); + } +} + +void +EngineControl::build_notebook () { using namespace Notebook_Helpers; Label* label; vector<string> strings; int row = 0; - _used = false; - - strings.push_back (_("8000Hz")); - strings.push_back (_("22050Hz")); - strings.push_back (_("44100Hz")); - strings.push_back (_("48000Hz")); - strings.push_back (_("88200Hz")); - strings.push_back (_("96000Hz")); - strings.push_back (_("192000Hz")); - set_popdown_strings (sample_rate_combo, strings); - sample_rate_combo.set_active_text ("48000Hz"); - - strings.clear (); - strings.push_back ("32"); - strings.push_back ("64"); - strings.push_back ("128"); - strings.push_back ("256"); - strings.push_back ("512"); - strings.push_back ("1024"); - strings.push_back ("2048"); - strings.push_back ("4096"); - strings.push_back ("8192"); - set_popdown_strings (period_size_combo, strings); - period_size_combo.set_active_text ("1024"); - - strings.clear (); - strings.push_back (_("None")); - strings.push_back (_("Triangular")); - strings.push_back (_("Rectangular")); - strings.push_back (_("Shaped")); - set_popdown_strings (dither_mode_combo, strings); - dither_mode_combo.set_active_text (_("None")); - - /* basic parameters */ + vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends(); + for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) { + strings.push_back ((*b)->name); + } + + set_popdown_strings (backend_combo, strings); + backend_combo.set_active_text (strings.front()); basic_packer.set_spacings (6); + basic_packer.set_border_width (12); + basic_packer.set_homogeneous (true); - strings.clear (); -#ifdef __APPLE__ - strings.push_back (X_("CoreAudio")); -#else -#ifndef __FreeBSD__ - strings.push_back (X_("ALSA")); -#endif - strings.push_back (X_("OSS")); - strings.push_back (X_("FreeBoB")); - strings.push_back (X_("FFADO")); -#endif - strings.push_back (X_("NetJACK")); - strings.push_back (X_("Dummy")); - set_popdown_strings (driver_combo, strings); - driver_combo.set_active_text (strings.front()); + row = 0; - driver_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::driver_changed)); - driver_changed (); - - strings.clear (); - strings.push_back (_("Playback/recording on 1 device")); - strings.push_back (_("Playback/recording on 2 devices")); - strings.push_back (_("Playback only")); - strings.push_back (_("Recording only")); - set_popdown_strings (audio_mode_combo, strings); - audio_mode_combo.set_active_text (strings.front()); - - audio_mode_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::audio_mode_changed)); - audio_mode_changed (); - - strings.clear (); - strings.push_back (_("None")); -#ifdef __APPLE__ - strings.push_back (_("coremidi")); -#else - strings.push_back (_("seq")); - strings.push_back (_("raw")); -#endif - set_popdown_strings (midi_driver_combo, strings); - midi_driver_combo.set_active_text (strings.front ()); + AttachOptions xopt = AttachOptions (FILL|EXPAND); - row = 0; + label = manage (left_aligned_label (_("Audio System:"))); + basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0); + basic_packer.attach (backend_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0); + row++; label = manage (left_aligned_label (_("Driver:"))); - basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - basic_packer.attach (driver_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); + basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0); + basic_packer.attach (driver_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0); row++; - label = manage (left_aligned_label (_("Audio Interface:"))); - basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - basic_packer.attach (interface_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); + label = manage (left_aligned_label (_("Device:"))); + basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0); + basic_packer.attach (device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0); row++; label = manage (left_aligned_label (_("Sample rate:"))); - basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); + basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0); + basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0); row++; - label = manage (left_aligned_label (_("Buffer size:"))); - basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - basic_packer.attach (period_size_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - row++; -#if !defined(__APPLE__) && !defined(__FreeBSD__) - label = manage (left_aligned_label (_("Number of buffers:"))); - basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - basic_packer.attach (periods_spinner, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - periods_spinner.set_value (2); + label = manage (left_aligned_label (_("Buffer size:"))); + basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0); + basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0); + buffer_size_duration_label.set_alignment (0.0); /* left-align */ + basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, xopt, (AttachOptions) 0); row++; -#endif - label = manage (left_aligned_label (_("Approximate latency:"))); - basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - basic_packer.attach (latency_label, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - row++; - sample_rate_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::redisplay_latency)); - periods_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &EngineControl::redisplay_latency)); - period_size_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::redisplay_latency)); - redisplay_latency(); - row++; - /* no audio mode with CoreAudio, its duplex or nuthin' */ + label = manage (left_aligned_label (_("Input Channels:"))); + basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0); + basic_packer.attach (input_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0); + ++row; -#if !defined(__APPLE__) && !defined(__FreeBSD__) - label = manage (left_aligned_label (_("Audio mode:"))); - basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - basic_packer.attach (audio_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - row++; -#endif - interface_combo.set_size_request (250, -1); - input_device_combo.set_size_request (250, -1); - output_device_combo.set_size_request (250, -1); + label = manage (left_aligned_label (_("Output Channels:"))); + basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0); + basic_packer.attach (output_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0); + ++row; - /* - if (engine_running()) { - start_button.set_sensitive (false); - } else { - stop_button.set_sensitive (false); - } + label = manage (left_aligned_label (_("Hardware input latency:"))); + basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0); + basic_packer.attach (input_latency, 1, 2, row, row+1, xopt, (AttachOptions) 0); + label = manage (left_aligned_label (_("samples"))); + basic_packer.attach (*label, 2, 3, row, row+1, xopt, (AttachOptions) 0); + ++row; - start_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::start_engine)); - stop_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::start_engine)); - */ + label = manage (left_aligned_label (_("Hardware output latency:"))); + basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0); + basic_packer.attach (output_latency, 1, 2, row, row+1, xopt, (AttachOptions) 0); + label = manage (left_aligned_label (_("samples"))); + basic_packer.attach (*label, 2, 3, row, row+1, xopt, (AttachOptions) 0); + ++row; - button_box.pack_start (start_button, false, false); - button_box.pack_start (stop_button, false, false); + basic_hbox.pack_start (basic_packer, false, false); + basic_vbox.pack_start (basic_hbox, false, false); - // basic_packer.attach (button_box, 0, 2, 8, 9, FILL|EXPAND, (AttachOptions) 0); + Gtk::HBox* hpacker = manage (new HBox); + hpacker->set_border_width (12); + hpacker->pack_start (control_app_button, false, false); + hpacker->show (); + control_app_button.show(); + basic_vbox.pack_start (*hpacker); - /* options */ + midi_packer.set_border_width (12); - options_packer.set_spacings (6); + /* latency measurement tab */ + + lm_title.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Latency Measurement Tool"))); + row = 0; + lm_table.set_row_spacings (12); - options_packer.attach (realtime_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; + lm_table.attach (lm_title, 0, 2, row, row+1, xopt, (AttachOptions) 0); + row++; - realtime_button.set_active (true); + lm_preamble.set_width_chars (60); + lm_preamble.set_line_wrap (true); + lm_preamble.set_markup (_("1. <span weight=\"bold\">Turn down the volume on your hardware to a very low level.</span>\n\n\ +2. Connect the two channels that you select below using either a cable or (less ideally) a speaker \ +and microphone.\n\n\ +3. Once the channels are connected, click the \"Measure latency\" button.\n\n\ +4. When satisfied with the results, click the \"Use results\" button.")); -#if PROVIDE_TOO_MANY_OPTIONS + lm_table.attach (lm_preamble, 0, 2, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0); + row++; -#if !defined(__APPLE__) && !defined(__FreeBSD__) - options_packer.attach (no_memory_lock_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; - options_packer.attach (unlock_memory_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; - options_packer.attach (soft_mode_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; - options_packer.attach (monitor_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; - options_packer.attach (force16bit_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; - options_packer.attach (hw_monitor_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; - options_packer.attach (hw_meter_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; - options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; -#else - options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; -#endif - - strings.clear (); - strings.push_back (_("Ignore")); - strings.push_back ("500 msec"); - strings.push_back ("1 sec"); - strings.push_back ("2 sec"); - strings.push_back ("10 sec"); - set_popdown_strings (timeout_combo, strings); - timeout_combo.set_active_text (strings.front ()); - - label = manage (new Label (_("Client timeout"))); - label->set_alignment (1.0, 0.5); - options_packer.attach (timeout_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0)); - options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); + label = manage (new Label (_("Output channel"))); + lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0); + lm_table.attach (lm_output_channel_combo, 1, 2, row, row+1, xopt, (AttachOptions) 0); ++row; -#endif /* PROVIDE_TOO_MANY_OPTIONS */ - label = manage (left_aligned_label (_("Number of ports:"))); - options_packer.attach (ports_spinner, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0)); - options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); + label = manage (new Label (_("Input channel"))); + lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0); + lm_table.attach (lm_input_channel_combo, 1, 2, row, row+1, xopt, (AttachOptions) 0); ++row; - label = manage (left_aligned_label (_("MIDI driver:"))); - options_packer.attach (midi_driver_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0)); - options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; + xopt = AttachOptions(0); -#if !defined(__APPLE__) && !defined(__FreeBSD__) - label = manage (left_aligned_label (_("Dither:"))); - options_packer.attach (dither_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0)); - options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); + lm_measure_button.signal_toggled().connect (sigc::mem_fun (*this, &EngineControl::latency_button_toggled)); + lm_use_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::use_latency_button_clicked)); + lm_use_button.set_sensitive (false); + + lm_table.attach (lm_measure_button, 0, 2, row, row+1, xopt, (AttachOptions) 0); ++row; -#endif - - find_jack_servers (server_strings); - - if (server_strings.empty()) { - fatal << _("No JACK server found anywhere on this system. Please install JACK and restart") << endmsg; - /*NOTREACHED*/ - } - - set_popdown_strings (serverpath_combo, server_strings); - serverpath_combo.set_active_text (server_strings.front()); - - if (server_strings.size() > 1) { - label = manage (left_aligned_label (_("Server:"))); - options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - options_packer.attach (serverpath_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0); - ++row; - } - - /* device settings */ - - device_packer.set_spacings (6); - row = 0; - -#if !defined(__APPLE__) && !defined(__FreeBSD__) - label = manage (left_aligned_label (_("Input device:"))); - device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0); - device_packer.attach (input_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0); + lm_table.attach (lm_results, 0, 2, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0); ++row; - label = manage (left_aligned_label (_("Output device:"))); - device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0); - device_packer.attach (output_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0); - ++row; -#endif - label = manage (left_aligned_label (_("Hardware input latency:"))); - device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0); - device_packer.attach (input_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0); - label = manage (left_aligned_label (_("samples"))); - device_packer.attach (*label, 2, 3, row, row+1, FILL|EXPAND, (AttachOptions) 0); - ++row; - label = manage (left_aligned_label (_("Hardware output latency:"))); - device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0); - device_packer.attach (output_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0); - label = manage (left_aligned_label (_("samples"))); - device_packer.attach (*label, 2, 3, row, row+1, FILL|EXPAND, (AttachOptions) 0); + lm_table.attach (lm_use_button, 0, 2, row, row+1, xopt, (AttachOptions) 0); ++row; - basic_hbox.pack_start (basic_packer, false, false); - options_hbox.pack_start (options_packer, false, false); + lm_results.set_markup ("<i>No measurement results yet</i>"); - device_packer.set_border_width (12); - options_packer.set_border_width (12); - basic_packer.set_border_width (12); + lm_vbox.pack_start (lm_table, false, false); - notebook.pages().push_back (TabElem (basic_hbox, _("Device"))); - notebook.pages().push_back (TabElem (options_hbox, _("Options"))); - notebook.pages().push_back (TabElem (device_packer, _("Advanced"))); + /* pack it all up */ + + notebook.pages().push_back (TabElem (basic_vbox, _("Audio"))); + notebook.pages().push_back (TabElem (midi_hbox, _("MIDI"))); + notebook.pages().push_back (TabElem (lm_vbox, _("Latency"))); notebook.set_border_width (12); - set_border_width (12); - pack_start (notebook); + notebook.set_tab_pos (POS_RIGHT); + notebook.show_all (); - /* Pick up any existing audio setup configuration, if appropriate */ + notebook.set_name ("SettingsNotebook"); - XMLNode* audio_setup = ARDOUR::Config->extra_xml ("AudioSetup"); - - if (audio_setup) { - set_state (*audio_setup); - } + /* Connect to signals */ + + backend_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::backend_changed)); + driver_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::driver_changed)); + sample_rate_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::sample_rate_changed)); + buffer_size_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::buffer_size_changed)); + input_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &input_channels)); + output_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &output_channels)); + device_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::device_changed)); } EngineControl::~EngineControl () @@ -388,555 +292,543 @@ EngineControl::~EngineControl () } void -EngineControl::build_command_line (vector<string>& cmd) +EngineControl::disable_latency_tab () { - string str; - string driver; - bool using_alsa = false; - bool using_coreaudio = false; - bool using_dummy = false; - bool using_ffado = false; - - /* first, path to jackd */ - - cmd.push_back (serverpath_combo.get_active_text ()); - - /* now jackd arguments */ - - str = timeout_combo.get_active_text (); - - if (str != _("Ignore")) { - - double secs = 0; - uint32_t msecs; - secs = atof (str); - msecs = (uint32_t) floor (secs * 1000.0); + vector<string> empty; + set_popdown_strings (lm_output_channel_combo, empty); + set_popdown_strings (lm_input_channel_combo, empty); +} - if (msecs > 0) { - cmd.push_back ("-t"); - cmd.push_back (to_string (msecs, std::dec)); - } - } +void +EngineControl::enable_latency_tab () +{ + vector<string> outputs; + ARDOUR::AudioEngine::instance()->get_physical_outputs (ARDOUR::DataType::AUDIO, outputs); + set_popdown_strings (lm_output_channel_combo, outputs); + lm_output_channel_combo.set_active_text (outputs.front()); + + vector<string> inputs; + ARDOUR::AudioEngine::instance()->get_physical_inputs (ARDOUR::DataType::AUDIO, inputs); + set_popdown_strings (lm_input_channel_combo, inputs); + lm_input_channel_combo.set_active_text (inputs.front()); +} - if (no_memory_lock_button.get_active()) { - cmd.push_back ("-m"); /* no munlock */ +void +EngineControl::backend_changed () +{ + if (ignore_changes) { + return; } - cmd.push_back ("-p"); /* port max */ - cmd.push_back (to_string ((uint32_t) floor (ports_spinner.get_value()), std::dec)); + string backend_name = backend_combo.get_active_text(); + boost::shared_ptr<ARDOUR::AudioBackend> backend; - if (realtime_button.get_active()) { - cmd.push_back ("-R"); - } else { - cmd.push_back ("-r"); /* override jackd's default --realtime */ + if (!(backend = ARDOUR::AudioEngine::instance()->set_backend (backend_name, "ardour", ""))) { + /* eh? setting the backend failed... how ? */ + return; } - if (unlock_memory_button.get_active()) { - cmd.push_back ("-u"); + if (backend->requires_driver_selection()) { + vector<string> drivers = backend->enumerate_drivers(); + driver_combo.set_sensitive (true); + set_popdown_strings (driver_combo, drivers); + driver_combo.set_active_text (drivers.front()); + driver_changed (); + } else { + driver_combo.set_sensitive (false); + list_devices (); } + + maybe_display_saved_state (); +} - if (verbose_output_button.get_active()) { - cmd.push_back ("-v"); +bool +EngineControl::print_channel_count (Gtk::SpinButton* sb) +{ + uint32_t cnt = (uint32_t) sb->get_value(); + if (cnt == 0) { + sb->set_text (_("all available channels")); + } else { + char buf[32]; + snprintf (buf, sizeof (buf), "%d", cnt); + sb->set_text (buf); } + return true; +} - /* now add fixed arguments (not user-selectable) */ +void +EngineControl::list_devices () +{ + boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend(); + assert (backend); - cmd.push_back ("-T"); // temporary */ + /* now fill out devices, mark sample rates, buffer sizes insensitive */ + + vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_devices (); + + /* NOTE: Ardour currently does not display the "available" field of the + * returned devices. + * + * Doing so would require a different GUI widget than the combo + * box/popdown that we currently use, since it has no way to list + * items that are not selectable. Something more like a popup menu, + * which could have unselectable items, would be appropriate. + */ - /* setup coremidi before the driver, otherwise jack won't start */ + vector<string> available_devices; - if (midi_driver_combo.get_active_text() == _("coremidi")) { - cmd.push_back ("-X coremidi"); + for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) { + available_devices.push_back (i->name); } - /* next the driver */ - - cmd.push_back ("-d"); - - driver = driver_combo.get_active_text (); - - if (driver == X_("ALSA")) { - using_alsa = true; - cmd.push_back ("alsa"); - } else if (driver == X_("OSS")) { - cmd.push_back ("oss"); - } else if (driver == X_("CoreAudio")) { - using_coreaudio = true; - cmd.push_back ("coreaudio"); - } else if (driver == X_("NetJACK")) { - cmd.push_back ("netjack"); - } else if (driver == X_("FreeBoB")) { - cmd.push_back ("freebob"); - } else if (driver == X_("FFADO")) { - using_ffado = true; - cmd.push_back ("firewire"); - } else if ( driver == X_("Dummy")) { - using_dummy = true; - cmd.push_back ("dummy"); + set_popdown_strings (device_combo, available_devices); + + if (!available_devices.empty()) { + device_combo.set_active_text (available_devices.front()); } - /* driver arguments */ - - if (!using_coreaudio) { - str = audio_mode_combo.get_active_text(); - - if (str == _("Playback/recording on 1 device")) { - - /* relax */ - - } else if (str == _("Playback/recording on 2 devices")) { - - string input_device = get_device_name (driver, input_device_combo.get_active_text()); - string output_device = get_device_name (driver, output_device_combo.get_active_text()); - - if (input_device.empty() || output_device.empty()) { - cmd.clear (); - return; - } - - cmd.push_back ("-C"); - cmd.push_back (input_device); - - cmd.push_back ("-P"); - cmd.push_back (output_device); - - } else if (str == _("Playback only")) { - cmd.push_back ("-P"); - } else if (str == _("Recording only")) { - cmd.push_back ("-C"); - } - - if (!using_dummy) { - cmd.push_back ("-n"); - cmd.push_back (to_string ((uint32_t) floor (periods_spinner.get_value()), std::dec)); - } + device_changed (); +} + +void +EngineControl::driver_changed () +{ + if (ignore_changes) { + return; } - cmd.push_back ("-r"); - cmd.push_back (to_string (get_rate(), std::dec)); - - cmd.push_back ("-p"); - cmd.push_back (period_size_combo.get_active_text()); + boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend(); + assert (backend); - if (using_alsa || using_ffado || using_coreaudio) { + backend->set_driver (driver_combo.get_active_text()); + list_devices (); - double val = input_latency_adjustment.get_value(); - - if (val) { - cmd.push_back ("-I"); - cmd.push_back (to_string ((uint32_t) val, std::dec)); - } - - val = output_latency_adjustment.get_value(); + maybe_display_saved_state (); +} - if (val) { - cmd.push_back ("-O"); - cmd.push_back (to_string ((uint32_t) val, std::dec)); - } +void +EngineControl::device_changed () +{ + if (ignore_changes) { + return; } - if (using_alsa) { + boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend(); + assert (backend); + string device_name = device_combo.get_active_text (); + vector<string> s; - if (audio_mode_combo.get_active_text() != _("Playback/recording on 2 devices")) { - - string device = get_device_name (driver, interface_combo.get_active_text()); - if (device.empty()) { - cmd.clear (); - return; - } + /* don't allow programmatic change to sample_rate_combo to cause a + recursive call to this method. + */ + + ignore_changes++; - cmd.push_back ("-d"); - cmd.push_back (device); - } + /* sample rates */ + + string desired; - if (hw_meter_button.get_active()) { - cmd.push_back ("-M"); + vector<float> sr = backend->available_sample_rates (device_name); + for (vector<float>::const_iterator x = sr.begin(); x != sr.end(); ++x) { + char buf[32]; + if (fmod (*x, 1000.0f)) { + snprintf (buf, sizeof (buf), "%.1f kHz", (*x)/1000.0); + } else { + snprintf (buf, sizeof (buf), "%.0f kHz", (*x)/1000.0); } - - if (hw_monitor_button.get_active()) { - cmd.push_back ("-H"); + s.push_back (buf); + if (*x == _desired_sample_rate) { + desired = buf; } + } - str = dither_mode_combo.get_active_text(); + set_popdown_strings (sample_rate_combo, s); + if (desired.empty()) { + sample_rate_combo.set_active_text (s.front()); + } else { + sample_rate_combo.set_active_text (desired); + } - if (str == _("None")) { - } else if (str == _("Triangular")) { - cmd.push_back ("-z triangular"); - } else if (str == _("Rectangular")) { - cmd.push_back ("-z rectangular"); - } else if (str == _("Shaped")) { - cmd.push_back ("-z shaped"); - } + vector<uint32_t> bs = backend->available_buffer_sizes(device_name); + s.clear (); + for (vector<uint32_t>::const_iterator x = bs.begin(); x != bs.end(); ++x) { + char buf[32]; + /* Translators: "samples" is always plural here, so no + need for plural+singular forms. + */ + snprintf (buf, sizeof (buf), _("%u samples"), *x); + s.push_back (buf); + } - if (force16bit_button.get_active()) { - cmd.push_back ("-S"); - } + set_popdown_strings (buffer_size_combo, s); + buffer_size_combo.set_active_text (s.front()); + show_buffer_duration (); - if (soft_mode_button.get_active()) { - cmd.push_back ("-s"); - } + manage_control_app_sensitivity (); - str = midi_driver_combo.get_active_text (); + ignore_changes--; - if (str == _("seq")) { - cmd.push_back ("-X seq"); - } else if (str == _("raw")) { - cmd.push_back ("-X raw"); - } - } else if (using_coreaudio) { + maybe_display_saved_state (); +} -#ifdef __APPLE__ - // note: older versions of the CoreAudio JACK backend use -n instead of -d here +void +EngineControl::sample_rate_changed () +{ + if (ignore_changes) { + return; + } - string device = get_device_name (driver, interface_combo.get_active_text()); - if (device.empty()) { - cmd.clear (); - return; - } + /* reset the strings for buffer size to show the correct msec value + (reflecting the new sample rate). + */ - cmd.push_back ("-d"); - cmd.push_back (device); -#endif + show_buffer_duration (); + save_state (); - } } -bool -EngineControl::need_setup () +void +EngineControl::buffer_size_changed () { - return !engine_running(); + if (ignore_changes) { + return; + } + + show_buffer_duration (); + save_state (); } -bool -EngineControl::engine_running () +void +EngineControl::show_buffer_duration () { - EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa (); - boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa; - - /* revert all environment settings back to whatever they were when - * ardour started, because ardour's startup script may have reset - * something in ways that interfere with finding/starting JACK. - */ - if (global_epa) { - current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */ - global_epa->restore (); - } + /* buffer sizes - convert from just samples to samples + msecs for + * the displayed string + */ - jack_status_t status; - jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status); + string bs_text = buffer_size_combo.get_active_text (); + uint32_t samples = atoi (bs_text); /* will ignore trailing text */ + uint32_t rate = get_rate(); - if (status == 0) { - jack_client_close (c); - return true; - } - return false; + /* Translators: "msecs" is ALWAYS plural here, so we do not + need singular form as well. + */ + /* Developers: note the hard-coding of a double buffered model + in the (2 * samples) computation of latency. we always start + the audiobackend in this configuration. + */ + char buf[32]; + snprintf (buf, sizeof (buf), _("(%.1f msecs)"), (2 * samples) / (rate/1000.0)); + buffer_size_duration_label.set_text (buf); } -int -EngineControl::setup_engine () +EngineControl::State* +EngineControl::get_matching_state (const string& backend, + const string& driver, + const string& device) { - vector<string> args; - std::string cwd = "/tmp"; - - build_command_line (args); - - if (args.empty()) { - return 1; // try again + for (StateList::iterator i = states.begin(); i != states.end(); ++i) { + if ((*i).backend == backend && + (*i).driver == driver && + (*i).device == device) { + return &(*i); + } } + return 0; +} - std::string jackdrc_path = Glib::get_home_dir(); - jackdrc_path += "/.jackdrc"; - - ofstream jackdrc (jackdrc_path.c_str()); - if (!jackdrc) { - error << string_compose (_("cannot open JACK rc file %1 to store parameters"), jackdrc_path) << endmsg; - return -1; - } +EngineControl::State* +EngineControl::get_current_state () +{ + boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend(); - for (vector<string>::iterator i = args.begin(); i != args.end(); ++i) { - jackdrc << (*i) << ' '; + if (backend) { + return get_matching_state (backend_combo.get_active_text(), + (backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()), + device_combo.get_active_text()); } - jackdrc << endl; - jackdrc.close (); - - _used = true; - return 0; + return get_matching_state (backend_combo.get_active_text(), + string(), + device_combo.get_active_text()); } void -EngineControl::enumerate_devices (const string& driver) +EngineControl::save_state () { - /* note: case matters for the map keys */ - - if (driver == "CoreAudio") { -#ifdef __APPLE__ - devices[driver] = enumerate_coreaudio_devices (); -#endif - -#if !defined(__APPLE__) && !defined(__FreeBSD__) - } else if (driver == "ALSA") { - devices[driver] = enumerate_alsa_devices (); - } else if (driver == "FreeBOB") { - devices[driver] = enumerate_freebob_devices (); - } else if (driver == "FFADO") { - devices[driver] = enumerate_ffado_devices (); - } else if (driver == "OSS") { - devices[driver] = enumerate_oss_devices (); - } else if (driver == "Dummy") { - devices[driver] = enumerate_dummy_devices (); - } else if (driver == "NetJACK") { - devices[driver] = enumerate_netjack_devices (); + bool existing = true; + State* state = get_current_state (); + + if (!state) { + existing = false; + state = new State; + } + + state->backend = backend_combo.get_active_text (); + state->driver = driver_combo.get_active_text (); + state->device = device_combo.get_active_text (); + state->buffer_size = buffer_size_combo.get_active_text (); + state->sample_rate = sample_rate_combo.get_active_text (); + state->input_latency = (uint32_t) input_latency.get_value(); + state->output_latency = (uint32_t) output_latency.get_value(); + state->input_channels = (uint32_t) input_channels.get_value(); + state->output_channels = (uint32_t) output_channels.get_value(); + + if (!existing) { + states.push_back (*state); } -#else - } -#endif } -#ifdef __APPLE__ -static OSStatus -getDeviceUIDFromID( AudioDeviceID id, char *name, size_t nsize) +void +EngineControl::maybe_display_saved_state () { - UInt32 size = sizeof(CFStringRef); - CFStringRef UI; - OSStatus res = AudioDeviceGetProperty(id, 0, false, - kAudioDevicePropertyDeviceUID, &size, &UI); - if (res == noErr) - CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding()); - CFRelease(UI); - return res; -} + State* state = get_current_state (); -vector<string> -EngineControl::enumerate_coreaudio_devices () -{ - vector<string> devs; - - // Find out how many Core Audio devices are there, if any... - // (code snippet gently "borrowed" from St?hane Letz jackdmp;) - OSStatus err; - Boolean isWritable; - UInt32 outSize = sizeof(isWritable); - - backend_devs.clear (); - - err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, - &outSize, &isWritable); - if (err == noErr) { - // Calculate the number of device available... - int numCoreDevices = outSize / sizeof(AudioDeviceID); - // Make space for the devices we are about to get... - AudioDeviceID *coreDeviceIDs = new AudioDeviceID [numCoreDevices]; - err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, - &outSize, (void *) coreDeviceIDs); - if (err == noErr) { - // Look for the CoreAudio device name... - char coreDeviceName[256]; - UInt32 nameSize; - - for (int i = 0; i < numCoreDevices; i++) { - - nameSize = sizeof (coreDeviceName); - - /* enforce duplex devices only */ - - err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i], - 0, true, kAudioDevicePropertyStreams, - &outSize, &isWritable); - - if (err != noErr || outSize == 0) { - continue; - } - - err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i], - 0, false, kAudioDevicePropertyStreams, - &outSize, &isWritable); - - if (err != noErr || outSize == 0) { - continue; - } - - err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i], - 0, true, kAudioDevicePropertyDeviceName, - &outSize, &isWritable); - if (err == noErr) { - err = AudioDeviceGetProperty(coreDeviceIDs[i], - 0, true, kAudioDevicePropertyDeviceName, - &nameSize, (void *) coreDeviceName); - if (err == noErr) { - char drivername[128]; - - // this returns the unique id for the device - // that must be used on the commandline for jack - - if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, sizeof (drivername)) == noErr) { - devs.push_back (coreDeviceName); - backend_devs.push_back (drivername); - } - } - } - } + if (state) { + ignore_changes++; + if (!_desired_sample_rate) { + sample_rate_combo.set_active_text (state->sample_rate); } - delete [] coreDeviceIDs; + buffer_size_combo.set_active_text (state->buffer_size); + input_latency.set_value (state->input_latency); + output_latency.set_value (state->output_latency); + ignore_changes--; } +} + +XMLNode& +EngineControl::get_state () +{ + XMLNode* root = new XMLNode ("AudioMIDISetup"); + std::string path; - - if (devs.size() == 0) { - MessageDialog msg (string_compose (_("\ -You do not have any audio devices capable of\n\ -simultaneous playback and recording.\n\n\ -Please use Applications -> Utilities -> Audio MIDI Setup\n\ -to create an \"aggregrate\" device, or install a suitable\n\ -audio interface.\n\n\ -Please send email to Apple and ask them why new Macs\n\ -have no duplex audio device.\n\n\ -Alternatively, if you really want just playback\n\ -or recording but not both, start JACK before running\n\ -%1 and choose the relevant device then." - ), PROGRAM_NAME), - true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK); - msg.set_title (_("No suitable audio devices")); - msg.set_position (Gtk::WIN_POS_MOUSE); - msg.run (); - exit (1); + if (!states.empty()) { + XMLNode* state_nodes = new XMLNode ("EngineStates"); + + for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) { + + XMLNode* node = new XMLNode ("State"); + + node->add_property ("backend", (*i).backend); + node->add_property ("driver", (*i).driver); + node->add_property ("device", (*i).device); + node->add_property ("sample-rate", (*i).sample_rate); + node->add_property ("buffer-size", (*i).buffer_size); + node->add_property ("input-latency", (*i).input_latency); + node->add_property ("output-latency", (*i).output_latency); + node->add_property ("input-channels", (*i).input_channels); + node->add_property ("output-channels", (*i).output_channels); + node->add_property ("active", (*i).active ? "yes" : "no"); + + state_nodes->add_child_nocopy (*node); + } + + root->add_child_nocopy (*state_nodes); } - - return devs; + return *root; } -#else -#if !defined(__FreeBSD__) -vector<string> -EngineControl::enumerate_alsa_devices () +void +EngineControl::set_state (const XMLNode& root) { - vector<string> devs; + XMLNodeList clist, cclist; + XMLNodeConstIterator citer, cciter; + XMLNode* child; + XMLNode* grandchild; + XMLProperty* prop = NULL; - snd_ctl_t *handle; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - snd_ctl_card_info_alloca(&info); - snd_pcm_info_alloca(&pcminfo); - string devname; - int cardnum = -1; - int device = -1; + if (root.name() != "AudioMIDISetup") { + return; + } - backend_devs.clear (); + clist = root.children(); - while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) { + states.clear (); - devname = "hw:"; - devname += to_string (cardnum, std::dec); + for (citer = clist.begin(); citer != clist.end(); ++citer) { - if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 0) { + child = *citer; + + if (child->name() != "EngineStates") { + continue; + } - while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) { + cclist = child->children(); - snd_pcm_info_set_device (pcminfo, device); - snd_pcm_info_set_subdevice (pcminfo, 0); - snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK); + for (cciter = cclist.begin(); cciter != cclist.end(); ++cciter) { + State state; + + grandchild = *cciter; - if (snd_ctl_pcm_info (handle, pcminfo) >= 0) { - devs.push_back (snd_pcm_info_get_name (pcminfo)); - devname += ','; - devname += to_string (device, std::dec); - backend_devs.push_back (devname); - } + if (grandchild->name() != "State") { + continue; + } + + if ((prop = grandchild->property ("backend")) == 0) { + continue; } + state.backend = prop->value (); + + if ((prop = grandchild->property ("driver")) == 0) { + continue; + } + state.driver = prop->value (); + + if ((prop = grandchild->property ("device")) == 0) { + continue; + } + state.device = prop->value (); + + if ((prop = grandchild->property ("sample-rate")) == 0) { + continue; + } + state.sample_rate = prop->value (); + + if ((prop = grandchild->property ("buffer-size")) == 0) { + continue; + } + state.buffer_size = prop->value (); + + if ((prop = grandchild->property ("input-latency")) == 0) { + continue; + } + state.input_latency = atoi (prop->value ()); + + if ((prop = grandchild->property ("output-latency")) == 0) { + continue; + } + state.output_latency = atoi (prop->value ()); + + if ((prop = grandchild->property ("input-channels")) == 0) { + continue; + } + state.input_channels = atoi (prop->value ()); + + if ((prop = grandchild->property ("output-channels")) == 0) { + continue; + } + state.output_channels = atoi (prop->value ()); - snd_ctl_close(handle); + if ((prop = grandchild->property ("active")) == 0) { + continue; + } + state.active = string_is_affirmative (prop->value ()); + + states.push_back (state); } } - return devs; + /* now see if there was an active state and switch the setup to it */ + + for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) { + if ((*i).active) { + ignore_changes++; + backend_combo.set_active_text ((*i).backend); + driver_combo.set_active_text ((*i).driver); + device_combo.set_active_text ((*i).device); + sample_rate_combo.set_active_text ((*i).sample_rate); + buffer_size_combo.set_active_text ((*i).buffer_size); + input_latency.set_value ((*i).input_latency); + output_latency.set_value ((*i).output_latency); + ignore_changes--; + + push_state_to_backend (false); + break; + } + } } -#endif -vector<string> -EngineControl::enumerate_ffado_devices () -{ - vector<string> devs; - backend_devs.clear (); - return devs; -} -vector<string> -EngineControl::enumerate_freebob_devices () +int +EngineControl::push_state_to_backend (bool start) { - vector<string> devs; - return devs; -} + boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend(); -vector<string> -EngineControl::enumerate_oss_devices () -{ - vector<string> devs; - return devs; -} -vector<string> -EngineControl::enumerate_dummy_devices () -{ - vector<string> devs; - return devs; -} -vector<string> -EngineControl::enumerate_netjack_devices () -{ - vector<string> devs; - return devs; -} -#endif + if (!backend) { + return 0; + } -void -EngineControl::driver_changed () -{ - string driver = driver_combo.get_active_text(); - string::size_type maxlen = 0; - int n = 0; + /* grab the parameters from the GUI and apply them */ - enumerate_devices (driver); + try { + if (backend->requires_driver_selection()) { + if (backend->set_driver (get_driver())) { + return -1; + } + } - vector<string>& strings = devices[driver]; + if (backend->set_device_name (get_device_name())) { + return -1; + } - if (strings.empty() && driver != "FreeBoB" && driver != "FFADO" && driver != "Dummy") { - return; - } + if (backend->set_sample_rate (get_rate())) { + error << string_compose (_("Cannot set sample rate to %1"), get_rate()) << endmsg; + return -1; + } + if (backend->set_buffer_size (get_buffer_size())) { + error << string_compose (_("Cannot set buffer size to %1"), get_buffer_size()) << endmsg; + return -1; + } + if (backend->set_input_channels (get_input_channels())) { + error << string_compose (_("Cannot set input channels to %1"), get_input_channels()) << endmsg; + return -1; + } + if (backend->set_output_channels (get_output_channels())) { + error << string_compose (_("Cannot set output channels to %1"), get_output_channels()) << endmsg; + return -1; + } + if (backend->set_systemic_input_latency (get_input_latency())) { + error << string_compose (_("Cannot set input latency to %1"), get_input_latency()) << endmsg; + return -1; + } + if (backend->set_systemic_output_latency (get_output_latency())) { + error << string_compose (_("Cannot set output latency to %1"), get_output_latency()) << endmsg; + return -1; + } - for (vector<string>::iterator i = strings.begin(); i != strings.end(); ++i, ++n) { - if ((*i).length() > maxlen) { - maxlen = (*i).length(); + /* get a pointer to the current state object, creating one if + * necessary + */ + + State* state = get_current_state (); + + if (!state) { + save_state (); + state = get_current_state (); + assert (state); } - } - set_popdown_strings (interface_combo, strings); - set_popdown_strings (input_device_combo, strings); - set_popdown_strings (output_device_combo, strings); + /* all off */ - if (!strings.empty()) { - interface_combo.set_active_text (strings.front()); - input_device_combo.set_active_text (strings.front()); - output_device_combo.set_active_text (strings.front()); - } + for (StateList::iterator i = states.begin(); i != states.end(); ++i) { + (*i).active = false; + } - if (driver == "ALSA") { - soft_mode_button.set_sensitive (true); - force16bit_button.set_sensitive (true); - hw_monitor_button.set_sensitive (true); - hw_meter_button.set_sensitive (true); - monitor_button.set_sensitive (true); - } else { - soft_mode_button.set_sensitive (false); - force16bit_button.set_sensitive (false); - hw_monitor_button.set_sensitive (false); - hw_meter_button.set_sensitive (false); - monitor_button.set_sensitive (false); + /* mark this one active (to be used next time the dialog is + * shown) + */ + + state->active = true; + + if (start) { + if (ARDOUR::AudioEngine::instance()->start()) { + return -1; + } + } + + manage_control_app_sensitivity (); + return 0; + + } catch (...) { + cerr << "exception thrown...\n"; + return -1; } } uint32_t -EngineControl::get_rate () +EngineControl::get_rate () const { double r = atof (sample_rate_combo.get_active_text ()); /* the string may have been translated with an abbreviation for @@ -948,412 +840,200 @@ EngineControl::get_rate () return lrint (r); } -void -EngineControl::redisplay_latency () +uint32_t +EngineControl::get_buffer_size () const { - uint32_t rate = get_rate(); -#if defined(__APPLE__) || defined(__FreeBSD__) - float periods = 2; -#else - float periods = periods_adjustment.get_value(); -#endif - float period_size = atof (period_size_combo.get_active_text()); + string txt = buffer_size_combo.get_active_text (); + uint32_t samples; - char buf[32]; - snprintf (buf, sizeof(buf), "%.1fmsec", (periods * period_size) / (rate/1000.0)); + if (sscanf (txt.c_str(), "%d", &samples) != 1) { + throw exception (); + } - latency_label.set_text (buf); - latency_label.set_alignment (0, 0.5); + return samples; } -void -EngineControl::audio_mode_changed () +uint32_t +EngineControl::get_input_channels() const { - std::string str = audio_mode_combo.get_active_text(); - - if (str == _("Playback/recording on 1 device")) { - input_device_combo.set_sensitive (false); - output_device_combo.set_sensitive (false); - } else if (str == _("Playback/recording on 2 devices")) { - input_device_combo.set_sensitive (true); - output_device_combo.set_sensitive (true); - } else if (str == _("Playback only")) { - output_device_combo.set_sensitive (true); - input_device_combo.set_sensitive (false); - } else if (str == _("Recording only")) { - input_device_combo.set_sensitive (true); - output_device_combo.set_sensitive (false); - } + return (uint32_t) input_channels_adjustment.get_value(); } -static bool jack_server_filter(const string& str, void */*arg*/) +uint32_t +EngineControl::get_output_channels() const { - return str == "jackd" || str == "jackdmp"; + return (uint32_t) output_channels_adjustment.get_value(); } -void -EngineControl::find_jack_servers (vector<string>& strings) +uint32_t +EngineControl::get_input_latency() const { -#ifdef __APPLE__ - /* this magic lets us finds the path to the OSX bundle, and then - we infer JACK's location from there - */ - - char execpath[MAXPATHLEN+1]; - uint32_t pathsz = sizeof (execpath); + return (uint32_t) input_latency_adjustment.get_value(); +} - _NSGetExecutablePath (execpath, &pathsz); +uint32_t +EngineControl::get_output_latency() const +{ + return (uint32_t) output_latency_adjustment.get_value(); +} - string path (Glib::path_get_dirname (execpath)); - path += "/jackd"; +string +EngineControl::get_driver () const +{ + return driver_combo.get_active_text (); +} - if (Glib::file_test (path, FILE_TEST_EXISTS)) { - strings.push_back (path); - } +string +EngineControl::get_device_name () const +{ + return device_combo.get_active_text (); +} - if (getenv ("ARDOUR_WITH_JACK")) { - /* no other options - only use the JACK we supply */ - if (strings.empty()) { - fatal << string_compose (_("JACK appears to be missing from the %1 bundle"), PROGRAM_NAME) << endmsg; - /*NOTREACHED*/ - } +void +EngineControl::control_app_button_clicked () +{ + boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend(); + + if (!backend) { return; } -#else - string path; -#endif - - PathScanner scanner; - vector<string *> *jack_servers; - std::map<string,int> un; - char *p; - bool need_minimal_path = false; - - p = getenv ("PATH"); - - if (p && *p) { - path = p; - } else { - need_minimal_path = true; - } - -#ifdef __APPLE__ - // many mac users don't have PATH set up to include - // likely installed locations of JACK - need_minimal_path = true; -#endif - - if (need_minimal_path) { - if (path.empty()) { - path = "/usr/bin:/bin:/usr/local/bin:/opt/local/bin"; - } else { - path += ":/usr/local/bin:/opt/local/bin"; - } - } - -#ifdef __APPLE__ - // push it back into the environment so that auto-started JACK can find it. - // XXX why can't we just expect OS X users to have PATH set correctly? we can't ... - setenv ("PATH", path.c_str(), 1); -#endif + + backend->launch_control_app (); +} - jack_servers = scanner (path, jack_server_filter, 0, false, true); - if (!jack_servers) { +void +EngineControl::manage_control_app_sensitivity () +{ + boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend(); + + if (!backend) { return; } + + string appname = backend->control_app_name(); - vector<string *>::iterator iter; - - for (iter = jack_servers->begin(); iter != jack_servers->end(); iter++) { - string p = **iter; - - if (un[p]++ == 0) { - strings.push_back(p); - } + if (appname.empty()) { + control_app_button.set_sensitive (false); + } else { + control_app_button.set_sensitive (true); } } - -string -EngineControl::get_device_name (const string& driver, const string& human_readable) +void +EngineControl::set_desired_sample_rate (uint32_t sr) { - vector<string>::iterator n; - vector<string>::iterator i; - - if (human_readable.empty()) { - /* this can happen if the user's .ardourrc file has a device name from - another computer system in it - */ - MessageDialog msg (_("You need to choose an audio device first.")); - msg.set_position (WIN_POS_MOUSE); - msg.run (); - return string(); - } - - if (backend_devs.empty()) { - return human_readable; - } + _desired_sample_rate = sr; + device_changed (); +} - for (i = devices[driver].begin(), n = backend_devs.begin(); i != devices[driver].end(); ++i, ++n) { - if (human_readable == (*i)) { - return (*n); - } - } +/* latency measurement */ - if (i == devices[driver].end()) { - warning << string_compose (_("Audio device \"%1\" not known on this computer."), human_readable) << endmsg; - } - - return string(); +void +EngineControl::update_latency_display () +{ + ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate(); + if (sample_rate == 0) { + lm_results.set_text (_("Disconnected from audio engine")); + } else { + char buf[64]; + //snprintf (buf, sizeof (buf), "%10.3lf frames %10.3lf ms", + //(float)_pi->latency(), (float)_pi->latency() * 1000.0f/sample_rate); + strcpy (buf, "got something"); + lm_results.set_text(buf); + } } -XMLNode& -EngineControl::get_state () +bool +EngineControl::check_latency_measurement () { - XMLNode* root = new XMLNode ("AudioSetup"); - XMLNode* child; - std::string path; - - child = new XMLNode ("periods"); - child->add_property ("val", to_string (periods_adjustment.get_value(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("ports"); - child->add_property ("val", to_string (ports_adjustment.get_value(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("inlatency"); - child->add_property ("val", to_string (input_latency.get_value(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("outlatency"); - child->add_property ("val", to_string (output_latency.get_value(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("realtime"); - child->add_property ("val", to_string (realtime_button.get_active(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("nomemorylock"); - child->add_property ("val", to_string (no_memory_lock_button.get_active(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("unlockmemory"); - child->add_property ("val", to_string (unlock_memory_button.get_active(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("softmode"); - child->add_property ("val", to_string (soft_mode_button.get_active(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("force16bit"); - child->add_property ("val", to_string (force16bit_button.get_active(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("hwmonitor"); - child->add_property ("val", to_string (hw_monitor_button.get_active(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("hwmeter"); - child->add_property ("val", to_string (hw_meter_button.get_active(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("verbose"); - child->add_property ("val", to_string (verbose_output_button.get_active(), std::dec)); - root->add_child_nocopy (*child); - - child = new XMLNode ("samplerate"); - child->add_property ("val", sample_rate_combo.get_active_text()); - root->add_child_nocopy (*child); - - child = new XMLNode ("periodsize"); - child->add_property ("val", period_size_combo.get_active_text()); - root->add_child_nocopy (*child); + MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm (); + static uint32_t cnt = 0; + + if (mtdm->resolve () < 0) { + string txt = _("No signal detected "); + uint32_t dots = cnt++%10; + for (uint32_t i = 0; i < dots; ++i) { + txt += '.'; + } + lm_results.set_text (txt); + return true; + } - child = new XMLNode ("serverpath"); - child->add_property ("val", serverpath_combo.get_active_text()); - root->add_child_nocopy (*child); + if (mtdm->err () > 0.3) { + mtdm->invert (); + mtdm->resolve (); + } - child = new XMLNode ("driver"); - child->add_property ("val", driver_combo.get_active_text()); - root->add_child_nocopy (*child); + char buf[128]; + ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate(); - child = new XMLNode ("interface"); - child->add_property ("val", interface_combo.get_active_text()); - root->add_child_nocopy (*child); + if (sample_rate == 0) { + lm_results.set_text (_("Disconnected from audio engine")); + ARDOUR::AudioEngine::instance()->stop_latency_detection (); + return false; + } - child = new XMLNode ("timeout"); - child->add_property ("val", timeout_combo.get_active_text()); - root->add_child_nocopy (*child); + uint32_t frames_total = mtdm->del(); + uint32_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay(); - child = new XMLNode ("dither"); - child->add_property ("val", dither_mode_combo.get_active_text()); - root->add_child_nocopy (*child); + snprintf (buf, sizeof (buf), "%u samples %10.3lf ms", extra, extra * 1000.0f/sample_rate); - child = new XMLNode ("audiomode"); - child->add_property ("val", audio_mode_combo.get_active_text()); - root->add_child_nocopy (*child); + bool solid = true; - child = new XMLNode ("inputdevice"); - child->add_property ("val", input_device_combo.get_active_text()); - root->add_child_nocopy (*child); + if (mtdm->err () > 0.2) { + strcat (buf, " ??"); + solid = false; + } - child = new XMLNode ("outputdevice"); - child->add_property ("val", output_device_combo.get_active_text()); - root->add_child_nocopy (*child); + if (mtdm->inv ()) { + strcat (buf, " (Inv)"); + solid = false; + } - child = new XMLNode ("mididriver"); - child->add_property ("val", midi_driver_combo.get_active_text()); - root->add_child_nocopy (*child); + if (solid) { + // _pi->set_measured_latency (rint (mtdm->del())); + lm_measure_button.set_active (false); + lm_use_button.set_sensitive (true); + strcat (buf, " (set)"); + } + + lm_results.set_text (buf); - return *root; + return true; } void -EngineControl::set_state (const XMLNode& root) +EngineControl::latency_button_toggled () { - XMLNodeList clist; - XMLNodeConstIterator citer; - XMLNode* child; - XMLProperty* prop = NULL; - bool using_dummy = false; - bool using_ffado = false; - - int val; - string strval; - - if ( (child = root.child ("driver"))){ - prop = child->property("val"); + if (lm_measure_button.get_active ()) { + + ARDOUR::AudioEngine::instance()->set_latency_input_port (lm_input_channel_combo.get_active_text()); + ARDOUR::AudioEngine::instance()->set_latency_output_port (lm_output_channel_combo.get_active_text()); + cerr << "latency detection on " << lm_input_channel_combo.get_active_text() << " => " << lm_output_channel_combo.get_active_text() << endl; + ARDOUR::AudioEngine::instance()->start_latency_detection (); + lm_results.set_text (_("Detecting ...")); + latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_latency_measurement), 250); + + } else { + ARDOUR::AudioEngine::instance()->stop_latency_detection (); + latency_timeout.disconnect (); + update_latency_display (); + } +} - if (prop && (prop->value() == "Dummy") ) { - using_dummy = true; - } - if (prop && (prop->value() == "FFADO") ) { - using_ffado = true; - } +void +EngineControl::use_latency_button_clicked () +{ + MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm (); + if (!mtdm) { + return; } - clist = root.children(); - - for (citer = clist.begin(); citer != clist.end(); ++citer) { - - child = *citer; - - prop = child->property ("val"); - - if (!prop || prop->value().empty()) { + uint32_t frames_total = mtdm->del(); + uint32_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay(); + uint32_t one_way = extra/2; - if (((using_dummy || using_ffado) - && ( child->name() == "interface" - || child->name() == "inputdevice" - || child->name() == "outputdevice")) - || child->name() == "timeout") - { - continue; - } - - error << string_compose (_("AudioSetup value for %1 is missing data"), child->name()) << endmsg; - continue; - } - - strval = prop->value(); - - /* adjustments/spinners */ - - if (child->name() == "periods") { - val = atoi (strval); - periods_adjustment.set_value(val); - } else if (child->name() == "ports") { - val = atoi (strval); - ports_adjustment.set_value(val); - } else if (child->name() == "inlatency") { - val = atoi (strval); - input_latency.set_value(val); - } else if (child->name() == "outlatency") { - val = atoi (strval); - output_latency.set_value(val); - } - - /* buttons */ - - else if (child->name() == "realtime") { - val = atoi (strval); - realtime_button.set_active(val); - } else if (child->name() == "nomemorylock") { - val = atoi (strval); - no_memory_lock_button.set_active(val); - } else if (child->name() == "unlockmemory") { - val = atoi (strval); - unlock_memory_button.set_active(val); - } else if (child->name() == "softmode") { - val = atoi (strval); - soft_mode_button.set_active(val); - } else if (child->name() == "force16bit") { - val = atoi (strval); - force16bit_button.set_active(val); - } else if (child->name() == "hwmonitor") { - val = atoi (strval); - hw_monitor_button.set_active(val); - } else if (child->name() == "hwmeter") { - val = atoi (strval); - hw_meter_button.set_active(val); - } else if (child->name() == "verbose") { - val = atoi (strval); - verbose_output_button.set_active(val); - } - - /* combos */ - - else if (child->name() == "samplerate") { - sample_rate_combo.set_active_text(strval); - } else if (child->name() == "periodsize") { - period_size_combo.set_active_text(strval); - } else if (child->name() == "serverpath") { - - /* only attempt to set this if we have bothered to look - up server names already. otherwise this is all - redundant (actually, all of this dialog/widget - is redundant in that case ...) - */ - - if (!server_strings.empty()) { - /* do not allow us to use a server path that doesn't - exist on this system. this handles cases where - the user has an RC file listing a serverpath - from some other machine. - */ - vector<string>::iterator x; - for (x = server_strings.begin(); x != server_strings.end(); ++x) { - if (*x == strval) { - break; - } - } - if (x != server_strings.end()) { - serverpath_combo.set_active_text (strval); - } else { - warning << string_compose (_("configuration files contain a JACK server path that doesn't exist (%1)"), - strval) - << endmsg; - } - } - - } else if (child->name() == "driver") { - driver_combo.set_active_text(strval); - } else if (child->name() == "interface") { - interface_combo.set_active_text(strval); - } else if (child->name() == "timeout") { - timeout_combo.set_active_text(strval); - } else if (child->name() == "dither") { - dither_mode_combo.set_active_text(strval); - } else if (child->name() == "audiomode") { - audio_mode_combo.set_active_text(strval); - } else if (child->name() == "inputdevice") { - input_device_combo.set_active_text(strval); - } else if (child->name() == "outputdevice") { - output_device_combo.set_active_text(strval); - } else if (child->name() == "mididriver") { - midi_driver_combo.set_active_text(strval); - } - } + input_latency_adjustment.set_value (one_way); + output_latency_adjustment.set_value (one_way); } diff --git a/gtk2_ardour/engine_dialog.h b/gtk2_ardour/engine_dialog.h index 0d7ce29b46..3872917add 100644 --- a/gtk2_ardour/engine_dialog.h +++ b/gtk2_ardour/engine_dialog.h @@ -26,7 +26,6 @@ #include <gtkmm/checkbutton.h> #include <gtkmm/spinbutton.h> -#include <gtkmm/notebook.h> #include <gtkmm/comboboxtext.h> #include <gtkmm/table.h> #include <gtkmm/expander.h> @@ -34,93 +33,149 @@ #include <gtkmm/buttonbox.h> #include <gtkmm/button.h> -class EngineControl : public Gtk::VBox { - public: - EngineControl (); - ~EngineControl (); - - static bool need_setup (); - int setup_engine (); +#include "pbd/signals.h" - bool was_used() const { return _used; } - XMLNode& get_state (); - void set_state (const XMLNode&); +#include "ardour_dialog.h" +class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList { + public: + EngineControl (); + ~EngineControl (); + + static bool need_setup (); + + XMLNode& get_state (); + void set_state (const XMLNode&); + + void set_desired_sample_rate (uint32_t); + private: - Gtk::Adjustment periods_adjustment; - Gtk::SpinButton periods_spinner; - Gtk::Adjustment ports_adjustment; - Gtk::SpinButton ports_spinner; - Gtk::Adjustment input_latency_adjustment; - Gtk::SpinButton input_latency; - Gtk::Adjustment output_latency_adjustment; - Gtk::SpinButton output_latency; - Gtk::Label latency_label; - - Gtk::CheckButton realtime_button; - Gtk::CheckButton no_memory_lock_button; - Gtk::CheckButton unlock_memory_button; - Gtk::CheckButton soft_mode_button; - Gtk::CheckButton monitor_button; - Gtk::CheckButton force16bit_button; - Gtk::CheckButton hw_monitor_button; - Gtk::CheckButton hw_meter_button; - Gtk::CheckButton verbose_output_button; - - Gtk::Button start_button; - Gtk::Button stop_button; - Gtk::HButtonBox button_box; - - Gtk::ComboBoxText sample_rate_combo; - Gtk::ComboBoxText period_size_combo; - - Gtk::ComboBoxText preset_combo; - Gtk::ComboBoxText serverpath_combo; - Gtk::ComboBoxText driver_combo; - Gtk::ComboBoxText interface_combo; - Gtk::ComboBoxText timeout_combo; - Gtk::ComboBoxText dither_mode_combo; - Gtk::ComboBoxText audio_mode_combo; - Gtk::ComboBoxText input_device_combo; - Gtk::ComboBoxText output_device_combo; - Gtk::ComboBoxText midi_driver_combo; - - Gtk::Table basic_packer; - Gtk::Table options_packer; - Gtk::Table device_packer; - Gtk::HBox basic_hbox; - Gtk::HBox options_hbox; - Gtk::HBox device_hbox; - Gtk::Notebook notebook; - - bool _used; - - static bool engine_running (); - - void driver_changed (); - void build_command_line (std::vector<std::string>&); - - std::map<std::string,std::vector<std::string> > devices; - std::vector<std::string> backend_devs; - void enumerate_devices (const std::string& driver); - -#ifdef __APPLE__ - std::vector<std::string> enumerate_coreaudio_devices (); -#else - std::vector<std::string> enumerate_alsa_devices (); - std::vector<std::string> enumerate_oss_devices (); - std::vector<std::string> enumerate_netjack_devices (); - std::vector<std::string> enumerate_freebob_devices (); - std::vector<std::string> enumerate_ffado_devices (); - std::vector<std::string> enumerate_dummy_devices (); -#endif - - void redisplay_latency (); - uint32_t get_rate(); - void audio_mode_changed (); - std::vector<std::string> server_strings; - void find_jack_servers (std::vector<std::string>&); - std::string get_device_name (const std::string& driver, const std::string& human_readable_name); + Gtk::Notebook notebook; + + /* core fields used by all backends */ + + Gtk::ComboBoxText backend_combo; + Gtk::ComboBoxText sample_rate_combo; + Gtk::ComboBoxText buffer_size_combo; + Gtk::Label buffer_size_duration_label; + Gtk::Adjustment input_latency_adjustment; + Gtk::SpinButton input_latency; + Gtk::Adjustment output_latency_adjustment; + Gtk::SpinButton output_latency; + Gtk::Adjustment input_channels_adjustment; + Gtk::SpinButton input_channels; + Gtk::Adjustment output_channels_adjustment; + Gtk::SpinButton output_channels; + Gtk::Adjustment ports_adjustment; + Gtk::SpinButton ports_spinner; + + Gtk::Button control_app_button; + + /* latency measurement */ + + Gtk::ComboBoxText lm_output_channel_combo; + Gtk::ComboBoxText lm_input_channel_combo; + Gtk::ToggleButton lm_measure_button; + Gtk::Button lm_use_button; + Gtk::Label lm_title; + Gtk::Label lm_preamble; + Gtk::Label lm_results; + Gtk::Table lm_table; + Gtk::VBox lm_vbox; + + /* JACK specific */ + + Gtk::CheckButton realtime_button; + Gtk::CheckButton no_memory_lock_button; + Gtk::CheckButton unlock_memory_button; + Gtk::CheckButton soft_mode_button; + Gtk::CheckButton monitor_button; + Gtk::CheckButton force16bit_button; + Gtk::CheckButton hw_monitor_button; + Gtk::CheckButton hw_meter_button; + Gtk::CheckButton verbose_output_button; + + Gtk::ComboBoxText preset_combo; + Gtk::ComboBoxText serverpath_combo; + Gtk::ComboBoxText driver_combo; + Gtk::ComboBoxText device_combo; + Gtk::ComboBoxText timeout_combo; + Gtk::ComboBoxText dither_mode_combo; + Gtk::ComboBoxText audio_mode_combo; + Gtk::ComboBoxText midi_driver_combo; + + Gtk::Table basic_packer; + Gtk::Table midi_packer; + Gtk::HBox basic_hbox; + Gtk::VBox basic_vbox; + Gtk::HBox midi_hbox; + + uint32_t ignore_changes; + + static bool engine_running (); + + void driver_changed (); + void backend_changed (); + void sample_rate_changed (); + void buffer_size_changed (); + + uint32_t get_rate() const; + uint32_t get_buffer_size() const; + uint32_t get_input_channels() const; + uint32_t get_output_channels() const; + uint32_t get_input_latency() const; + uint32_t get_output_latency() const; + std::string get_device_name() const; + std::string get_driver() const; + + void device_changed (); + void list_devices (); + void show_buffer_duration (); + + struct State { + std::string backend; + std::string driver; + std::string device; + std::string sample_rate; + std::string buffer_size; + uint32_t input_latency; + uint32_t output_latency; + uint32_t input_channels; + uint32_t output_channels; + bool active; + + State() : active (false) {}; + }; + + typedef std::list<State> StateList; + + StateList states; + + State* get_matching_state (const std::string& backend, + const std::string& driver, + const std::string& device); + State* get_current_state (); + void maybe_display_saved_state (); + void save_state (); + + static bool print_channel_count (Gtk::SpinButton*); + + void build_notebook (); + + void on_response (int); + void control_app_button_clicked (); + void use_latency_button_clicked (); + void manage_control_app_sensitivity (); + int push_state_to_backend (bool start); + uint32_t _desired_sample_rate; + + /* latency measurement */ + void latency_button_toggled (); + bool check_latency_measurement (); + void update_latency_display (); + sigc::connection latency_timeout; + void enable_latency_tab (); + void disable_latency_tab (); }; #endif /* __gtk2_ardour_engine_dialog_h__ */ diff --git a/gtk2_ardour/export_video_dialog.cc b/gtk2_ardour/export_video_dialog.cc index 09283d4c8d..f54232a681 100644 --- a/gtk2_ardour/export_video_dialog.cc +++ b/gtk2_ardour/export_video_dialog.cc @@ -259,8 +259,7 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s) video_codec_combo.append_text("mjpeg"); video_codec_combo.append_text("mpeg2video"); video_codec_combo.append_text("mpeg4"); - video_codec_combo.append_text("x264 (baseline)"); - video_codec_combo.append_text("x264 (hq)"); + video_codec_combo.append_text("h264"); video_codec_combo.append_text("vpx (webm)"); video_codec_combo.append_text("copy"); video_codec_combo.set_active(4); @@ -614,13 +613,8 @@ ExportVideoDialog::encode_pass (int pass) ffs["-strict"] = "-2"; } - if (video_codec_combo.get_active_text() == "x264 (hq)" ) { + if (video_codec_combo.get_active_text() == "h264" ) { ffs["-vcodec"] = "libx264"; - ffs["-vprofile"] = "high"; - } - else if (video_codec_combo.get_active_text() == "x264 (baseline)" ) { - ffs["-vcodec"] = "libx264"; - ffs["-vpre"] = "baseline"; } else if (video_codec_combo.get_active_text() == "vpx (webm)" ) { ffs["-vcodec"] = "libvpx"; diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc index c2e4a43858..d4610da601 100644 --- a/gtk2_ardour/gain_meter.cc +++ b/gtk2_ardour/gain_meter.cc @@ -32,7 +32,6 @@ #include <gtkmm2ext/fastmeter.h> #include <gtkmm2ext/barcontroller.h> #include <gtkmm2ext/gtk_ui.h> -#include "midi++/manager.h" #include "pbd/fastlog.h" #include "pbd/stacktrace.h" @@ -280,14 +279,15 @@ GainMeterBase::setup_meters (int len) case Wide: meter_ticks1_area.show(); meter_ticks2_area.show(); + meter_metric_area.show(); if (_route && _route->shared_peak_meter()->input_streams().n_total() == 1) { meter_width = 10; } break; case Narrow: - meter_width = 2; meter_ticks1_area.hide(); meter_ticks2_area.hide(); + meter_metric_area.hide(); break; } level_meter->setup_meters(len, meter_width); @@ -864,7 +864,7 @@ GainMeterBase::update_meters() } } -void GainMeterBase::color_handler(bool /* dpi */) +void GainMeterBase::color_handler(bool /*dpi*/) { setup_meters(); } diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc index 6cea8f3c0b..83f091a1e0 100644 --- a/gtk2_ardour/generic_pluginui.cc +++ b/gtk2_ardour/generic_pluginui.cc @@ -37,8 +37,6 @@ #include <gtkmm2ext/doi.h> #include <gtkmm2ext/slider_controller.h> -#include "midi++/manager.h" - #include "ardour/plugin.h" #include "ardour/plugin_insert.h" #include "ardour/session.h" diff --git a/gtk2_ardour/global_port_matrix.cc b/gtk2_ardour/global_port_matrix.cc index e1bdfb199e..218cfe7a1c 100644 --- a/gtk2_ardour/global_port_matrix.cc +++ b/gtk2_ardour/global_port_matrix.cc @@ -19,6 +19,7 @@ #include <gtkmm/image.h> #include <gtkmm/stock.h> + #include "global_port_matrix.h" #include "utils.h" @@ -82,9 +83,9 @@ GlobalPortMatrix::set_state (BundleChannel c[2], bool s) } else { /* two non-Ardour ports */ if (s) { - jack_connect (_session->engine().jack (), j->c_str(), i->c_str()); + AudioEngine::instance()->connect (*j, *i); } else { - jack_disconnect (_session->engine().jack (), j->c_str(), i->c_str()); + AudioEngine::instance()->disconnect (*j, *i); } } } @@ -113,33 +114,25 @@ GlobalPortMatrix::get_state (BundleChannel c[2]) const for (Bundle::PortList::const_iterator i = in_ports.begin(); i != in_ports.end(); ++i) { for (Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) { - boost::shared_ptr<Port> p = _session->engine().get_port_by_name (*i); - boost::shared_ptr<Port> q = _session->engine().get_port_by_name (*j); + boost::shared_ptr<Port> p = AudioEngine::instance()->get_port_by_name (*i); + boost::shared_ptr<Port> q = AudioEngine::instance()->get_port_by_name (*j); if (!p && !q) { /* two non-Ardour ports; things are slightly more involved */ - /* XXX: is this the easiest way to do this? */ - /* XXX: isn't this very inefficient? */ - jack_client_t* jack = _session->engine().jack (); - jack_port_t* jp = jack_port_by_name (jack, i->c_str()); - if (jp == 0) { + /* get a port handle for one of them .. */ + + PortEngine::PortHandle ph = AudioEngine::instance()->port_engine().get_port_by_name (*i); + if (!ph) { return PortMatrixNode::NOT_ASSOCIATED; } - char const ** c = jack_port_get_all_connections (jack, jp); - - char const ** p = c; + /* see if it is connected to the other one ... */ - while (p && *p != 0) { - if (strcmp (*p, j->c_str()) == 0) { - free (c); - return PortMatrixNode::ASSOCIATED; - } - ++p; + if (AudioEngine::instance()->port_engine().connected_to (ph, *j, false)) { + return PortMatrixNode::ASSOCIATED; } - free (c); return PortMatrixNode::NOT_ASSOCIATED; } diff --git a/gtk2_ardour/level_meter.cc b/gtk2_ardour/level_meter.cc index 6f48864992..bf9823518b 100644 --- a/gtk2_ardour/level_meter.cc +++ b/gtk2_ardour/level_meter.cc @@ -23,7 +23,6 @@ #include <gtkmm2ext/utils.h> #include <gtkmm2ext/barcontroller.h> -#include "midi++/manager.h" #include "pbd/fastlog.h" #include "ardour_ui.h" diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc index dfa0bda945..f55405a84d 100644 --- a/gtk2_ardour/main.cc +++ b/gtk2_ardour/main.cc @@ -373,34 +373,30 @@ static void load_custom_fonts() { #endif static gboolean -tell_about_jack_death (void* /* ignored */) +tell_about_backend_death (void* /* ignored */) { if (AudioEngine::instance()->processed_frames() == 0) { /* died during startup */ - MessageDialog msg (_("JACK exited"), false); + MessageDialog msg (string_compose (_("The audio backend (%1) has failed, or terminated"), AudioEngine::instance()->current_backend_name()), false); msg.set_position (Gtk::WIN_POS_CENTER); msg.set_secondary_text (string_compose (_( -"JACK exited unexpectedly, and without notifying %1.\n\ +"%2 exited unexpectedly, and without notifying %1.\n\ \n\ -This could be due to misconfiguration or to an error inside JACK.\n\ +This could be due to misconfiguration or to an error inside %2.\n\ \n\ -Click OK to exit %1."), PROGRAM_NAME)); +Click OK to exit %1."), PROGRAM_NAME, AudioEngine::instance()->current_backend_name())); msg.run (); _exit (0); } else { - /* engine has already run, so this is a mid-session JACK death */ - - MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false)); - msg->set_secondary_text (string_compose (_( -"JACK exited unexpectedly, and without notifying %1.\n\ -\n\ -This is probably due to an error inside JACK. You should restart JACK\n\ -and reconnect %1 to it, or exit %1 now. You cannot save your\n\ -session at this time, because we would lose your connection information.\n"), PROGRAM_NAME)); - msg->present (); + /* engine has already run, so this is a mid-session backend death */ + + MessageDialog msg (string_compose (_("The audio backend (%1) has failed, or terminated"), AudioEngine::instance()->current_backend_name()), false); + msg.set_secondary_text (string_compose (_("%2 exited unexpectedly, and without notifying %1."), + PROGRAM_NAME, AudioEngine::instance()->current_backend_name())); + msg.present (); } return false; /* do not call again */ } @@ -408,15 +404,15 @@ session at this time, because we would lose your connection information.\n"), PR static void sigpipe_handler (int /*signal*/) { - /* XXX fix this so that we do this again after a reconnect to JACK + /* XXX fix this so that we do this again after a reconnect to the backend */ - static bool done_the_jack_thing = false; + static bool done_the_backend_thing = false; - if (!done_the_jack_thing) { + if (!done_the_backend_thing) { AudioEngine::instance()->died (); - g_idle_add (tell_about_jack_death, 0); - done_the_jack_thing = true; + g_idle_add (tell_about_backend_death, 0); + done_the_backend_thing = true; } } diff --git a/gtk2_ardour/meterbridge.cc b/gtk2_ardour/meterbridge.cc index 4a4f1dd8dd..8756089e00 100644 --- a/gtk2_ardour/meterbridge.cc +++ b/gtk2_ardour/meterbridge.cc @@ -702,11 +702,11 @@ Meterbridge::sync_order_keys (RouteSortOrderKey) MeterType nmt = (*i).s->meter_type(); if (nmt == MeterKrms) nmt = MeterPeak; // identical metrics - if (pos == 0) { + if (vis == 1) { (*i).s->set_tick_bar(1); } - if ((*i).visible && nmt != lmt && pos == 0) { + if ((*i).visible && nmt != lmt && vis == 1) { lmt = nmt; metrics_left.set_metric_mode(1, lmt); } else if ((*i).visible && nmt != lmt) { diff --git a/gtk2_ardour/midi_tracer.cc b/gtk2_ardour/midi_tracer.cc index c4fe76252b..934dffd11c 100644 --- a/gtk2_ardour/midi_tracer.cc +++ b/gtk2_ardour/midi_tracer.cc @@ -27,7 +27,10 @@ #include "pbd/timersub.h" #include "midi++/parser.h" -#include "midi++/manager.h" + +#include "ardour/async_midi_port.h" +#include "ardour/midi_port.h" +#include "ardour/audioengine.h" #include "midi_tracer.h" #include "gui_thread.h" @@ -56,7 +59,8 @@ MidiTracer::MidiTracer () , collect_button (_("Enabled")) , delta_time_button (_("Delta times")) { - Manager::instance()->PortsChanged.connect (_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context()); + ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect + (_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context()); _last_receipt.tv_sec = 0; _last_receipt.tv_usec = 0; @@ -129,24 +133,58 @@ MidiTracer::ports_changed () { string const c = _port_combo.get_active_text (); _port_combo.clear (); + + ARDOUR::PortManager::PortList pl; + ARDOUR::AudioEngine::instance()->get_ports (ARDOUR::DataType::MIDI, pl); + + if (pl.empty()) { + _port_combo.set_active_text (""); + return; + } - boost::shared_ptr<const Manager::PortList> p = Manager::instance()->get_midi_ports (); - for (Manager::PortList::const_iterator i = p->begin(); i != p->end(); ++i) { + for (ARDOUR::PortManager::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) { _port_combo.append_text ((*i)->name()); } - _port_combo.set_active_text (c); + if (c.empty()) { + _port_combo.set_active_text (pl.front()->name()); + } else { + _port_combo.set_active_text (c); + } } void MidiTracer::port_changed () { + using namespace ARDOUR; + disconnect (); - Port* p = Manager::instance()->port (_port_combo.get_active_text()); + boost::shared_ptr<ARDOUR::Port> p = AudioEngine::instance()->get_port_by_name (_port_combo.get_active_text()); + + if (!p) { + std::cerr << "port not found\n"; + return; + } + + /* The inheritance heirarchy makes this messy. AsyncMIDIPort has two + * available MIDI::Parsers what we could connect to, ::self_parser() + * (from ARDOUR::MidiPort) and ::parser() from MIDI::Port. One day, + * this mess will all go away ... + */ + + boost::shared_ptr<AsyncMIDIPort> async = boost::dynamic_pointer_cast<AsyncMIDIPort> (p); + + if (!async) { - if (p) { - p->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3)); + boost::shared_ptr<ARDOUR::MidiPort> mp = boost::dynamic_pointer_cast<ARDOUR::MidiPort> (p); + + if (mp) { + mp->self_parser().any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3)); + } + + } else { + async->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3)); } } @@ -369,9 +407,9 @@ MidiTracer::tracer (Parser&, byte* msg, size_t len) fifo.write (&buf, 1); - if (g_atomic_int_get (&_update_queued) == 0) { + if (g_atomic_int_get (const_cast<gint*> (&_update_queued)) == 0) { gui_context()->call_slot (invalidator (*this), boost::bind (&MidiTracer::update, this)); - g_atomic_int_inc (&_update_queued); + g_atomic_int_inc (const_cast<gint*> (&_update_queued)); } } @@ -379,7 +417,7 @@ void MidiTracer::update () { bool updated = false; - g_atomic_int_dec_and_test (&_update_queued); + g_atomic_int_dec_and_test (const_cast<gint*> (&_update_queued)); RefPtr<TextBuffer> buf (text.get_buffer()); diff --git a/gtk2_ardour/nsm.cc b/gtk2_ardour/nsm.cc index 18d88fec0a..e3ceba355f 100644 --- a/gtk2_ardour/nsm.cc +++ b/gtk2_ardour/nsm.cc @@ -50,7 +50,7 @@ NSM_Client::command_open(const char* name, int r = ERR_OK; ARDOUR_COMMAND_LINE::session_name = name; - ARDOUR_COMMAND_LINE::jack_client_name = client_id; + ARDOUR_COMMAND_LINE::backend_client_name = client_id; if (ARDOUR_UI::instance()->get_session_parameters(true, false, "")) { return ERR_GENERAL; diff --git a/gtk2_ardour/opts.cc b/gtk2_ardour/opts.cc index b29f106bfe..90d753af4c 100644 --- a/gtk2_ardour/opts.cc +++ b/gtk2_ardour/opts.cc @@ -32,7 +32,8 @@ using namespace std; string ARDOUR_COMMAND_LINE::session_name = ""; -string ARDOUR_COMMAND_LINE::jack_client_name = "ardour"; +string ARDOUR_COMMAND_LINE::backend_client_name = "ardour"; +string ARDOUR_COMMAND_LINE::backend_session_uuid; bool ARDOUR_COMMAND_LINE::show_key_actions = false; bool ARDOUR_COMMAND_LINE::no_splash = false; bool ARDOUR_COMMAND_LINE::just_version = false; @@ -45,7 +46,6 @@ string ARDOUR_COMMAND_LINE::keybindings_path = ""; /* empty means use builtin de std::string ARDOUR_COMMAND_LINE::menus_file = "ardour.menus"; bool ARDOUR_COMMAND_LINE::finder_invoked_ardour = false; string ARDOUR_COMMAND_LINE::immediate_save; -string ARDOUR_COMMAND_LINE::jack_session_uuid; string ARDOUR_COMMAND_LINE::load_template; bool ARDOUR_COMMAND_LINE::check_announcements = true; @@ -60,7 +60,7 @@ print_help (const char *execname) << _(" -h, --help Print this message\n") << _(" -a, --no-announcements Do not contact website for announcements\n") << _(" -b, --bindings Print all possible keyboard binding names\n") - << _(" -c, --name <name> Use a specific jack client name, default is ardour\n") + << _(" -c, --name <name> Use a specific backend client name, default is ardour\n") << _(" -d, --disable-plugins Disable all plugins in an existing session\n") << _(" -D, --debug <options> Set debug flags. Use \"-D list\" to see available options\n") << _(" -n, --no-splash Do not show splash screen\n") @@ -199,7 +199,7 @@ ARDOUR_COMMAND_LINE::parse_opts (int argc, char *argv[]) break; case 'c': - jack_client_name = optarg; + backend_client_name = optarg; break; case 'C': @@ -215,7 +215,7 @@ ARDOUR_COMMAND_LINE::parse_opts (int argc, char *argv[]) break; case 'U': - jack_session_uuid = optarg; + backend_session_uuid = optarg; break; default: diff --git a/gtk2_ardour/opts.h b/gtk2_ardour/opts.h index b9faa36d72..fdf29157d2 100644 --- a/gtk2_ardour/opts.h +++ b/gtk2_ardour/opts.h @@ -28,7 +28,8 @@ extern std::string session_name; extern bool show_key_actions; extern bool no_splash; extern bool just_version; -extern std::string jack_client_name; +extern std::string backend_client_name; +extern std::string backend_session_uuid; extern bool use_vst; extern bool new_session; extern char* curvetest_file; @@ -39,7 +40,6 @@ extern std::string keybindings_path; extern std::string menus_file; extern bool finder_invoked_ardour; extern std::string immediate_save; -extern std::string jack_session_uuid; extern std::string load_template; extern bool check_announcements; diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc index a5ed0c7aee..95d7491921 100644 --- a/gtk2_ardour/panner_ui.cc +++ b/gtk2_ardour/panner_ui.cc @@ -21,7 +21,6 @@ #include <gtkmm2ext/utils.h> #include <gtkmm2ext/barcontroller.h> -#include "midi++/manager.h" #include "pbd/fastlog.h" #include "ardour/pannable.h" diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc index c19738f02f..28ef9b1297 100644 --- a/gtk2_ardour/plugin_ui.cc +++ b/gtk2_ardour/plugin_ui.cc @@ -40,8 +40,6 @@ #include <gtkmm2ext/slider_controller.h> #include <gtkmm2ext/application.h> -#include "midi++/manager.h" - #include "ardour/session.h" #include "ardour/plugin.h" #include "ardour/plugin_insert.h" diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc index 531a5cf2c4..2a93cf6bee 100644 --- a/gtk2_ardour/port_group.cc +++ b/gtk2_ardour/port_group.cc @@ -21,7 +21,6 @@ #include <boost/shared_ptr.hpp> #include <boost/algorithm/string.hpp> -#include "midi++/manager.h" #include "midi++/mmc.h" #include "ardour/audioengine.h" @@ -29,9 +28,12 @@ #include "ardour/bundle.h" #include "ardour/control_protocol_manager.h" #include "ardour/io_processor.h" +#include "ardour/midi_port.h" +#include "ardour/midiport_manager.h" #include "ardour/session.h" #include "ardour/user_bundle.h" #include "ardour/port.h" + #include "control_protocol/control_protocol.h" #include "gui_thread.h" @@ -452,37 +454,35 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp /* Ardour's sync ports */ - MIDI::Manager* midi_manager = MIDI::Manager::instance (); - if (midi_manager && (type == DataType::MIDI || type == DataType::NIL)) { + if ((type == DataType::MIDI || type == DataType::NIL)) { boost::shared_ptr<Bundle> sync (new Bundle (_("Sync"), inputs)); - MIDI::MachineControl* mmc = midi_manager->mmc (); - AudioEngine& ae = session->engine (); + AudioEngine* ae = AudioEngine::instance(); if (inputs) { sync->add_channel ( - _("MTC in"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->mtc_input_port()->name()) + _("MTC in"), DataType::MIDI, ae->make_port_name_non_relative (session->mtc_input_port()->name()) ); sync->add_channel ( - _("MIDI control in"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_input_port()->name()) + _("MIDI control in"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_input_port()->name()) ); sync->add_channel ( - _("MIDI clock in"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_clock_input_port()->name()) + _("MIDI clock in"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_clock_input_port()->name()) ); sync->add_channel ( - _("MMC in"), DataType::MIDI, ae.make_port_name_non_relative (mmc->input_port()->name()) + _("MMC in"), DataType::MIDI, ae->make_port_name_non_relative (session->mmc_input_port()->name()) ); } else { sync->add_channel ( - _("MTC out"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->mtc_output_port()->name()) + _("MTC out"), DataType::MIDI, ae->make_port_name_non_relative (session->mtc_output_port()->name()) ); sync->add_channel ( - _("MIDI control out"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_output_port()->name()) + _("MIDI control out"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_output_port()->name()) ); sync->add_channel ( - _("MIDI clock out"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_clock_output_port()->name()) + _("MIDI clock out"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_clock_output_port()->name()) ); sync->add_channel ( - _("MMC out"), DataType::MIDI, ae.make_port_name_non_relative (mmc->output_port()->name()) + _("MMC out"), DataType::MIDI, ae->make_port_name_non_relative (session->mmc_output_port()->name()) ); } @@ -499,20 +499,12 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp string lpnc = lpn; lpnc += ':'; - const char ** ports = 0; - if (type == DataType::NIL) { - ports = session->engine().get_ports ("", "", inputs ? JackPortIsInput : JackPortIsOutput); - } else { - ports = session->engine().get_ports ("", type.to_jack_type(), inputs ? JackPortIsInput : JackPortIsOutput); - } - - if (ports) { - - int n = 0; + vector<string> ports; + if (AudioEngine::instance()->get_ports ("", type, inputs ? IsInput : IsOutput, ports) > 0) { - while (ports[n]) { + for (vector<string>::const_iterator s = ports.begin(); s != ports.end(); ) { - std::string const p = ports[n]; + std::string const p = *s; if (!system->has_port(p) && !bus->has_port(p) && @@ -526,7 +518,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp */ if (p.find ("Midi-Through") != string::npos) { - ++n; + ++s; continue; } @@ -539,15 +531,15 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp if ((lp.find (N_(":monitor")) != string::npos) && (lp.find (lpn) != string::npos)) { - ++n; + ++s; continue; } /* can't use the audio engine for this as we are looking at non-Ardour ports */ - jack_port_t* jp = jack_port_by_name (session->engine().jack(), p.c_str()); - if (jp) { - DataType t (jack_port_type (jp)); + PortEngine::PortHandle ph = AudioEngine::instance()->port_engine().get_port_by_name (p); + if (ph) { + DataType t (AudioEngine::instance()->port_engine().port_data_type (ph)); if (t != DataType::NIL) { if (port_has_prefix (p, N_("system:")) || port_has_prefix (p, N_("alsa_pcm")) || @@ -560,10 +552,8 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp } } - ++n; + ++s; } - - free (ports); } for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) { diff --git a/gtk2_ardour/port_insert_ui.cc b/gtk2_ardour/port_insert_ui.cc index 0511b357db..3c495f0e79 100644 --- a/gtk2_ardour/port_insert_ui.cc +++ b/gtk2_ardour/port_insert_ui.cc @@ -66,7 +66,7 @@ PortInsertUI::PortInsertUI (Gtk::Window* parent, ARDOUR::Session* sess, boost::s void PortInsertUI::update_latency_display () { - framecnt_t const sample_rate = input_selector.session()->engine().frame_rate(); + framecnt_t const sample_rate = AudioEngine::instance()->sample_rate(); if (sample_rate == 0) { latency_display.set_text (_("Disconnected from audio engine")); } else { @@ -93,7 +93,7 @@ PortInsertUI::check_latency_measurement () } char buf[128]; - framecnt_t const sample_rate = AudioEngine::instance()->frame_rate(); + framecnt_t const sample_rate = AudioEngine::instance()->sample_rate(); if (sample_rate == 0) { latency_display.set_text (_("Disconnected from audio engine")); diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc index 77f0e2da01..07781fe7ee 100644 --- a/gtk2_ardour/processor_box.cc +++ b/gtk2_ardour/processor_box.cc @@ -2202,10 +2202,10 @@ ProcessorBox::register_actions () act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"), sigc::ptr_fun (ProcessorBox::rb_choose_insert)); - ActionManager::jack_sensitive_actions.push_back (act); + ActionManager::engine_sensitive_actions.push_back (act); act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New External Send ..."), sigc::ptr_fun (ProcessorBox::rb_choose_send)); - ActionManager::jack_sensitive_actions.push_back (act); + ActionManager::engine_sensitive_actions.push_back (act); ActionManager::register_action (popup_act_grp, X_("newaux"), _("New Aux Send ...")); diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index 98a4ffd014..ed9ffda4ef 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -31,8 +31,6 @@ #include "pbd/fpu.h" #include "pbd/cpus.h" -#include "midi++/manager.h" - #include "ardour/audioengine.h" #include "ardour/dB.h" #include "ardour/rc_configuration.h" @@ -1468,8 +1466,8 @@ RCOptionEditor::RCOptionEditor () #ifndef __APPLE__ /* no JACK monitoring on CoreAudio */ - if (AudioEngine::instance()->can_request_hardware_monitoring()) { - mm->add (HardwareMonitoring, _("JACK")); + if (AudioEngine::instance()->port_engine().can_monitor_input()) { + mm->add (HardwareMonitoring, _("via Audio Driver")); } #endif mm->add (SoftwareMonitoring, _("ardour")); diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc index bb10bea16f..76f3d4e264 100644 --- a/gtk2_ardour/route_params_ui.cc +++ b/gtk2_ardour/route_params_ui.cc @@ -277,7 +277,7 @@ RouteParams_UI::cleanup_latency_frame () void RouteParams_UI::setup_latency_frame () { - latency_widget = new LatencyGUI (*(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle()); + latency_widget = new LatencyGUI (*(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle()); char buf[128]; snprintf (buf, sizeof (buf), _("Playback delay: %" PRId64 " samples"), _route->initial_delay()); diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index 9494d42353..3b3f32ac04 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -1692,7 +1692,7 @@ RouteUI::map_frozen () void RouteUI::adjust_latency () { - LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle()); + LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle()); } void diff --git a/gtk2_ardour/startup.cc b/gtk2_ardour/startup.cc index e24e7d6989..266a7e2a27 100644 --- a/gtk2_ardour/startup.cc +++ b/gtk2_ardour/startup.cc @@ -34,6 +34,7 @@ #include "pbd/stacktrace.h" #include "pbd/openuri.h" +#include "ardour/audioengine.h" #include "ardour/filesystem_paths.h" #include "ardour/recent_sessions.h" #include "ardour/session.h" @@ -74,7 +75,6 @@ ArdourStartup::ArdourStartup (bool require_new, const std::string& session_name, , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n" "%1 will play NO role in monitoring"), PROGRAM_NAME)) , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME)) - , engine_dialog (0) , new_folder_chooser (FILE_CHOOSER_ACTION_SELECT_FOLDER) , more_new_session_options_button (_("I'd like more options for this session")) , _output_limit_count_adj (1, 0, 100, 1, 10, 0) @@ -91,13 +91,12 @@ ArdourStartup::ArdourStartup (bool require_new, const std::string& session_name, , _existing_session_chooser_used (false) { new_user = !Glib::file_test (been_here_before_path(), Glib::FILE_TEST_EXISTS); - need_audio_setup = EngineControl::need_setup (); need_session_info = (session_name.empty() || require_new); _provided_session_name = session_name; _provided_session_path = session_path; - if (need_audio_setup || need_session_info || new_user) { + if (need_session_info || new_user) { use_template_button.set_group (session_template_group); use_session_as_template_button.set_group (session_template_group); @@ -139,18 +138,10 @@ ArdourStartup::ArdourStartup (bool require_new, const std::string& session_name, setup_monitoring_choice_page (); setup_monitor_section_choice_page (); - if (need_audio_setup) { - setup_audio_page (); - } - ic_new_session_button.set_active (true); // always create new session on first run } else { - if (need_audio_setup) { - setup_audio_page (); - } - setup_initial_choice_page (); } @@ -183,7 +174,7 @@ ArdourStartup::~ArdourStartup () bool ArdourStartup::ready_without_display () const { - return !new_user && !need_audio_setup && !need_session_info; + return !new_user && !need_session_info; } void @@ -311,24 +302,6 @@ ArdourStartup::session_folder () } void -ArdourStartup::setup_audio_page () -{ - engine_dialog = manage (new EngineControl); - - engine_dialog->set_border_width (12); - - engine_dialog->show_all (); - - audio_page_index = append_page (*engine_dialog); - set_page_type (*engine_dialog, ASSISTANT_PAGE_CONTENT); - set_page_title (*engine_dialog, _("Audio / MIDI Setup")); - - /* the default parameters should work, so the page is potentially complete */ - - set_page_complete (*engine_dialog, true); -} - -void ArdourStartup::setup_new_user_page () { Label* foomatic = manage (new Label); @@ -403,8 +376,6 @@ Where would you like new %1 sessions to be stored by default?\n\n\ vbox->pack_start (*txt, false, false); vbox->pack_start (*hbox, false, true); - cerr << "Setting defaultDIR session dir to [" << Config->get_default_session_parent_dir() << "]\n"; - default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir())); default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed)); default_dir_chooser->show (); @@ -661,13 +632,6 @@ ArdourStartup::on_delete_event (GdkEventAny*) void ArdourStartup::on_apply () { - if (engine_dialog) { - if (engine_dialog->setup_engine ()) { - set_current_page (audio_page_index); - return; - } - } - if (config_modified) { if (default_dir_chooser) { diff --git a/gtk2_ardour/startup.h b/gtk2_ardour/startup.h index 4af6ffbc2a..4dcc3a9fb2 100644 --- a/gtk2_ardour/startup.h +++ b/gtk2_ardour/startup.h @@ -56,8 +56,6 @@ class ArdourStartup : public Gtk::Assistant { bool use_session_template(); std::string session_template_name(); - EngineControl* engine_control() { return engine_dialog; } - // advanced session options bool create_master_bus() const; @@ -82,7 +80,6 @@ class ArdourStartup : public Gtk::Assistant { gint _response; bool config_modified; bool new_user; - bool need_audio_setup; bool need_session_info; bool new_only; std::string _provided_session_name; @@ -175,11 +172,6 @@ class ArdourStartup : public Gtk::Assistant { void existing_session_selected (); - /* audio setup page */ - - void setup_audio_page (); - EngineControl* engine_dialog; - /* new sessions */ void setup_new_session_page (); diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index 93e4ee98c7..28e0907f44 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -395,7 +395,7 @@ emulate_key_event (Gtk::Widget* w, unsigned int keyval) ev.state = 0; ev.keyval = keyval; ev.length = 0; - ev.string = ""; + ev.string = (const gchar*) ""; ev.hardware_keycode = keymapkey[0].keycode; ev.group = keymapkey[0].group; g_free(keymapkey); diff --git a/gtk2_ardour/window_manager.cc b/gtk2_ardour/window_manager.cc index 5fa1b6c7b0..3ab9e1adff 100644 --- a/gtk2_ardour/window_manager.cc +++ b/gtk2_ardour/window_manager.cc @@ -410,7 +410,7 @@ ProxyBase::hide () } bool -ProxyBase::handle_win_event (GdkEventAny *ev) +ProxyBase::handle_win_event (GdkEventAny* /*ev*/) { hide(); return true; diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 12681cfe2d..a02e27f83d 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -520,6 +520,7 @@ def build(bld): 'SMALLER' : '9', 'SMALL' : '10', 'NORMAL' : '11', + 'BIG' : '13', 'BIGGER' : '17', 'LARGE' : '18', 'LARGER' : '28', @@ -545,6 +546,7 @@ def build(bld): 'SMALLER' : '8', 'SMALL' : '9', 'NORMAL' : '10', + 'BIG' : '14', 'BIGGER' : '17', 'LARGE' : '18', 'LARGER' : '24', |