diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2013-10-16 22:06:56 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2013-10-16 22:06:56 -0400 |
commit | e5888d398350b26ba2cdc634cc9791e90b4fc6b6 (patch) | |
tree | 54f485ea56d034ecba01938fbc680b12884fc136 /libs/backends/jack | |
parent | 18850253e9f0034fad132e0da07a2651ce041450 (diff) | |
parent | da5a49067839ec32a016bf1b66c3808ad7cbf699 (diff) |
merge with master and fix 2 conflicts
Diffstat (limited to 'libs/backends/jack')
-rw-r--r-- | libs/backends/jack/jack_api.cc | 2 | ||||
-rw-r--r-- | libs/backends/jack/jack_audiobackend.cc | 111 | ||||
-rw-r--r-- | libs/backends/jack/jack_audiobackend.h | 28 | ||||
-rw-r--r-- | libs/backends/jack/jack_connection.cc | 36 | ||||
-rw-r--r-- | libs/backends/jack/jack_connection.h | 6 | ||||
-rw-r--r-- | libs/backends/jack/jack_session.cc | 193 | ||||
-rw-r--r-- | libs/backends/jack/jack_session.h | 47 | ||||
-rw-r--r-- | libs/backends/jack/jack_utils.cc | 80 | ||||
-rw-r--r-- | libs/backends/jack/jack_utils.h | 7 | ||||
-rw-r--r-- | libs/backends/jack/wscript | 5 |
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' ] |