X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fengine_dialog.cc;h=7d8f29cce46c3c5f2a11b27e2033c03fa4b97884;hb=e11b3f90c2d02735a071d526d67cfd0de90cbac3;hp=8a8f99f7459542463fc3e4e91278603da23ff675;hpb=a29a10c02ad52e69584e3a5d1a332e83a72dedc0;p=ardour.git diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc index 8a8f99f745..7d8f29cce4 100644 --- a/gtk2_ardour/engine_dialog.cc +++ b/gtk2_ardour/engine_dialog.cc @@ -1,8 +1,10 @@ #include #include #include +#include #include +#include #include #ifdef __APPLE__ @@ -22,6 +24,7 @@ #include #include +#include #ifdef __APPLE #include @@ -113,16 +116,12 @@ EngineControl::EngineControl () strings.push_back (X_("ALSA")); strings.push_back (X_("OSS")); strings.push_back (X_("FFADO")); - strings.push_back (X_("FreeBoB")); #endif strings.push_back (X_("NetJACK")); strings.push_back (X_("Dummy")); set_popdown_strings (driver_combo, strings); driver_combo.set_active_text (strings.front()); - /* figure out available devices and set up interface_combo */ - - enumerate_devices (); driver_combo.signal_changed().connect (mem_fun (*this, &EngineControl::driver_changed)); driver_changed (); @@ -364,7 +363,7 @@ EngineControl::build_command_line (vector& cmd) bool using_coreaudio = false; bool using_netjack = false; bool using_ffado = false; - bool using_freebob = false; + bool using_dummy = false; /* first, path to jackd */ @@ -374,7 +373,7 @@ EngineControl::build_command_line (vector& cmd) str = timeout_combo.get_active_text (); if (str != _("Ignore")) { - double secs; + double secs = 0; uint32_t msecs; atof (str); msecs = (uint32_t) floor (secs * 1000.0); @@ -426,10 +425,20 @@ EngineControl::build_command_line (vector& cmd) cmd.push_back ("netjack"); } else if (driver == X_("FFADO")) { using_ffado = true; - cmd.push_back ("firewire"); - } else if (driver == X_("FreeBoB")) { - using_freebob = true; - cmd.push_back ("freebob"); + + /* 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"); + } + + } else if ( driver == X_("Dummy")) { + using_dummy = true; + cmd.push_back ("dummy"); } /* driver arguments */ @@ -443,19 +452,29 @@ EngineControl::build_command_line (vector& cmd) } 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 (get_device_name (driver, input_device_combo.get_active_text())); + cmd.push_back (input_device); cmd.push_back ("-P"); - cmd.push_back (get_device_name (driver, output_device_combo.get_active_text())); - + cmd.push_back (output_device); + } else if (str == _("Playback only")) { cmd.push_back ("-P"); } else if (str == _("Recording only")) { cmd.push_back ("-C"); } - cmd.push_back ("-n"); - cmd.push_back (to_string ((uint32_t) floor (periods_spinner.get_value()), std::dec)); + if (! using_dummy ) { + cmd.push_back ("-n"); + cmd.push_back (to_string ((uint32_t) floor (periods_spinner.get_value()), std::dec)); + } } cmd.push_back ("-r"); @@ -467,8 +486,15 @@ EngineControl::build_command_line (vector& cmd) if (using_alsa) { 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; + } + cmd.push_back ("-d"); - cmd.push_back (get_device_name (driver, interface_combo.get_active_text())); + cmd.push_back (device); } if (hw_meter_button.get_active()) { @@ -502,8 +528,15 @@ EngineControl::build_command_line (vector& cmd) #ifdef __APPLE__ // note: older versions of the CoreAudio JACK backend use -n instead of -d here + + string device = get_device_name (driver, interface_combo.get_active_text()); + if (device.empty()) { + cmd.clear (); + return; + } + cmd.push_back ("-d"); - cmd.push_back (get_device_name (driver, interface_combo.get_active_text())); + cmd.push_back (device); #endif } else if (using_oss) { @@ -533,6 +566,10 @@ EngineControl::setup_engine () std::string cwd = "/tmp"; build_command_line (args); + + if (args.empty()) { + return 1; // try again + } Glib::ustring jackdrc_path = Glib::get_home_dir(); jackdrc_path += "/.jackdrc"; @@ -542,10 +579,12 @@ EngineControl::setup_engine () error << string_compose (_("cannot open JACK rc file %1 to store parameters"), jackdrc_path) << endmsg; return -1; } - + cerr << "JACK COMMAND: "; for (vector::iterator i = args.begin(); i != args.end(); ++i) { + cerr << (*i) << ' '; jackdrc << (*i) << ' '; } + cerr << endl; jackdrc << endl; jackdrc.close (); @@ -563,19 +602,29 @@ EngineControl::realtime_changed () } void -EngineControl::enumerate_devices () +EngineControl::enumerate_devices (const string& driver) { /* note: case matters for the map keys */ -#ifdef __APPLE__ - devices["CoreAudio"] = enumerate_coreaudio_devices (); + if (driver == "CoreAudio") { +#ifdef __APPLE__ + devices[driver] = enumerate_coreaudio_devices (); +#endif + +#ifndef __APPLE__ + } else if (driver == "ALSA") { + devices[driver] = enumerate_alsa_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 (); + } #else - devices["ALSA"] = enumerate_alsa_devices (); - devices["FFADO"] = enumerate_ffado_devices (); - devices["FreeBoB"] = enumerate_freebob_devices (); - devices["OSS"] = enumerate_oss_devices (); - devices["Dummy"] = enumerate_dummy_devices (); - devices["NetJACK"] = enumerate_netjack_devices (); + } #endif } @@ -619,10 +668,29 @@ EngineControl::enumerate_coreaudio_devices () // Look for the CoreAudio device name... char coreDeviceName[256]; size_t 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); @@ -647,6 +715,28 @@ EngineControl::enumerate_coreaudio_devices () delete [] coreDeviceIDs; } + + if (devs.size() == 0) { + MessageDialog msg (_("\ +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\ +Ardour and choose the relevant device then." + ), + 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); + } + + return devs; } #else @@ -715,8 +805,10 @@ vector EngineControl::enumerate_ffado_devices () { vector devs; + backend_devs.clear (); return devs; } + vector EngineControl::enumerate_freebob_devices () { @@ -747,11 +839,19 @@ void EngineControl::driver_changed () { string driver = driver_combo.get_active_text(); - vector& strings = devices[driver]; 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; + return; + } + for (vector::iterator i = strings.begin(); i != strings.end(); ++i, ++n) { if ((*i).length() > maxlen) { maxlen = (*i).length(); @@ -767,7 +867,7 @@ EngineControl::driver_changed () interface_combo.set_active_text (strings.front()); input_device_combo.set_active_text (strings.front()); output_device_combo.set_active_text (strings.front()); - } + } if (driver == "ALSA") { soft_mode_button.set_sensitive (true); @@ -825,6 +925,11 @@ EngineControl::audio_mode_changed () } } +static bool jack_server_filter(const string& str, void *arg) +{ + return str == "jackd" || str == "jackdmp"; +} + void EngineControl::find_jack_servers (vector& strings) { @@ -838,14 +943,11 @@ EngineControl::find_jack_servers (vector& strings) _NSGetExecutablePath (execpath, &pathsz); - cerr << " execpath = " << execpath << endl; - - Glib::ustring path (Glib::path_get_dirname (execpath)); + string path (Glib::path_get_dirname (execpath)); path += "/jackd"; if (Glib::file_test (path, FILE_TEST_EXISTS)) { strings.push_back (path); - cerr << "Found jack in " << path << endl; } if (getenv ("ARDOUR_WITH_JACK")) { @@ -856,35 +958,73 @@ EngineControl::find_jack_servers (vector& strings) } return; } +#else + string path; #endif - if (Glib::file_test ("/usr/bin/jackd", FILE_TEST_EXISTS)) { - strings.push_back ("/usr/bin/jackd"); - } - if (Glib::file_test ("/usr/local/bin/jackd", FILE_TEST_EXISTS)) { - strings.push_back ("/usr/local/bin/jackd"); - } - if (Glib::file_test ("/opt/bin/jackd", FILE_TEST_EXISTS)) { - strings.push_back ("/opt/bin/jackd"); - } - if (Glib::file_test ("/usr/bin/jackdmp", FILE_TEST_EXISTS)) { - strings.push_back ("/usr/bin/jackd"); - } - if (Glib::file_test ("/usr/local/bin/jackdmp", FILE_TEST_EXISTS)) { - strings.push_back ("/usr/local/bin/jackd"); + PathScanner scanner; + vector *jack_servers; + std::map un; + char *p; + bool need_minimal_path = false; + + p = getenv ("PATH"); + + if (p && *p) { + path = p; + } else { + need_minimal_path = true; } - if (Glib::file_test ("/opt/bin/jackdmp", FILE_TEST_EXISTS)) { - strings.push_back ("/opt/bin/jackd"); + +#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 + + jack_servers = scanner (path, jack_server_filter, 0, false, true); + + vector::iterator iter; + + for (iter = jack_servers->begin(); iter != jack_servers->end(); iter++) { + string p = **iter; + + if (un[p]++ == 0) { + strings.push_back(p); + } + } } + string EngineControl::get_device_name (const string& driver, const string& human_readable) { vector::iterator n; vector::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.run (); + return string(); + } + if (backend_devs.empty()) { return human_readable; } @@ -896,12 +1036,9 @@ EngineControl::get_device_name (const string& driver, const string& human_readab } if (i == devices[driver].end()) { - fatal << string_compose (_("programming error: %1"), "true hardware name for ID missing") << endmsg; - /*NOTREACHED*/ + warning << string_compose (_("Audio device \"%1\" not known on this computer."), human_readable) << endmsg; } - /* keep gcc happy */ - return string(); } @@ -1021,20 +1158,32 @@ EngineControl::set_state (const XMLNode& root) XMLNodeList clist; XMLNodeConstIterator citer; XMLNode* child; - XMLProperty* prop; - + XMLProperty* prop = NULL; + bool using_dummy = false; + int val; string strval; - + + if ( (child = root.child ("driver"))){ + prop = child->property("val"); + if (prop && (prop->value() == "Dummy") ) { + using_dummy = true; + } + } + clist = root.children(); for (citer = clist.begin(); citer != clist.end(); ++citer) { - + if ( prop && (prop->value() == "FFADO" )) + continue; child = *citer; prop = child->property ("val"); if (!prop || prop->value().empty()) { + + if ( using_dummy && ( child->name() == "interface" || child->name() == "inputdevice" || child->name() == "outputdevice" )) + continue; error << string_compose (_("AudioSetup value for %1 is missing data"), child->name()) << endmsg; continue; }