X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fengine_dialog.cc;h=d6e6a52f4606e2cc6e5168b1f78b255a3ed9dc59;hb=153ee4e441eeebc9aceaa3121e4a785c6011a962;hp=05d953aeabc40742376c1107bdaf44cc6c360cc1;hpb=e98b3c1ec65f173f357f9b6747d11174e2743cd6;p=ardour.git diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc index 05d953aeab..d6e6a52f46 100644 --- a/gtk2_ardour/engine_dialog.cc +++ b/gtk2_ardour/engine_dialog.cc @@ -1,10 +1,33 @@ +/* + Copyright (C) 2010 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + #include #include #include #include +#include + #include #include + +#include "pbd/epa.h" #include "pbd/xml++.h" #ifdef __APPLE__ @@ -46,6 +69,10 @@ EngineControl::EngineControl () priority_spinner (priority_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")), @@ -115,6 +142,7 @@ EngineControl::EngineControl () #else strings.push_back (X_("ALSA")); strings.push_back (X_("OSS")); + strings.push_back (X_("FreeBoB")); strings.push_back (X_("FFADO")); #endif strings.push_back (X_("NetJACK")); @@ -122,73 +150,86 @@ EngineControl::EngineControl () set_popdown_strings (driver_combo, strings); driver_combo.set_active_text (strings.front()); - driver_combo.signal_changed().connect (mem_fun (*this, &EngineControl::driver_changed)); + 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/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 (mem_fun (*this, &EngineControl::audio_mode_changed)); + audio_mode_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::audio_mode_changed)); audio_mode_changed (); + strings.clear (); + strings.push_back (_("None")); + strings.push_back (_("seq")); + strings.push_back (_("raw")); + set_popdown_strings (midi_driver_combo, strings); + midi_driver_combo.set_active_text (strings.front ()); + row = 0; - label = manage (new Label (_("Driver"))); + label = manage (new Label (_("Driver:"))); + label->set_alignment (0, 0.5); 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); row++; - label = manage (new Label (_("Interface"))); + label = manage (new Label (_("Interface:"))); + label->set_alignment (0, 0.5); 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); row++; - label = manage (new Label (_("Sample Rate"))); + label = manage (new Label (_("Sample rate:"))); + label->set_alignment (0, 0.5); 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); row++; - label = manage (new Label (_("Buffer size"))); + label = manage (new Label (_("Buffer size:"))); + label->set_alignment (0, 0.5); 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++; #ifndef __APPLE__ - label = manage (new Label (_("Number of buffers"))); + label = manage (new Label (_("Number of buffers:"))); + label->set_alignment (0, 0.5); 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); row++; #endif - label = manage (new Label (_("Approximate latency"))); - label->set_alignment (0.0, 0.5); + label = manage (new Label (_("Approximate latency:"))); + label->set_alignment (0, 0.5); 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 (mem_fun (*this, &EngineControl::redisplay_latency)); - periods_adjustment.signal_value_changed().connect (mem_fun (*this, &EngineControl::redisplay_latency)); - period_size_combo.signal_changed().connect (mem_fun (*this, &EngineControl::redisplay_latency)); + 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' */ #ifndef __APPLE__ - label = manage (new Label (_("Audio Mode"))); + label = manage (new Label (_("Audio mode:"))); + label->set_alignment (0, 0.5); 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 (125, -1); - input_device_combo.set_size_request (125, -1); - output_device_combo.set_size_request (125, -1); + interface_combo.set_size_request (250, -1); + input_device_combo.set_size_request (250, -1); + output_device_combo.set_size_request (250, -1); /* @@ -198,8 +239,8 @@ EngineControl::EngineControl () stop_button.set_sensitive (false); } - start_button.signal_clicked().connect (mem_fun (*this, &EngineControl::start_engine)); - stop_button.signal_clicked().connect (mem_fun (*this, &EngineControl::start_engine)); + start_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::start_engine)); + stop_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::start_engine)); */ button_box.pack_start (start_button, false, false); @@ -216,7 +257,7 @@ EngineControl::EngineControl () ++row; realtime_button.set_active (true); - realtime_button.signal_toggled().connect (mem_fun (*this, &EngineControl::realtime_changed)); + realtime_button.signal_toggled().connect (sigc::mem_fun (*this, &EngineControl::realtime_changed)); realtime_changed (); #if PROVIDE_TOO_MANY_OPTIONS @@ -266,15 +307,21 @@ EngineControl::EngineControl () ++row; #endif /* PROVIDE_TOO_MANY_OPTIONS */ - label = manage (new Label (_("Number of ports"))); - label->set_alignment (1.0, 0.5); + label = manage (new Label (_("Number of ports:"))); + label->set_alignment (0, 0.5); 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); ++row; + label = manage (new Label (_("MIDI driver:"))); + label->set_alignment (0, 0.5); + 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; + #ifndef __APPLE__ - label = manage (new Label (_("Dither"))); - label->set_alignment (1.0, 0.5); + label = manage (new Label (_("Dither:"))); + label->set_alignment (0, 0.5); 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); ++row; @@ -304,36 +351,42 @@ EngineControl::EngineControl () row = 0; #ifndef __APPLE__ - label = manage (new Label (_("Input device"))); - label->set_alignment (1.0, 0.5); + label = manage (new Label (_("Input device:"))); + label->set_alignment (0, 0.5); 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); ++row; - label = manage (new Label (_("Output device"))); - label->set_alignment (1.0, 0.5); + label = manage (new Label (_("Output device:"))); + label->set_alignment (0, 0.5); 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 (new Label (_("Input channels"))); - label->set_alignment (1.0, 0.5); + label = manage (new Label (_("Input channels:"))); + label->set_alignment (0, 0.5); device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0); device_packer.attach (input_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0); ++row; - label = manage (new Label (_("Output channels"))); - label->set_alignment (1.0, 0.5); + label = manage (new Label (_("Output channels:"))); + label->set_alignment (0, 0.5); device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0); device_packer.attach (output_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0); ++row; - label = manage (new Label (_("Hardware input latency (samples)"))); - label->set_alignment (1.0, 0.5); + label = manage (new Label (_("Hardware input latency:"))); + label->set_alignment (0, 0.5); 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 (new Label (_("samples"))); + label->set_alignment (0, 0.5); + device_packer.attach (*label, 2, 3, row, row+1, FILL|EXPAND, (AttachOptions) 0); ++row; - label = manage (new Label (_("Hardware output latency (samples)"))); - label->set_alignment (1.0, 0.5); + label = manage (new Label (_("Hardware output latency:"))); + label->set_alignment (0, 0.5); 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 (new Label (_("samples"))); + label->set_alignment (0, 0.5); + device_packer.attach (*label, 2, 3, row, row+1, FILL|EXPAND, (AttachOptions) 0); ++row; basic_hbox.pack_start (basic_packer, false, false); @@ -362,12 +415,10 @@ EngineControl::build_command_line (vector& cmd) { string str; string driver; - bool using_oss = false; bool using_alsa = false; bool using_coreaudio = false; - bool using_netjack = false; - bool using_ffado = false; bool using_dummy = false; + bool using_ffado = false; /* first, path to jackd */ @@ -376,11 +427,14 @@ EngineControl::build_command_line (vector& cmd) /* 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); + if (msecs > 0) { cmd.push_back ("-t"); cmd.push_back (to_string (msecs, std::dec)); @@ -398,6 +452,8 @@ EngineControl::build_command_line (vector& cmd) cmd.push_back ("-R"); cmd.push_back ("-P"); cmd.push_back (to_string ((uint32_t) floor (priority_spinner.get_value()), std::dec)); + } else { + cmd.push_back ("-r"); /* override jackd's default --realtime */ } if (unlock_memory_button.get_active()) { @@ -417,31 +473,22 @@ EngineControl::build_command_line (vector& cmd) 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")) { - using_oss = true; cmd.push_back ("oss"); } else if (driver == X_("CoreAudio")) { using_coreaudio = true; cmd.push_back ("coreaudio"); } else if (driver == X_("NetJACK")) { - using_netjack = true; cmd.push_back ("netjack"); + } else if (driver == X_("FreeBoB")) { + cmd.push_back ("freebob"); } else if (driver == X_("FFADO")) { using_ffado = true; - - /* do this until FFADO becomes the standard */ - - char* hack = getenv ("ARDOUR_FIREWIRE_DRIVER_NAME"); - - if (hack) { - cmd.push_back (hack); - } else { - cmd.push_back ("freebob"); - } - + cmd.push_back ("firewire"); } else if ( driver == X_("Dummy")) { using_dummy = true; cmd.push_back ("dummy"); @@ -468,6 +515,7 @@ EngineControl::build_command_line (vector& cmd) cmd.push_back ("-C"); cmd.push_back (input_device); + cmd.push_back ("-P"); cmd.push_back (output_device); @@ -477,7 +525,7 @@ EngineControl::build_command_line (vector& cmd) cmd.push_back ("-C"); } - if (! using_dummy ) { + if (!using_dummy) { cmd.push_back ("-n"); cmd.push_back (to_string ((uint32_t) floor (periods_spinner.get_value()), std::dec)); } @@ -489,6 +537,23 @@ EngineControl::build_command_line (vector& cmd) cmd.push_back ("-p"); cmd.push_back (period_size_combo.get_active_text()); + if (using_alsa || using_ffado || using_coreaudio) { + + 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(); + + if (val) { + cmd.push_back ("-O"); + cmd.push_back (to_string ((uint32_t) val, std::dec)); + } + } + if (using_alsa) { if (audio_mode_combo.get_active_text() != _("Playback/Recording on 2 Devices")) { @@ -530,6 +595,13 @@ EngineControl::build_command_line (vector& cmd) cmd.push_back ("-s"); } + str = midi_driver_combo.get_active_text (); + + if (str == _("seq")) { + cmd.push_back ("-X seq"); + } else if (str == _("raw")) { + cmd.push_back ("-X raw"); + } } else if (using_coreaudio) { #ifdef __APPLE__ @@ -545,16 +617,23 @@ EngineControl::build_command_line (vector& cmd) cmd.push_back (device); #endif - } else if (using_oss) { - - } else if (using_netjack) { - } } bool EngineControl::engine_running () { + EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa (); + boost::scoped_ptr current_epa; + + /* revert all environment settings back to whatever they were when ardour started + */ + + if (global_epa) { + current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */ + global_epa->restore (); + } + jack_status_t status; jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status); @@ -577,7 +656,7 @@ EngineControl::setup_engine () return 1; // try again } - Glib::ustring jackdrc_path = Glib::get_home_dir(); + std::string jackdrc_path = Glib::get_home_dir(); jackdrc_path += "/.jackdrc"; ofstream jackdrc (jackdrc_path.c_str()); @@ -620,6 +699,8 @@ EngineControl::enumerate_devices (const string& driver) #ifndef __APPLE__ } 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") { @@ -771,28 +852,11 @@ EngineControl::enumerate_alsa_devices () while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) { - bool have_playback = false; - bool have_capture = false; - - /* find duplex devices only */ - - snd_pcm_info_set_device (pcminfo, device); - snd_pcm_info_set_subdevice (pcminfo, 0); - snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_CAPTURE); - - if (snd_ctl_pcm_info (handle, pcminfo) >= 0) { - have_capture = true; - } - snd_pcm_info_set_device (pcminfo, device); snd_pcm_info_set_subdevice (pcminfo, 0); snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK); if (snd_ctl_pcm_info (handle, pcminfo) >= 0) { - have_playback = true; - } - - if (have_capture && have_playback) { devs.push_back (snd_pcm_info_get_name (pcminfo)); devname += ','; devname += to_string (device, std::dec); @@ -821,6 +885,7 @@ EngineControl::enumerate_freebob_devices () vector devs; return devs; } + vector EngineControl::enumerate_oss_devices () { @@ -846,22 +911,19 @@ EngineControl::driver_changed () { string driver = driver_combo.get_active_text(); string::size_type maxlen = 0; - int maxindex = -1; int n = 0; enumerate_devices (driver); vector& strings = devices[driver]; - if (strings.empty() && driver != "FFADO" && driver != "Dummy") { - error << string_compose (_("No devices found for driver \"%1\""), driver) << endmsg; + if (strings.empty() && driver != "FreeBoB" && driver != "FFADO" && driver != "Dummy") { return; } for (vector::iterator i = strings.begin(); i != strings.end(); ++i, ++n) { if ((*i).length() > maxlen) { maxlen = (*i).length(); - maxindex = n; } } @@ -911,12 +973,13 @@ EngineControl::redisplay_latency () snprintf (buf, sizeof(buf), "%.1fmsec", (periods * period_size) / (rate/1000.0)); latency_label.set_text (buf); + latency_label.set_alignment (0, 0.5); } void EngineControl::audio_mode_changed () { - Glib::ustring str = audio_mode_combo.get_active_text(); + std::string str = audio_mode_combo.get_active_text(); if (str == _("Playback/Recording on 1 Device")) { input_device_combo.set_sensitive (false); @@ -959,7 +1022,7 @@ EngineControl::find_jack_servers (vector& strings) if (getenv ("ARDOUR_WITH_JACK")) { /* no other options - only use the JACK we supply */ if (strings.empty()) { - fatal << _("JACK appears to be missing from the Ardour bundle") << endmsg; + fatal << string_compose (_("JACK appears to be missing from the %1 bundle"), PROGRAM_NAME) << endmsg; /*NOTREACHED*/ } return; @@ -1053,7 +1116,7 @@ EngineControl::get_state () { XMLNode* root = new XMLNode ("AudioSetup"); XMLNode* child; - Glib::ustring path; + std::string path; child = new XMLNode ("periods"); child->add_property ("val", to_string (periods_adjustment.get_value(), std::dec)); @@ -1155,6 +1218,10 @@ EngineControl::get_state () child->add_property ("val", output_device_combo.get_active_text()); root->add_child_nocopy (*child); + child = new XMLNode ("mididriver"); + child->add_property ("val", midi_driver_combo.get_active_text()); + root->add_child_nocopy (*child); + return *root; } @@ -1166,15 +1233,21 @@ EngineControl::set_state (const XMLNode& root) 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 (prop && (prop->value() == "Dummy") ) { using_dummy = true; } + if (prop && (prop->value() == "FFADO") ) { + using_ffado = true; + } + } clist = root.children(); @@ -1187,8 +1260,15 @@ EngineControl::set_state (const XMLNode& root) if (!prop || prop->value().empty()) { - if ( using_dummy && ( child->name() == "interface" || child->name() == "inputdevice" || child->name() == "outputdevice" )) + 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; } @@ -1255,24 +1335,34 @@ EngineControl::set_state (const XMLNode& root) } else if (child->name() == "periodsize") { period_size_combo.set_active_text(strval); } else if (child->name() == "serverpath") { - /* 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::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; - } + + /* 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::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") { @@ -1287,6 +1377,8 @@ EngineControl::set_state (const XMLNode& root) 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); } } }