Merge pull request #23 from jackaudio/device_reservation_fixes
Device reservation fixes
This commit is contained in:
commit
e814e508d5
|
@ -76,6 +76,8 @@ SERVER_EXPORT bool audio_acquire(const char * device_name)
|
|||
|
||||
assert(gReserveCount < DEVICE_MAX);
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if ((ret= rd_acquire(
|
||||
&gReservedDevice[gReserveCount].reserved_device,
|
||||
gConnection,
|
||||
|
@ -86,6 +88,7 @@ SERVER_EXPORT bool audio_acquire(const char * device_name)
|
|||
&error)) < 0) {
|
||||
|
||||
jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret)));
|
||||
dbus_error_free(&error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -377,6 +377,8 @@ on_device_acquire(const char * device_name)
|
|||
int ret;
|
||||
DBusError error;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
ret = rd_acquire(
|
||||
&g_reserved_device[g_device_count].reserved_device,
|
||||
g_connection,
|
||||
|
@ -388,6 +390,7 @@ on_device_acquire(const char * device_name)
|
|||
if (ret < 0)
|
||||
{
|
||||
jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret)));
|
||||
dbus_error_free(&error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "reserve.h"
|
||||
#include "jack/control.h"
|
||||
|
||||
#define RESERVE_ERROR_NO_MEMORY "org.freedesktop.ReserveDevice1.Error.NoMemory"
|
||||
#define RESERVE_ERROR_PROTOCOL_VIOLATION "org.freedesktop.ReserveDevice1.Error.Protocol"
|
||||
#define RESERVE_ERROR_RELEASE_DENIED "org.freedesktop.ReserveDevice1.Error.ReleaseDenied"
|
||||
|
||||
struct rd_device {
|
||||
int ref;
|
||||
|
@ -371,34 +376,51 @@ int rd_acquire(
|
|||
dbus_bool_t good;
|
||||
vtable.message_function = object_handler;
|
||||
|
||||
if (!error)
|
||||
if (!error) {
|
||||
error = &_error;
|
||||
dbus_error_init(error);
|
||||
}
|
||||
|
||||
dbus_error_init(error);
|
||||
if (!_d) {
|
||||
assert(0);
|
||||
r = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!_d)
|
||||
return -EINVAL;
|
||||
if (!connection) {
|
||||
assert(0);
|
||||
r = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!connection)
|
||||
return -EINVAL;
|
||||
if (!device_name) {
|
||||
assert(0);
|
||||
r = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!device_name)
|
||||
return -EINVAL;
|
||||
if (!request_cb && priority != INT32_MAX) {
|
||||
assert(0);
|
||||
r = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!request_cb && priority != INT32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(d = (rd_device *)calloc(sizeof(rd_device), 1)))
|
||||
return -ENOMEM;
|
||||
if (!(d = (rd_device *)calloc(sizeof(rd_device), 1))) {
|
||||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot allocate memory for rd_device struct");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
d->ref = 1;
|
||||
|
||||
if (!(d->device_name = strdup(device_name))) {
|
||||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot duplicate device name string");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(d->application_name = strdup(application_name))) {
|
||||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot duplicate application name string");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -408,12 +430,14 @@ int rd_acquire(
|
|||
d->request_cb = request_cb;
|
||||
|
||||
if (!(d->service_name = (char*)malloc(sizeof(SERVICE_PREFIX) + strlen(device_name)))) {
|
||||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot allocate memory for service name string");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
sprintf(d->service_name, SERVICE_PREFIX "%s", d->device_name);
|
||||
|
||||
if (!(d->object_path = (char*)malloc(sizeof(OBJECT_PREFIX) + strlen(device_name)))) {
|
||||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot allocate memory for object path string");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -425,20 +449,28 @@ int rd_acquire(
|
|||
DBUS_NAME_FLAG_DO_NOT_QUEUE|
|
||||
(priority < INT32_MAX ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT : 0),
|
||||
error)) < 0) {
|
||||
jack_error("dbus_bus_request_name() failed. (1)");
|
||||
r = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (k == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER || k == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER)
|
||||
switch (k) {
|
||||
case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
|
||||
case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
|
||||
goto success;
|
||||
|
||||
if (k != DBUS_REQUEST_NAME_REPLY_EXISTS) {
|
||||
case DBUS_REQUEST_NAME_REPLY_EXISTS:
|
||||
break;
|
||||
case DBUS_REQUEST_NAME_REPLY_IN_QUEUE : /* DBUS_NAME_FLAG_DO_NOT_QUEUE was specified */
|
||||
default: /* unknown reply returned */
|
||||
jack_error("request name reply with unexpected value %d.", k);
|
||||
assert(0);
|
||||
r = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (priority <= INT32_MIN) {
|
||||
r = -EBUSY;
|
||||
dbus_set_error(error, RESERVE_ERROR_RELEASE_DENIED, "Device reservation request with priority %"PRIi32" denied for \"%s\"", priority, device_name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -447,6 +479,7 @@ int rd_acquire(
|
|||
d->object_path,
|
||||
"org.freedesktop.ReserveDevice1",
|
||||
"RequestRelease"))) {
|
||||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot allocate memory for RequestRelease method call");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -455,6 +488,7 @@ int rd_acquire(
|
|||
m,
|
||||
DBUS_TYPE_INT32, &d->priority,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot append args for RequestRelease method call");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -469,10 +503,12 @@ int rd_acquire(
|
|||
dbus_error_has_name(error, DBUS_ERROR_UNKNOWN_METHOD) ||
|
||||
dbus_error_has_name(error, DBUS_ERROR_NO_REPLY)) {
|
||||
/* This must be treated as denied. */
|
||||
jack_info("Device reservation request with priority %"PRIi32" denied for \"%s\": %s (%s)", priority, device_name, error->name, error->message);
|
||||
r = -EBUSY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
jack_error("dbus_connection_send_with_reply_and_block(RequestRelease) failed.");
|
||||
r = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -482,11 +518,13 @@ int rd_acquire(
|
|||
error,
|
||||
DBUS_TYPE_BOOLEAN, &good,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
jack_error("RequestRelease() reply is invalid.");
|
||||
r = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!good) {
|
||||
dbus_set_error(error, RESERVE_ERROR_RELEASE_DENIED, "Device reservation request with priority %"PRIi32" denied for \"%s\" via RequestRelease()", priority, device_name);
|
||||
r = -EBUSY;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -498,11 +536,14 @@ int rd_acquire(
|
|||
(priority < INT32_MAX ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT : 0)|
|
||||
DBUS_NAME_FLAG_REPLACE_EXISTING,
|
||||
error)) < 0) {
|
||||
jack_error("dbus_bus_request_name() failed. (2)");
|
||||
r = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (k != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
||||
/* this is racy, another contender may have acquired the device */
|
||||
dbus_set_error(error, RESERVE_ERROR_PROTOCOL_VIOLATION, "request name reply is not DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER but %d.", k);
|
||||
r = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -510,11 +551,13 @@ int rd_acquire(
|
|||
success:
|
||||
d->owning = 1;
|
||||
|
||||
if (!(dbus_connection_register_object_path(
|
||||
if (!(dbus_connection_try_register_object_path(
|
||||
d->connection,
|
||||
d->object_path,
|
||||
&vtable,
|
||||
d))) {
|
||||
d,
|
||||
error))) {
|
||||
jack_error("cannot register object path \"%s\": %s", d->object_path, error->message);
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -526,6 +569,7 @@ success:
|
|||
filter_handler,
|
||||
d,
|
||||
NULL)) {
|
||||
dbus_set_error(error, RESERVE_ERROR_NO_MEMORY, "Cannot add filter");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <regex.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "JackAlsaDriver.h"
|
||||
|
@ -172,30 +171,31 @@ int JackAlsaDriver::Detach()
|
|||
return JackAudioDriver::Detach();
|
||||
}
|
||||
|
||||
static char* get_control_device_name(const char * device_name)
|
||||
extern "C" char* get_control_device_name(const char * device_name)
|
||||
{
|
||||
char * ctl_name;
|
||||
regex_t expression;
|
||||
const char * comma;
|
||||
|
||||
regcomp(&expression, "(plug)?hw:[0-9](,[0-9])?", REG_ICASE | REG_EXTENDED);
|
||||
/* the user wants a hw or plughw device, the ctl name
|
||||
* should be hw:x where x is the card identification.
|
||||
* We skip the subdevice suffix that starts with comma */
|
||||
|
||||
if (!regexec(&expression, device_name, 0, NULL, 0)) {
|
||||
/* the user wants a hw or plughw device, the ctl name
|
||||
* should be hw:x where x is the card number */
|
||||
|
||||
char tmp[5];
|
||||
strncpy(tmp, strstr(device_name, "hw"), 4);
|
||||
tmp[4] = '\0';
|
||||
jack_info("control device %s",tmp);
|
||||
ctl_name = strdup(tmp);
|
||||
} else {
|
||||
ctl_name = strdup(device_name);
|
||||
if (strncasecmp(device_name, "plughw:", 7) == 0) {
|
||||
/* skip the "plug" prefix" */
|
||||
device_name += 4;
|
||||
}
|
||||
|
||||
regfree(&expression);
|
||||
|
||||
if (ctl_name == NULL) {
|
||||
jack_error("strdup(\"%s\") failed.", ctl_name);
|
||||
comma = strchr(device_name, ',');
|
||||
if (comma == NULL) {
|
||||
ctl_name = strdup(device_name);
|
||||
if (ctl_name == NULL) {
|
||||
jack_error("strdup(\"%s\") failed.", device_name);
|
||||
}
|
||||
} else {
|
||||
ctl_name = strndup(device_name, comma - device_name);
|
||||
if (ctl_name == NULL) {
|
||||
jack_error("strndup(\"%s\", %u) failed.", device_name, (unsigned int)(comma - device_name));
|
||||
}
|
||||
}
|
||||
|
||||
return ctl_name;
|
||||
|
@ -278,16 +278,22 @@ int JackAlsaDriver::Open(jack_nframes_t nframes,
|
|||
int playback_card = card_to_num(playback_driver_name);
|
||||
char audio_name[32];
|
||||
|
||||
snprintf(audio_name, sizeof(audio_name), "Audio%d", capture_card);
|
||||
if (!JackServerGlobals::on_device_acquire(audio_name)) {
|
||||
jack_error("Audio device %s cannot be acquired...", capture_driver_name);
|
||||
return -1;
|
||||
if (capture_card >= 0) {
|
||||
snprintf(audio_name, sizeof(audio_name), "Audio%d", capture_card);
|
||||
if (!JackServerGlobals::on_device_acquire(audio_name)) {
|
||||
jack_error("Audio device %s cannot be acquired...", capture_driver_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (playback_card != capture_card) {
|
||||
if (playback_card >= 0 && playback_card != capture_card) {
|
||||
snprintf(audio_name, sizeof(audio_name), "Audio%d", playback_card);
|
||||
if (!JackServerGlobals::on_device_acquire(audio_name)) {
|
||||
jack_error("Audio device %s cannot be acquired...", playback_driver_name);
|
||||
if (capture_card >= 0) {
|
||||
snprintf(audio_name, sizeof(audio_name), "Audio%d", capture_card);
|
||||
JackServerGlobals::on_device_release(audio_name);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,15 +39,13 @@ class JackAlsaDriver : public JackAudioDriver
|
|||
private:
|
||||
|
||||
jack_driver_t* fDriver;
|
||||
int fReservedCaptureDevice;
|
||||
int fReservedPlaybackDevice;
|
||||
|
||||
void UpdateLatencies();
|
||||
|
||||
public:
|
||||
|
||||
JackAlsaDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
|
||||
: JackAudioDriver(name, alias, engine, table),fDriver(NULL),fReservedCaptureDevice(-1),fReservedPlaybackDevice(-1)
|
||||
: JackAudioDriver(name, alias, engine, table),fDriver(NULL)
|
||||
{}
|
||||
virtual ~JackAlsaDriver()
|
||||
{}
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <regex.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alsa_driver.h"
|
||||
|
@ -137,30 +136,18 @@ alsa_driver_check_capabilities (alsa_driver_t *driver)
|
|||
return 0;
|
||||
}
|
||||
|
||||
char* get_control_device_name(const char * device_name);
|
||||
|
||||
static int
|
||||
alsa_driver_check_card_type (alsa_driver_t *driver)
|
||||
{
|
||||
int err;
|
||||
snd_ctl_card_info_t *card_info;
|
||||
char * ctl_name;
|
||||
regex_t expression;
|
||||
|
||||
snd_ctl_card_info_alloca (&card_info);
|
||||
|
||||
regcomp(&expression,"(plug)?hw:[0-9](,[0-9])?",REG_ICASE|REG_EXTENDED);
|
||||
|
||||
if (!regexec(&expression,driver->alsa_name_playback,0,NULL,0)) {
|
||||
/* the user wants a hw or plughw device, the ctl name
|
||||
* should be hw:x where x is the card number */
|
||||
|
||||
char tmp[5];
|
||||
strncpy(tmp,strcasestr(driver->alsa_name_playback,"hw"),4);
|
||||
tmp[4]='\0';
|
||||
jack_info("control device %s",tmp);
|
||||
ctl_name = strdup(tmp);
|
||||
} else {
|
||||
ctl_name = strdup(driver->alsa_name_playback);
|
||||
}
|
||||
ctl_name = get_control_device_name(driver->alsa_name_playback);
|
||||
|
||||
// XXX: I don't know the "right" way to do this. Which to use
|
||||
// driver->alsa_name_playback or driver->alsa_name_capture.
|
||||
|
@ -175,7 +162,6 @@ alsa_driver_check_card_type (alsa_driver_t *driver)
|
|||
|
||||
driver->alsa_driver = strdup(snd_ctl_card_info_get_driver (card_info));
|
||||
|
||||
regfree(&expression);
|
||||
free(ctl_name);
|
||||
|
||||
return alsa_driver_check_capabilities (driver);
|
||||
|
|
Loading…
Reference in New Issue