summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/backends/alsa/alsa_audiobackend.cc91
-rw-r--r--libs/backends/alsa/alsa_audiobackend.h11
2 files changed, 78 insertions, 24 deletions
diff --git a/libs/backends/alsa/alsa_audiobackend.cc b/libs/backends/alsa/alsa_audiobackend.cc
index e8198ba333..1e80022c95 100644
--- a/libs/backends/alsa/alsa_audiobackend.cc
+++ b/libs/backends/alsa/alsa_audiobackend.cc
@@ -29,8 +29,8 @@
#include "pbd/compose.h"
#include "pbd/error.h"
#include "pbd/file_utils.h"
+#include "ardour/filesystem_paths.h"
#include "ardour/port_manager.h"
-#include "ardour/system_exec.h"
#include "ardouralsautil/devicelist.h"
#include "i18n.h"
@@ -47,6 +47,7 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
, _freewheeling (false)
, _audio_device("")
, _midi_device("")
+ , _device_reservation(0)
, _samplerate (48000)
, _samples_per_period (1024)
, _periods_per_cycle (2)
@@ -92,7 +93,24 @@ AlsaAudioBackend::enumerate_devices () const
return s;
}
-static void acquire_device(const char* device_name)
+void
+AlsaAudioBackend::reservation_stdout (std::string d, size_t /* s */)
+{
+ if (d.substr(0, 19) == "Acquired audio-card") {
+ _reservation_succeeded = true;
+ }
+}
+
+void
+AlsaAudioBackend::release_device()
+{
+ _reservation_connection.drop_connections();
+ delete _device_reservation;
+ _device_reservation = 0;
+}
+
+bool
+AlsaAudioBackend::acquire_device(const char* device_name)
{
/* This is quick hack, ideally we'll link against libdbus and implement a dbus-listener
* that owns the device. here we try to get away by just requesting it and then block it...
@@ -102,32 +120,50 @@ static void acquire_device(const char* device_name)
* -> should not return 'boolean false'
*/
int device_number = card_to_num(device_name);
- if (device_number < 0) return;
+ if (device_number < 0) return false;
+
+ assert(_device_reservation == 0);
+ _reservation_succeeded = false;
- std::string dbus_send_path;
- if (PBD::find_file_in_search_path (PBD::Searchpath(Glib::getenv("PATH")), X_("dbus-send"), dbus_send_path)) {
+ std::string request_device_exe;
+ if (!PBD::find_file_in_search_path (
+ PBD::Searchpath(Glib::build_filename(ARDOUR::ardour_dll_directory(), "ardouralsautil")
+ + G_SEARCHPATH_SEPARATOR_S + ARDOUR::ardour_dll_directory()),
+ "ardour-request-device", request_device_exe))
+ {
+ PBD::warning << "ardour-request-device binary was not found..'" << endmsg;
+ return false;
+ }
+ else
+ {
char **argp;
char tmp[128];
- argp=(char**) calloc(8,sizeof(char*));
- argp[0] = strdup(dbus_send_path.c_str());
- argp[1] = strdup("--session");
- argp[2] = strdup("--print-reply"); // need to wait for the receiver to act.
- argp[3] = strdup("--type=method_call");
- snprintf(tmp, sizeof(tmp), "--dest=org.freedesktop.ReserveDevice1.Audio%d", device_number);
- argp[4] = strdup(tmp);
- snprintf(tmp, sizeof(tmp), "/org/freedesktop/ReserveDevice1/Audio%d", device_number);
- argp[5] = strdup(tmp);
- argp[6] = strdup("org.freedesktop.ReserveDevice1.RequestRelease");
- argp[7] = strdup("int32:4294967296");
- snprintf(tmp, sizeof(tmp), "string:'org.freedesktop.ReserveDevice1.Audio%d'", device_number);
- argp[7] = strdup(tmp);
- argp[8] = 0;
-
- ARDOUR::SystemExec process (dbus_send_path, argp);
- if (!process.start(1)) {
- process.wait();
+ argp=(char**) calloc(3,sizeof(char*));
+ argp[0] = strdup(request_device_exe.c_str());
+ snprintf(tmp, sizeof(tmp), "Audio%d", device_number);
+ argp[1] = strdup(tmp);
+ argp[2] = 0;
+
+ _device_reservation = new ARDOUR::SystemExec(request_device_exe, argp);
+ _device_reservation->ReadStdout.connect_same_thread (_reservation_connection, boost::bind (&AlsaAudioBackend::reservation_stdout, this, _1 ,_2));
+ _device_reservation->Terminated.connect_same_thread (_reservation_connection, boost::bind (&AlsaAudioBackend::release_device, this));
+ if (_device_reservation->start(0)) {
+ PBD::warning << _("AlsaAudioBackend: Device Request failed.") << endmsg;
+ release_device();
+ return false;
}
}
+ // wait to check if reservation suceeded.
+ int timeout = 500; // 5 sec
+ while (_device_reservation && !_reservation_succeeded && --timeout > 0) {
+ Glib::usleep(10000);
+ }
+ if (timeout == 0 || !_reservation_succeeded) {
+ PBD::warning << _("AlsaAudioBackend: Device Reservation failed.") << endmsg;
+ release_device();
+ return false;
+ }
+ return true;
}
std::vector<float>
@@ -355,6 +391,8 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
_ports.clear();
}
+ release_device();
+
assert(_rmidi_in.size() == 0);
assert(_rmidi_out.size() == 0);
assert(_pcmi == 0);
@@ -383,6 +421,7 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
}
if (_pcmi->state ()) {
delete _pcmi; _pcmi = 0;
+ release_device();
return -1;
}
@@ -429,12 +468,14 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
if (register_system_audio_ports()) {
PBD::error << _("AlsaAudioBackend: failed to register system ports.") << endmsg;
delete _pcmi; _pcmi = 0;
+ release_device();
return -1;
}
if (engine.reestablish_ports ()) {
PBD::error << _("AlsaAudioBackend: Could not re-establish ports.") << endmsg;
delete _pcmi; _pcmi = 0;
+ release_device();
return -1;
}
@@ -449,6 +490,7 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
{
PBD::error << _("AlsaAudioBackend: failed to create process thread.") << endmsg;
delete _pcmi; _pcmi = 0;
+ release_device();
_run = false;
return -1;
} else {
@@ -462,6 +504,7 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
if (timeout == 0 || !_active) {
PBD::error << _("AlsaAudioBackend: failed to start process thread.") << endmsg;
delete _pcmi; _pcmi = 0;
+ release_device();
_run = false;
return -1;
}
@@ -498,6 +541,8 @@ AlsaAudioBackend::stop ()
unregister_system_ports();
delete _pcmi; _pcmi = 0;
+ release_device();
+
return (_active == false) ? 0 : -1;
}
diff --git a/libs/backends/alsa/alsa_audiobackend.h b/libs/backends/alsa/alsa_audiobackend.h
index 6ad58161f3..386a83a33f 100644
--- a/libs/backends/alsa/alsa_audiobackend.h
+++ b/libs/backends/alsa/alsa_audiobackend.h
@@ -30,8 +30,9 @@
#include <boost/shared_ptr.hpp>
-#include "ardour/types.h"
#include "ardour/audio_backend.h"
+#include "ardour/system_exec.h"
+#include "ardour/types.h"
#include "zita-alsa-pcmi.h"
#include "alsa_rawmidi.h"
@@ -288,6 +289,14 @@ class AlsaAudioBackend : public AudioBackend {
std::string _audio_device;
std::string _midi_device;
+ /* audio device reservation */
+ ARDOUR::SystemExec *_device_reservation;
+ PBD::ScopedConnectionList _reservation_connection;
+ void reservation_stdout (std::string, size_t);
+ bool acquire_device(const char* device_name);
+ void release_device();
+ bool _reservation_succeeded;
+
float _samplerate;
size_t _samples_per_period;
size_t _periods_per_cycle;