#include <glibmm.h>
#include <gtkmm/messagedialog.h>
-#include <pbd/xml++.h>
+#include "pbd/xml++.h"
#ifdef __APPLE__
#include <CoreAudio/CoreAudio.h>
#include <alsa/asoundlib.h>
#endif
-#include <ardour/profile.h>
+#include "ardour/profile.h"
#include <jack/jack.h>
#include <gtkmm/stock.h>
#include <gtkmm2ext/utils.h>
-#include <pbd/convert.h>
-#include <pbd/error.h>
-#include <pbd/pathscanner.h>
+#include "pbd/convert.h"
+#include "pbd/error.h"
+#include "pbd/pathscanner.h"
#ifdef __APPLE
#include <CFBundle.h>
basic_packer (8, 2),
options_packer (14, 2),
device_packer (6, 2)
-#endif
+#endif
{
using namespace Notebook_Helpers;
Label* label;
options_packer.attach (realtime_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
++row;
+ realtime_button.set_active (true);
realtime_button.signal_toggled().connect (mem_fun (*this, &EngineControl::realtime_changed));
realtime_changed ();
+#if PROVIDE_TOO_MANY_OPTIONS
+
#ifndef __APPLE__
label = manage (new Label (_("Realtime Priority")));
label->set_alignment (1.0, 0.5);
++row;
options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
++row;
-#else
+#else
options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
++row;
#endif
options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
++row;
+#endif /* PROVIDE_TOO_MANY_OPTIONS */
label = manage (new Label (_("Number of ports")));
label->set_alignment (1.0, 0.5);
options_packer.attach (ports_spinner, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
++row;
#ifndef __APPLE__
- label = manage (new Label (_("Dither")));
+ label = manage (new Label (_("Dither")));
label->set_alignment (1.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);
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());
label = manage (new Label (_("Output device")));
label->set_alignment (1.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);
+ device_packer.attach (output_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
++row;
#endif
label = manage (new Label (_("Input channels")));
/* 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;
- atof (str);
+ secs = atof (str);
msecs = (uint32_t) floor (secs * 1000.0);
- cmd.push_back ("-t");
- cmd.push_back (to_string (msecs, std::dec));
+ if (msecs > 0) {
+ cmd.push_back ("-t");
+ cmd.push_back (to_string (msecs, std::dec));
+ }
}
if (no_memory_lock_button.get_active()) {
cmd.push_back ("-m"); /* no munlock */
}
-
+
cmd.push_back ("-p"); /* port max */
cmd.push_back (to_string ((uint32_t) floor (ports_spinner.get_value()), std::dec));
if (verbose_output_button.get_active()) {
cmd.push_back ("-v");
}
-
+
/* now add fixed arguments (not user-selectable) */
cmd.push_back ("-T"); // temporary */
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 (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 ("-r");
cmd.push_back (to_string (get_rate(), std::dec));
-
+
cmd.push_back ("-p");
cmd.push_back (period_size_combo.get_active_text());
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()) {
cmd.push_back ("-M");
}
-
+
if (hw_monitor_button.get_active()) {
cmd.push_back ("-H");
}
if (force16bit_button.get_active()) {
cmd.push_back ("-S");
}
-
+
if (soft_mode_button.get_active()) {
cmd.push_back ("-s");
}
#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) {
build_command_line (args);
+ if (args.empty()) {
+ return 1; // try again
+ }
+
Glib::ustring jackdrc_path = Glib::get_home_dir();
jackdrc_path += "/.jackdrc";
error << string_compose (_("cannot open JACK rc file %1 to store parameters"), jackdrc_path) << endmsg;
return -1;
}
-
+ cerr << "JACK COMMAND: ";
for (vector<string>::iterator i = args.begin(); i != args.end(); ++i) {
+ cerr << (*i) << ' ';
jackdrc << (*i) << ' ';
}
+ cerr << endl;
jackdrc << endl;
jackdrc.close ();
/* note: case matters for the map keys */
if (driver == "CoreAudio") {
-#ifdef __APPLE__
+#ifdef __APPLE__
devices[driver] = enumerate_coreaudio_devices ();
#endif
}
#ifdef __APPLE__
-static OSStatus
+static OSStatus
getDeviceUIDFromID( AudioDeviceID id, char *name, size_t nsize)
{
UInt32 size = sizeof(CFStringRef);
CFStringRef UI;
OSStatus res = AudioDeviceGetProperty(id, 0, false,
kAudioDevicePropertyDeviceUID, &size, &UI);
- if (res == noErr)
+ if (res == noErr)
CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding());
CFRelease(UI);
return res;
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;
// 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);
- }
+ }
}
}
}
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);
vector<string>& strings = devices[driver];
- if (strings.empty() && driver != "FFADO") {
+ if (strings.empty() && driver != "FFADO" && driver != "Dummy") {
error << string_compose (_("No devices found for driver \"%1\""), driver) << endmsg;
return;
}
-
+
for (vector<string>::iterator i = strings.begin(); i != strings.end(); ++i, ++n) {
if ((*i).length() > maxlen) {
maxlen = (*i).length();
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);
force16bit_button.set_sensitive (true);
}
}
-static bool jack_server_filter(const string& str, void *arg)
+static bool jack_server_filter(const string& str, void */*arg*/)
{
return str == "jackd" || str == "jackdmp";
}
/* 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);
_NSGetExecutablePath (execpath, &pathsz);
-
- 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);
- }
+ }
if (getenv ("ARDOUR_WITH_JACK")) {
/* no other options - only use the JACK we supply */
#else
string path;
#endif
-
+
PathScanner scanner;
vector<string *> *jack_servers;
std::map<string,int> un;
-
- path = getenv ("PATH");
+ 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
jack_servers = scanner (path, jack_server_filter, 0, false, true);
-
+
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);
}
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.run ();
+ return string();
+ }
+
if (backend_devs.empty()) {
return human_readable;
}
-
+
for (i = devices[driver].begin(), n = backend_devs.begin(); i != devices[driver].end(); ++i, ++n) {
if (human_readable == (*i)) {
return (*n);
}
}
-
+
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();
}
child = new XMLNode ("outputdevice");
child->add_property ("val", output_device_combo.get_active_text());
root->add_child_nocopy (*child);
-
+
return *root;
}
XMLNode* child;
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) {
error << string_compose (_("AudioSetup value for %1 is missing data"), child->name()) << endmsg;
continue;
}
-
+
strval = prop->value();
/* adjustments/spinners */