*/
#ifdef HAVE_ALSA
-#include <alsa/asoundlib.h>
+#include "ardouralsautil/devicelist.h"
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
-#ifdef HAVE_PORTAUDIO
-#include <portaudio.h>
+#ifdef PLATFORM_WINDOWS
+#include <shobjidl.h> // Needed for
+#include <shlguid.h> // 'IShellLink'
#endif
-#include <jack/jack.h>
-
-#include <fstream>
+#if (defined PLATFORM_WINDOWS && defined HAVE_PORTAUDIO)
+#include <portaudio.h>
+#endif
#include <boost/scoped_ptr.hpp>
+#include "pbd/gstdio_compat.h"
#include <glibmm/miscutils.h>
#include "pbd/epa.h"
void
ARDOUR::get_jack_audio_driver_names (vector<string>& 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);
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;
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;
}
bool
ARDOUR::get_jack_server_application_names (std::vector<std::string>& server_names)
{
-#ifdef WIN32
+#ifdef PLATFORM_WINDOWS
server_names.push_back ("jackd.exe");
#else
server_names.push_back ("jackd");
#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", SearchPath(dirs).to_string().c_str(), 1);
+ setenv ("PATH", Searchpath(dirs).to_string().c_str(), 1);
#else
/* silence a compiler unused variable warning */
(void) dirs;
server_dir_paths.push_back (Glib::path_get_dirname (execpath));
#endif
- SearchPath sp(string(g_getenv("PATH")));
+ Searchpath sp(string(g_getenv("PATH")));
+
+#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
-#ifdef WIN32
gchar *install_dir = g_win32_get_package_installation_directory_of_module (NULL);
if (install_dir) {
sp.push_back (install_dir);
vector<std::string>& server_paths)
{
for (vector<string>::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();
}
}
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<string> 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);
args.push_back ("-v");
}
-#ifndef WIN32
if (options.temporary) {
args.push_back ("-T");
}
-#endif
if (options.driver == alsa_driver_name) {
if (options.midi_driver == alsa_seq_midi_driver_name) {
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));
}
}
- 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) {
}
}
- if (options.driver == alsa_driver_name || options.driver == coreaudio_driver_name) {
+ if (options.driver == alsa_driver_name) {
if (options.midi_driver != alsa_seq_midi_driver_name) {
if (!options.midi_driver.empty() && options.midi_driver != get_none_string ()) {
ostringstream oss;
for (vector<string>::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 << ' ';
}
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<string>
-ARDOUR::enumerate_midi_options ()
+ARDOUR::enumerate_midi_options ()
{
if (midi_options.empty()) {
#ifdef HAVE_ALSA
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));
vector<string> 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;
}