summaryrefslogtreecommitdiff
path: root/libs/backends/jack
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2013-10-16 22:06:56 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2013-10-16 22:06:56 -0400
commite5888d398350b26ba2cdc634cc9791e90b4fc6b6 (patch)
tree54f485ea56d034ecba01938fbc680b12884fc136 /libs/backends/jack
parent18850253e9f0034fad132e0da07a2651ce041450 (diff)
parentda5a49067839ec32a016bf1b66c3808ad7cbf699 (diff)
merge with master and fix 2 conflicts
Diffstat (limited to 'libs/backends/jack')
-rw-r--r--libs/backends/jack/jack_api.cc2
-rw-r--r--libs/backends/jack/jack_audiobackend.cc111
-rw-r--r--libs/backends/jack/jack_audiobackend.h28
-rw-r--r--libs/backends/jack/jack_connection.cc36
-rw-r--r--libs/backends/jack/jack_connection.h6
-rw-r--r--libs/backends/jack/jack_session.cc193
-rw-r--r--libs/backends/jack/jack_session.h47
-rw-r--r--libs/backends/jack/jack_utils.cc80
-rw-r--r--libs/backends/jack/jack_utils.h7
-rw-r--r--libs/backends/jack/wscript5
10 files changed, 451 insertions, 64 deletions
diff --git a/libs/backends/jack/jack_api.cc b/libs/backends/jack/jack_api.cc
index 836acfda11..c8859a1fc9 100644
--- a/libs/backends/jack/jack_api.cc
+++ b/libs/backends/jack/jack_api.cc
@@ -63,7 +63,7 @@ deinstantiate ()
static bool
already_configured ()
{
- return JackConnection::server_running ();
+ return !JackConnection::in_control ();
}
static ARDOUR::AudioBackendInfo _descriptor = {
diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc
index 1e7cb9d8d5..ff76486bad 100644
--- a/libs/backends/jack/jack_audiobackend.cc
+++ b/libs/backends/jack/jack_audiobackend.cc
@@ -37,6 +37,7 @@
#include "jack_audiobackend.h"
#include "jack_connection.h"
#include "jack_utils.h"
+#include "jack_session.h"
#include "i18n.h"
@@ -45,6 +46,7 @@ using namespace PBD;
using std::string;
using std::vector;
+
#define GET_PRIVATE_JACK_POINTER(localvar) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
#define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
@@ -63,6 +65,7 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnec
, _target_systemic_output_latency (0)
, _current_sample_rate (0)
, _current_buffer_size (0)
+ , _session (0)
{
_jack_connection->Connected.connect_same_thread (jack_connection_connection, boost::bind (&JACKAudioBackend::when_connected_to_jack, this));
_jack_connection->Disconnected.connect_same_thread (disconnect_connection, boost::bind (&JACKAudioBackend::disconnected, this, _1));
@@ -406,6 +409,12 @@ JACKAudioBackend::interleaved () const
return false;
}
+string
+JACKAudioBackend::midi_option () const
+{
+ return _target_midi_option;
+}
+
uint32_t
JACKAudioBackend::input_channels () const
{
@@ -462,7 +471,7 @@ JACKAudioBackend::raw_buffer_size(DataType t)
}
void
-JACKAudioBackend::setup_jack_startup_command ()
+JACKAudioBackend::setup_jack_startup_command (bool for_latency_measurement)
{
/* first we map the parameters that have been set onto a
* JackCommandLineOptions object.
@@ -487,6 +496,8 @@ JACKAudioBackend::setup_jack_startup_command ()
options.realtime = true;
options.ports_max = 2048;
+ ARDOUR::set_midi_option (options, _target_midi_option);
+
/* this must always be true for any server instance we start ourselves
*/
@@ -494,7 +505,7 @@ JACKAudioBackend::setup_jack_startup_command ()
string cmdline;
- if (!get_jack_command_line_string (options, cmdline)) {
+ if (!get_jack_command_line_string (options, cmdline, for_latency_measurement)) {
/* error, somehow - we will still try to start JACK
* automatically but it will be without our preferred options
*/
@@ -509,12 +520,15 @@ JACKAudioBackend::setup_jack_startup_command ()
/* ---- BASIC STATE CONTROL API: start/stop/pause/freewheel --- */
int
-JACKAudioBackend::start ()
+JACKAudioBackend::_start (bool for_latency_measurement)
{
if (!available()) {
- if (!_jack_connection->server_running()) {
- setup_jack_startup_command ();
+ if (_jack_connection->in_control()) {
+ /* we will be starting JACK, so set up the
+ command that JACK will use when it (auto-)starts
+ */
+ setup_jack_startup_command (for_latency_measurement);
}
if (_jack_connection->open ()) {
@@ -591,7 +605,7 @@ JACKAudioBackend::freewheel (bool onoff)
}
if (jack_set_freewheel (_priv_jack, onoff) == 0) {
- _freewheeling = true;
+ _freewheeling = onoff;
return 0;
}
@@ -744,7 +758,8 @@ JACKAudioBackend::jack_timebase_callback (jack_transport_state_t state, pframes_
ARDOUR::Session* session = engine.session();
if (session) {
- session->jack_timebase_callback (state, nframes, pos, new_position);
+ JACKSession jsession (session);
+ jsession.timebase_callback (state, nframes, pos, new_position);
}
}
@@ -789,7 +804,6 @@ JACKAudioBackend::_xrun_callback (void *arg)
return 0;
}
-#ifdef HAVE_JACK_SESSION
void
JACKAudioBackend::_session_callback (jack_session_event_t *event, void *arg)
{
@@ -797,10 +811,10 @@ JACKAudioBackend::_session_callback (jack_session_event_t *event, void *arg)
ARDOUR::Session* session = jab->engine.session();
if (session) {
- session->jack_session_event (event);
+ JACKSession jsession (session);
+ jsession.session_event (event);
}
}
-#endif
void
JACKAudioBackend::_freewheel_callback (int onoff, void *arg)
@@ -822,25 +836,72 @@ JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* ar
}
int
-JACKAudioBackend::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
+JACKAudioBackend::create_process_thread (boost::function<void()> f)
{
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
- ThreadData* td = new ThreadData (this, f, stacksize);
- if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
+ jack_native_thread_t thread_id;
+ ThreadData* td = new ThreadData (this, f, thread_stack_size());
+
+ if (jack_client_create_thread (_priv_jack, &thread_id, jack_client_real_time_priority (_priv_jack),
jack_is_realtime (_priv_jack), _start_process_thread, td)) {
return -1;
}
- return 0;
+ _jack_threads.push_back(thread_id);
+ return 0;
}
int
-JACKAudioBackend::wait_for_process_thread_exit (AudioBackendNativeThread thr)
+JACKAudioBackend::join_process_threads ()
+{
+ GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+
+ int ret = 0;
+
+ for (std::vector<jack_native_thread_t>::const_iterator i = _jack_threads.begin ();
+ i != _jack_threads.end(); i++) {
+
+#if defined(USING_JACK2_EXPANSION_OF_JACK_API) || defined(PLATFORM_WINDOWS)
+ if (jack_client_stop_thread (_priv_jack, *i) != 0) {
+#else
+ void* status;
+ if (pthread_join (*i, &status) != 0) {
+#endif
+ error << "AudioEngine: cannot stop process thread" << endmsg;
+ ret += -1;
+ }
+ }
+
+ _jack_threads.clear();
+
+ return ret;
+}
+
+bool
+JACKAudioBackend::in_process_thread ()
+{
+ for (std::vector<jack_native_thread_t>::const_iterator i = _jack_threads.begin ();
+ i != _jack_threads.end(); i++) {
+
+#ifdef COMPILER_MINGW
+ if (*i == GetCurrentThread()) {
+ return true;
+ }
+#else // pthreads
+ if (pthread_equal (*i, pthread_self()) != 0) {
+ return true;
+ }
+#endif
+ }
+
+ return false;
+}
+
+uint32_t
+JACKAudioBackend::process_thread_count ()
{
- void* status;
- /* this doesn't actively try to stop the thread, it just waits till it exits */
- return pthread_join (thr, &status);
+ return _jack_threads.size();
}
void*
@@ -960,6 +1021,7 @@ JACKAudioBackend::disconnected (const char* why)
engine.halted_callback (why); /* EMIT SIGNAL */
}
}
+
float
JACKAudioBackend::cpu_load() const
{
@@ -1056,3 +1118,16 @@ JACKAudioBackend::launch_control_app ()
args.push_back (appname);
Glib::spawn_async ("", args, Glib::SPAWN_SEARCH_PATH);
}
+
+vector<string>
+JACKAudioBackend::enumerate_midi_options () const
+{
+ return ARDOUR::enumerate_midi_options ();
+}
+
+int
+JACKAudioBackend::set_midi_option (const string& opt)
+{
+ _target_midi_option = opt;
+ return 0;
+}
diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h
index 9ab545f3ee..3c48be5ead 100644
--- a/libs/backends/jack/jack_audiobackend.h
+++ b/libs/backends/jack/jack_audiobackend.h
@@ -30,15 +30,14 @@
#include <boost/shared_ptr.hpp>
#include <jack/jack.h>
-#ifdef HAVE_JACK_SESSION
#include <jack/session.h>
-#endif
#include "ardour/audio_backend.h"
namespace ARDOUR {
class JackConnection;
+class JACKSession;
class JACKAudioBackend : public AudioBackend {
public:
@@ -90,7 +89,7 @@ class JACKAudioBackend : public AudioBackend {
std::string control_app_name () const;
void launch_control_app ();
- int start ();
+ int _start (bool for_latency_measurement);
int stop ();
int pause ();
int freewheel (bool);
@@ -103,8 +102,10 @@ class JACKAudioBackend : public AudioBackend {
size_t raw_buffer_size (DataType t);
- int create_process_thread (boost::function<void()> func, AudioBackendNativeThread*, size_t stacksize);
- int wait_for_process_thread_exit (AudioBackendNativeThread);
+ int create_process_thread (boost::function<void()> func);
+ int join_process_threads ();
+ bool in_process_thread ();
+ uint32_t process_thread_count ();
void transport_start ();
void transport_stop ();
@@ -148,6 +149,10 @@ class JACKAudioBackend : public AudioBackend {
/* MIDI */
+ std::vector<std::string> enumerate_midi_options () const;
+ int set_midi_option (const std::string&);
+ std::string midi_option () const;
+
int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
uint32_t get_midi_event_count (void* port_buffer);
@@ -184,6 +189,8 @@ class JACKAudioBackend : public AudioBackend {
bool _freewheeling;
std::map<DataType,size_t> _raw_buffer_sizes;
+ std::vector<jack_native_thread_t> _jack_threads;
+
static int _xrun_callback (void *arg);
static void* _process_thread (void *arg);
static int _sample_rate_callback (pframes_t nframes, void *arg);
@@ -192,9 +199,7 @@ class JACKAudioBackend : public AudioBackend {
static int _jack_sync_callback (jack_transport_state_t, jack_position_t*, void *arg);
static void _freewheel_callback (int , void *arg);
static void _latency_callback (jack_latency_callback_mode_t, void*);
-#ifdef HAVE_JACK_SESSION
static void _session_callback (jack_session_event_t *event, void *arg);
-#endif
void jack_timebase_callback (jack_transport_state_t, pframes_t, jack_position_t*, int);
int jack_sync_callback (jack_transport_state_t, jack_position_t*);
@@ -220,7 +225,7 @@ class JACKAudioBackend : public AudioBackend {
void* process_thread ();
static void* _start_process_thread (void*);
- void setup_jack_startup_command ();
+ void setup_jack_startup_command (bool for_latency_measurement);
/* pffooo */
@@ -236,6 +241,7 @@ class JACKAudioBackend : public AudioBackend {
uint32_t _target_systemic_output_latency;
uint32_t _current_sample_rate;
uint32_t _current_buffer_size;
+ std::string _target_midi_option;
typedef std::set<std::string> DeviceList;
typedef std::map<std::string,DeviceList> DriverDeviceMap;
@@ -257,6 +263,12 @@ class JACKAudioBackend : public AudioBackend {
void when_connected_to_jack ();
PBD::ScopedConnection jack_connection_connection;
+
+ /* Object to manage interactions with Session in a way that
+ keeps JACK out of libardour directly
+ */
+
+ JACKSession* _session;
};
} // namespace
diff --git a/libs/backends/jack/jack_connection.cc b/libs/backends/jack/jack_connection.cc
index d5d25c747f..b3d7fcecc4 100644
--- a/libs/backends/jack/jack_connection.cc
+++ b/libs/backends/jack/jack_connection.cc
@@ -36,6 +36,8 @@ using std::vector;
using std::cerr;
using std::endl;
+bool JackConnection::_in_control = false;
+
static void jack_halted_callback (void* arg)
{
JackConnection* jc = static_cast<JackConnection*> (arg);
@@ -54,17 +56,9 @@ JackConnection::JackConnection (const std::string& arg1, const std::string& arg2
, _client_name (arg1)
, session_uuid (arg2)
{
- _in_control = !server_running();
-}
-
-JackConnection::~JackConnection ()
-{
- close ();
-}
+ /* See if the server is already up
+ */
-bool
-JackConnection::server_running ()
-{
EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
@@ -83,10 +77,15 @@ JackConnection::server_running ()
if (status == 0) {
jack_client_close (c);
- return true;
+ _in_control = false;
+ } else {
+ _in_control = true;
}
+}
- return false;
+JackConnection::~JackConnection ()
+{
+ close ();
}
int
@@ -106,19 +105,6 @@ JackConnection::open ()
global_epa->restore ();
}
- /* check to see if the server is already running so that we know if we
- * are starting it.
- */
-
- jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
-
- if (status == 0) {
- _in_control = false;
- jack_client_close (c);
- } else {
- _in_control = true;
- }
-
/* ensure that PATH or equivalent includes likely locations of the JACK
* server, in case the user's default does not.
*/
diff --git a/libs/backends/jack/jack_connection.h b/libs/backends/jack/jack_connection.h
index 229d9697d9..8d15be6e3a 100644
--- a/libs/backends/jack/jack_connection.h
+++ b/libs/backends/jack/jack_connection.h
@@ -27,15 +27,13 @@ class JackConnection {
void halted_callback ();
void halted_info_callback (jack_status_t, const char*);
- bool in_control() const { return _in_control; }
+ static bool in_control() { return _in_control; }
- static bool server_running();
-
private:
jack_client_t* volatile _jack;
std::string _client_name;
std::string session_uuid;
- bool _in_control;
+ static bool _in_control;
};
} // namespace
diff --git a/libs/backends/jack/jack_session.cc b/libs/backends/jack/jack_session.cc
new file mode 100644
index 0000000000..ca51dafccc
--- /dev/null
+++ b/libs/backends/jack/jack_session.cc
@@ -0,0 +1,193 @@
+/*
+ Copyright (C) 2013 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 <time.h>
+
+#include <glibmm/miscutils.h>
+
+#include <jack/jack.h>
+
+#include "ardour/audioengine.h"
+#include "ardour/filename_extensions.h"
+#include "ardour/session.h"
+#include "ardour/session_directory.h"
+#include "ardour/tempo.h"
+
+#include "jack_session.h"
+
+using namespace ARDOUR;
+using std::string;
+
+JACKSession::JACKSession (Session* s)
+ : SessionHandlePtr (s)
+{
+}
+
+JACKSession::~JACKSession ()
+{
+}
+
+void
+JACKSession::session_event (jack_session_event_t* event)
+{
+ char timebuf[128], *tmp;
+ time_t n;
+ struct tm local_time;
+
+ time (&n);
+ localtime_r (&n, &local_time);
+ strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
+
+ while ((tmp = strchr(timebuf, ':'))) { *tmp = '.'; }
+
+ if (event->type == JackSessionSaveTemplate)
+ {
+ if (_session->save_template( timebuf )) {
+ event->flags = JackSessionSaveError;
+ } else {
+ string cmd ("ardour3 -P -U ");
+ cmd += event->client_uuid;
+ cmd += " -T ";
+ cmd += timebuf;
+
+ event->command_line = strdup (cmd.c_str());
+ }
+ }
+ else
+ {
+ if (_session->save_state (timebuf)) {
+ event->flags = JackSessionSaveError;
+ } else {
+ std::string xml_path (_session->session_directory().root_path());
+ std::string legalized_filename = legalize_for_path (timebuf) + statefile_suffix;
+ xml_path = Glib::build_filename (xml_path, legalized_filename);
+
+ string cmd ("ardour3 -P -U ");
+ cmd += event->client_uuid;
+ cmd += " \"";
+ cmd += xml_path;
+ cmd += '\"';
+
+ event->command_line = strdup (cmd.c_str());
+ }
+ }
+
+ /* this won't be called if the port engine in use is not JACK, so we do
+ not have to worry about the type of PortEngine::private_handle()
+ */
+
+ jack_client_t* jack_client = (jack_client_t*) AudioEngine::instance()->port_engine().private_handle();
+
+ if (jack_client) {
+ jack_session_reply (jack_client, event);
+ }
+
+ if (event->type == JackSessionSaveAndQuit) {
+ _session->Quit (); /* EMIT SIGNAL */
+ }
+
+ jack_session_event_free (event);
+}
+
+void
+JACKSession::timebase_callback (jack_transport_state_t /*state*/,
+ pframes_t /*nframes*/,
+ jack_position_t* pos,
+ int /*new_position*/)
+{
+ Timecode::BBT_Time bbt;
+ TempoMap& tempo_map (_session->tempo_map());
+ framepos_t tf = _session->transport_frame ();
+
+ /* BBT info */
+
+ TempoMetric metric (tempo_map.metric_at (tf));
+
+ try {
+ tempo_map.bbt_time_rt (tf, bbt);
+
+ pos->bar = bbt.bars;
+ pos->beat = bbt.beats;
+ pos->tick = bbt.ticks;
+
+ // XXX still need to set bar_start_tick
+
+ pos->beats_per_bar = metric.meter().divisions_per_bar();
+ pos->beat_type = metric.meter().note_divisor();
+ pos->ticks_per_beat = Timecode::BBT_Time::ticks_per_beat;
+ pos->beats_per_minute = metric.tempo().beats_per_minute();
+
+ pos->valid = jack_position_bits_t (pos->valid | JackPositionBBT);
+
+ } catch (...) {
+ /* no message */
+ }
+
+#ifdef HAVE_JACK_VIDEO_SUPPORT
+ //poke audio video ratio so Ardour can track Video Sync
+ pos->audio_frames_per_video_frame = _session->frame_rate() / _session->timecode_frames_per_second();
+ pos->valid = jack_position_bits_t (pos->valid | JackAudioVideoRatio);
+#endif
+
+#ifdef HAVE_JACK_TIMCODE_SUPPORT
+ /* This is not yet defined in JACK */
+
+ /* Timecode info */
+
+ pos->timecode_offset = _session->config.get_timecode_offset();
+ t.timecode_frame_rate = _session->timecode_frames_per_second();
+ pos->valid = jack_position_bits_t (pos->valid | JackPositionTimecode);
+#endif
+
+#ifdef HAVE_JACK_LOOPING_SUPPORT
+ /* This is not yet defined in JACK */
+ if (_transport_speed) {
+
+ if (play_loop) {
+
+ Location* location = _session->locations()->auto_loop_location();
+
+ if (location) {
+
+ t.transport_state = JackTransportLooping;
+ t.loop_start = location->start();
+ t.loop_end = location->end();
+ t.valid = jack_transport_bits_t (t.valid | JackTransportLoop);
+
+ } else {
+
+ t.loop_start = 0;
+ t.loop_end = 0;
+ t.transport_state = JackTransportRolling;
+
+ }
+
+ } else {
+
+ t.loop_start = 0;
+ t.loop_end = 0;
+ t.transport_state = JackTransportRolling;
+
+ }
+
+ }
+#endif
+}
+
diff --git a/libs/backends/jack/jack_session.h b/libs/backends/jack/jack_session.h
new file mode 100644
index 0000000000..c912b5f170
--- /dev/null
+++ b/libs/backends/jack/jack_session.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2013 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.
+
+*/
+
+#ifndef __ardour_jack_audiobackend_jack_session_h__
+#define __ardour_jack_audiobackend_jack_session_h__
+
+#include <jack/session.h>
+#include <jack/transport.h>
+
+#include "ardour/types.h"
+#include "ardour/session_handle.h"
+
+namespace ARDOUR {
+ class Session;
+
+class JACKSession : public ARDOUR::SessionHandlePtr
+{
+ public:
+ JACKSession (ARDOUR::Session* s);
+ ~JACKSession ();
+
+ void session_event (jack_session_event_t* event);
+ void timebase_callback (jack_transport_state_t /*state*/,
+ ARDOUR::pframes_t /*nframes*/,
+ jack_position_t* pos,
+ int /*new_position*/);
+};
+
+} /* namespace */
+
+#endif /* __ardour_jack_audiobackend_jack_session_h__ */
diff --git a/libs/backends/jack/jack_utils.cc b/libs/backends/jack/jack_utils.cc
index 93fc3d440a..92f175d9cb 100644
--- a/libs/backends/jack/jack_utils.cc
+++ b/libs/backends/jack/jack_utils.cc
@@ -83,6 +83,8 @@ namespace {
const char * const dummy_driver_command_line_name = X_("dummy");
// should we provide more "pretty" names like above?
+ 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");
@@ -92,6 +94,8 @@ namespace {
const char * const default_device_name = X_("Default");
}
+static ARDOUR::MidiOptions midi_options;
+
std::string
get_none_string ()
{
@@ -682,7 +686,7 @@ ARDOUR::JackCommandLineOptions::JackCommandLineOptions ()
}
bool
-ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& command_line)
+ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& command_line, bool for_latency_measurement)
{
vector<string> args;
@@ -740,6 +744,16 @@ ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& c
}
#endif
+ if (options.driver == alsa_driver_name) {
+ 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;
if (!get_jack_command_line_audio_driver_name (options.driver, command_line_driver_name)) {
@@ -811,7 +825,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 (get_jack_audio_driver_supports_latency_adjustment (options.driver)) {
+ if (!for_latency_measurement && 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));
@@ -846,10 +860,15 @@ ARDOUR::get_jack_command_line_string (JackCommandLineOptions& options, string& c
if (options.soft_mode) {
args.push_back ("-s");
}
+ }
- if (!options.midi_driver.empty() && options.midi_driver != get_none_string ()) {
- args.push_back ("-X");
- args.push_back (options.midi_driver);
+ if (options.driver == alsa_driver_name || options.driver == coreaudio_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);
+ }
}
}
@@ -900,3 +919,54 @@ ARDOUR::write_jack_config_file (const std::string& config_file_path, const strin
jackdrc.close ();
return true;
}
+
+vector<string>
+ARDOUR::enumerate_midi_options ()
+{
+ if (midi_options.empty()) {
+#ifdef HAVE_ALSA
+ 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
+ /* 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));
+#endif
+#ifdef __APPLE__
+ midi_options.push_back (make_pair (_("CoreMIDI"), coremidi_midi_driver_name));
+#endif
+ }
+
+ 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);
+ }
+
+ return v;
+}
+
+int
+ARDOUR::set_midi_option (ARDOUR::JackCommandLineOptions& options, const string& opt)
+{
+ if (opt.empty() || opt == get_none_string()) {
+ options.midi_driver = "";
+ return 0;
+ }
+
+ for (MidiOptions::const_iterator i = midi_options.begin(); i != midi_options.end(); ++i) {
+ if (i->first == opt) {
+ options.midi_driver = i->second;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
diff --git a/libs/backends/jack/jack_utils.h b/libs/backends/jack/jack_utils.h
index a7521ad1c4..ee8575c5c8 100644
--- a/libs/backends/jack/jack_utils.h
+++ b/libs/backends/jack/jack_utils.h
@@ -180,6 +180,8 @@ namespace ARDOUR {
*/
bool get_jack_default_server_path (std::string& server_path);
+ typedef std::vector<std::pair<std::string,std::string> > MidiOptions;
+
/**
* @return The name of the jack server config file
*/
@@ -228,8 +230,11 @@ namespace ARDOUR {
std::string midi_driver;
};
+ std::vector<std::string> enumerate_midi_options ();
+ int set_midi_option (ARDOUR::JackCommandLineOptions&, const std::string& opt);
+
/**
* @return true if able to build a valid command line based on options
*/
- bool get_jack_command_line_string (JackCommandLineOptions& options, std::string& command_line);
+ bool get_jack_command_line_string (JackCommandLineOptions& options, std::string& command_line, bool for_latency_measurement);
}
diff --git a/libs/backends/jack/wscript b/libs/backends/jack/wscript
index 2903abb641..111ecf3218 100644
--- a/libs/backends/jack/wscript
+++ b/libs/backends/jack/wscript
@@ -19,6 +19,7 @@ def options(opt):
autowaf.set_options(opt)
def configure(conf):
+ autowaf.check_pkg(conf, 'jack', uselib_store='JACK', atleast_version='0.121.0')
autowaf.configure(conf)
def build(bld):
@@ -28,10 +29,10 @@ def build(bld):
'jack_connection.cc',
'jack_audiobackend.cc',
'jack_portengine.cc',
- 'jack_utils.cc'
+ 'jack_utils.cc',
+ 'jack_session.cc',
]
obj.includes = ['.']
- obj.cxxflags = [ '-fPIC' ]
obj.name = 'jack_audiobackend'
obj.target = 'jack_audiobackend'
obj.uselib = [ 'JACK' ]