X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fbackends%2Fjack%2Fjack_utils.cc;h=b26cb4036797194112457aba6ea1c4a53396773a;hb=cf52d6e4b40111eb04b244ec054055a4ec15dbe0;hp=83919eadb677e49605e683771cc90553d5e1d300;hpb=69a8fc43e2552d9d3c72f9117131ca6b9392093b;p=ardour.git diff --git a/libs/backends/jack/jack_utils.cc b/libs/backends/jack/jack_utils.cc index 83919eadb6..b26cb40367 100644 --- a/libs/backends/jack/jack_utils.cc +++ b/libs/backends/jack/jack_utils.cc @@ -19,7 +19,7 @@ */ #ifdef HAVE_ALSA -#include +#include "ardouralsautil/devicelist.h" #endif #ifdef __APPLE__ @@ -29,16 +29,18 @@ #include #endif -#ifdef HAVE_PORTAUDIO -#include +#ifdef PLATFORM_WINDOWS +#include // Needed for +#include // 'IShellLink' #endif -#include - -#include +#if (defined PLATFORM_WINDOWS && defined HAVE_PORTAUDIO) +#include +#endif #include +#include "pbd/gstdio_compat.h" #include #include "pbd/epa.h" @@ -53,7 +55,7 @@ #include #endif -#include "i18n.h" +#include "pbd/i18n.h" using namespace std; using namespace PBD; @@ -83,7 +85,8 @@ namespace { const char * const dummy_driver_command_line_name = X_("dummy"); // should we provide more "pretty" names like above? - const char * const alsaint_midi_driver_name = X_("alsa"); + const char * const alsa_seq_midi_driver_name = X_("alsa"); + const char * const alsa_raw_midi_driver_name = X_("alsarawmidi"); const char * const alsaseq_midi_driver_name = X_("seq"); const char * const alsaraw_midi_driver_name = X_("raw"); const char * const winmme_midi_driver_name = X_("winmme"); @@ -104,7 +107,7 @@ get_none_string () void ARDOUR::get_jack_audio_driver_names (vector& audio_driver_names) { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS audio_driver_names.push_back (portaudio_driver_name); #elif __APPLE__ audio_driver_names.push_back (coreaudio_driver_name); @@ -270,60 +273,7 @@ void ARDOUR::get_jack_alsa_device_names (device_map_t& devices) { #ifdef HAVE_ALSA - 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; - - while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) { - - devname = "hw:"; - devname += PBD::to_string (cardnum, std::dec); - - if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 0) { - - if (snd_ctl_card_info (handle, info) < 0) { - continue; - } - - string card_name = snd_ctl_card_info_get_name (info); - - /* change devname to use ID, not number */ - - devname = "hw:"; - devname += snd_ctl_card_info_get_id (info); - - while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) { - - /* only detect duplex devices here. more - * complex arrangements are beyond our scope - */ - - 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) { - - 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) { - devname += ','; - devname += PBD::to_string (device, std::dec); - devices.insert (std::make_pair (card_name, devname)); - } - } - } - - snd_ctl_close(handle); - } - } + get_alsa_audio_device_names(devices); #else /* silence a compiler unused variable warning */ (void) devices; @@ -422,7 +372,7 @@ ARDOUR::get_jack_coreaudio_device_names (device_map_t& devices) void ARDOUR::get_jack_portaudio_device_names (device_map_t& devices) { -#ifdef HAVE_PORTAUDIO +#if (defined PLATFORM_WINDOWS && defined HAVE_PORTAUDIO) if (Pa_Initialize() != paNoError) { return; } @@ -542,7 +492,7 @@ ARDOUR::get_jack_audio_driver_supports_setting_period_count (const string& drive bool ARDOUR::get_jack_server_application_names (std::vector& server_names) { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS server_names.push_back ("jackd.exe"); #else server_names.push_back ("jackd"); @@ -582,7 +532,61 @@ ARDOUR::get_jack_server_dir_paths (vector& server_dir_paths) Searchpath sp(string(g_getenv("PATH"))); -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS +// N.B. The #define (immediately below) can be safely removed once we know that this code builds okay with mingw +#ifdef COMPILER_MSVC + IShellLinkA *pISL = NULL; + IPersistFile *ppf = NULL; + + // Mixbus creates a Windows shortcut giving the location of its + // own (bundled) version of Jack. Let's see if that shortcut exists + if (SUCCEEDED (CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pISL))) + { + if (SUCCEEDED (pISL->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf))) + { + char target_path[MAX_PATH]; + char shortcut_pathA[MAX_PATH]; + WCHAR shortcut_pathW[MAX_PATH]; + + // Our Windows installer should have created a shortcut to the Jack + // server so let's start by finding out what drive it got installed on + if (char *env_path = getenv ("windir")) + { + strcpy (shortcut_pathA, env_path); + shortcut_pathA[2] = '\0'; // Gives us just the drive letter and colon + } + else // Assume 'C:' + strcpy (shortcut_pathA, "C:"); + + strcat (shortcut_pathA, "\\Program Files (x86)\\Jack\\Start Jack.lnk"); + + MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, shortcut_pathA, -1, shortcut_pathW, MAX_PATH); + + // If it did, load the shortcut into our persistent file + if (SUCCEEDED (ppf->Load(shortcut_pathW, 0))) + { + // Read the target information from the shortcut object + if (S_OK == (pISL->GetPath (target_path, MAX_PATH, NULL, SLGP_UNCPRIORITY))) + { + char *p = strrchr (target_path, '\\'); + + if (p) + { + *p = NULL; + sp.push_back (target_path); + } + } + } + } + } + + if (ppf) + ppf->Release(); + + if (pISL) + pISL->Release(); +#endif + gchar *install_dir = g_win32_get_package_installation_directory_of_module (NULL); if (install_dir) { sp.push_back (install_dir); @@ -609,8 +613,7 @@ ARDOUR::get_jack_server_paths (const vector& server_dir_paths, vector& server_paths) { for (vector::const_iterator i = server_names.begin(); i != server_names.end(); ++i) { - Glib::PatternSpec ps (*i); - find_matching_files_in_directories (server_dir_paths, ps, server_paths); + find_files_matching_pattern (server_paths, server_dir_paths, *i); } return !server_paths.empty(); } @@ -685,17 +688,19 @@ ARDOUR::JackCommandLineOptions::JackCommandLineOptions () } bool -ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& command_line, bool for_latency_measurement) +ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& command_line) { vector args; args.push_back (options.server_path); -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS // must use sync mode on windows args.push_back ("-S"); +#endif - // this needs to be added now on windows +#if (defined PLATFORM_WINDOWS || defined __APPLE__) + // midi systems needs to be added before the audio driver for jack2 if (!options.midi_driver.empty () && options.midi_driver != get_none_string ()) { args.push_back ("-X"); args.push_back (options.midi_driver); @@ -737,21 +742,25 @@ ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& c args.push_back ("-v"); } -#ifndef WIN32 if (options.temporary) { args.push_back ("-T"); } -#endif if (options.driver == alsa_driver_name) { - if (options.midi_driver == alsaint_midi_driver_name) { - args.push_back ("-I"); + if (options.midi_driver == alsa_seq_midi_driver_name) { + args.push_back ("-X"); args.push_back ("alsa_midi"); + } else if (options.midi_driver == alsa_raw_midi_driver_name) { + args.push_back ("-X"); + args.push_back ("alsarawmidi"); } } string command_line_driver_name; + string command_line_input_device_name; + string command_line_output_device_name; + if (!get_jack_command_line_audio_driver_name (options.driver, command_line_driver_name)) { return false; } @@ -759,60 +768,71 @@ ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& c args.push_back ("-d"); args.push_back (command_line_driver_name); - if (options.output_device.empty() && options.input_device.empty()) { - return false; - } - - string command_line_input_device_name; - string command_line_output_device_name; - - if (!get_jack_command_line_audio_device_name (options.driver, - options.input_device, command_line_input_device_name)) { - return false; - } + if (options.driver != dummy_driver_name) { + if (options.output_device.empty() && options.input_device.empty()) { + return false; + } - if (!get_jack_command_line_audio_device_name (options.driver, - options.output_device, command_line_output_device_name)) { - return false; - } - if (options.input_device.empty()) { - // playback only - if (options.output_device.empty()) { + if (!get_jack_command_line_audio_device_name (options.driver, + options.input_device, command_line_input_device_name)) { return false; } - args.push_back ("-P"); - } else if (options.output_device.empty()) { - // capture only - if (options.input_device.empty()) { + + if (!get_jack_command_line_audio_device_name (options.driver, + options.output_device, command_line_output_device_name)) { return false; } - args.push_back ("-C"); - } else if (options.input_device != options.output_device) { - // capture and playback on two devices if supported - if (get_jack_audio_driver_supports_two_devices (options.driver)) { - args.push_back ("-C"); - args.push_back (command_line_input_device_name); + + if (options.input_device.empty()) { + // playback only + if (options.output_device.empty()) { + return false; + } args.push_back ("-P"); - args.push_back (command_line_output_device_name); - } else { - return false; + } else if (options.output_device.empty()) { + // capture only + if (options.input_device.empty()) { + return false; + } + args.push_back ("-C"); + } else if (options.input_device != options.output_device) { + // capture and playback on two devices if supported + if (get_jack_audio_driver_supports_two_devices (options.driver)) { + args.push_back ("-C"); + args.push_back (command_line_input_device_name); + args.push_back ("-P"); + args.push_back (command_line_output_device_name); + } else { + return false; + } } - } - if (options.input_channels) { - args.push_back ("-i"); - args.push_back (to_string (options.input_channels, std::dec)); - } + if (options.input_channels) { + args.push_back ("-i"); + args.push_back (to_string (options.input_channels, std::dec)); + } - if (options.output_channels) { - args.push_back ("-o"); - args.push_back (to_string (options.output_channels, std::dec)); - } + if (options.output_channels) { + args.push_back ("-o"); + args.push_back (to_string (options.output_channels, std::dec)); + } + + if (get_jack_audio_driver_supports_setting_period_count (options.driver)) { + args.push_back ("-n"); + args.push_back (to_string (options.num_periods, std::dec)); + } + } else { + // jackd dummy backend + if (options.input_channels) { + args.push_back ("-C"); + args.push_back (to_string (options.input_channels, std::dec)); + } - if (get_jack_audio_driver_supports_setting_period_count (options.driver)) { - args.push_back ("-n"); - args.push_back (to_string (options.num_periods, std::dec)); + if (options.output_channels) { + args.push_back ("-P"); + args.push_back (to_string (options.output_channels, std::dec)); + } } args.push_back ("-r"); @@ -821,7 +841,7 @@ ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& c args.push_back ("-p"); args.push_back (to_string (options.period_size, std::dec)); - if (!for_latency_measurement && get_jack_audio_driver_supports_latency_adjustment (options.driver)) { + if (get_jack_audio_driver_supports_latency_adjustment (options.driver)) { if (options.input_latency) { args.push_back ("-I"); args.push_back (to_string (options.input_latency, std::dec)); @@ -832,9 +852,11 @@ ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& c } } - if (options.input_device == options.output_device && options.input_device != default_device_name) { - args.push_back ("-d"); - args.push_back (command_line_input_device_name); + if (options.driver != dummy_driver_name) { + if (options.input_device == options.output_device && options.input_device != default_device_name) { + args.push_back ("-d"); + args.push_back (command_line_input_device_name); + } } if (options.driver == alsa_driver_name) { @@ -858,9 +880,9 @@ ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& c } } - if (options.driver == alsa_driver_name || options.driver == coreaudio_driver_name) { + if (options.driver == alsa_driver_name) { - if (options.midi_driver != alsaint_midi_driver_name) { + if (options.midi_driver != alsa_seq_midi_driver_name) { if (!options.midi_driver.empty() && options.midi_driver != get_none_string ()) { args.push_back ("-X"); args.push_back (options.midi_driver); @@ -871,11 +893,11 @@ ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& c ostringstream oss; for (vector::const_iterator i = args.begin(); i != args.end();) { -#ifdef WIN32 - oss << quote_string (*i); -#else - oss << *i; -#endif + if (i->find_first_of(' ') != string::npos) { + oss << "\"" << *i << "\""; + } else { + oss << *i; + } if (++i != args.end()) oss << ' '; } @@ -904,32 +926,28 @@ ARDOUR::get_jack_server_user_config_file_path () bool ARDOUR::write_jack_config_file (const std::string& config_file_path, const string& command_line) { - ofstream jackdrc (config_file_path.c_str()); - - if (!jackdrc) { + if (!g_file_set_contents (config_file_path.c_str(), command_line.c_str(), -1, NULL)) { error << string_compose (_("cannot open JACK rc file %1 to store parameters"), config_file_path) << endmsg; return false; } - - jackdrc << command_line << endl; - jackdrc.close (); return true; } vector -ARDOUR::enumerate_midi_options () +ARDOUR::enumerate_midi_options () { if (midi_options.empty()) { #ifdef HAVE_ALSA - midi_options.push_back (make_pair (_("ALSA"), alsaint_midi_driver_name)); midi_options.push_back (make_pair (_("(legacy) ALSA raw devices"), alsaraw_midi_driver_name)); midi_options.push_back (make_pair (_("(legacy) ALSA sequencer"), alsaseq_midi_driver_name)); + midi_options.push_back (make_pair (_("ALSA (JACK1, 0.124 and later)"), alsa_seq_midi_driver_name)); + midi_options.push_back (make_pair (_("ALSA (JACK2, 1.9.8 and later)"), alsa_raw_midi_driver_name)); #endif -#ifdef HAVE_PORTAUDIO +#if (defined PLATFORM_WINDOWS && defined HAVE_PORTAUDIO) /* Windows folks: what name makes sense here? Are there other choices as well ? */ - midi_options.push_back (make_pair (_("Multimedia Extension"), winmme_midi_driver_name)); + midi_options.push_back (make_pair (_("System MIDI (MME)"), winmme_midi_driver_name)); #endif #ifdef __APPLE__ midi_options.push_back (make_pair (_("CoreMIDI"), coremidi_midi_driver_name)); @@ -938,12 +956,12 @@ ARDOUR::enumerate_midi_options () vector v; - v.push_back (get_none_string()); - for (MidiOptions::const_iterator i = midi_options.begin(); i != midi_options.end(); ++i) { v.push_back (i->first); } + v.push_back (get_none_string()); + return v; }