diff --git a/ChangeLog b/ChangeLog index ef1336e4..fe9fc6f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,16 +22,17 @@ Michael Voigt --------------------------- Jackdmp changes log --------------------------- - + 2009-02-23 Stephane Letz - * Another fix in systemdeps.h and types.h: jack_time_t now uniquely defined in types.h. + * Another fix in systemdeps.h and types.h: jack_time_t now uniquely defined in types.h. * Move generic code and data in JackNetInterface and JackNetMasterInterface classes. + * First version of D-Bus based audio device rerservation. 2009-02-20 Stephane Letz * Add InitConnection and InitRendering methods in JackNetSlaveInterface, better packet type checking in JackNetSlaveInterface::SyncRecv. - * Change fMulticastIP handling in JackNetInterface. + * Change fMulticastIP handling in JackNetInterface. * Cleanup systemdeps.h on Windows. 2009-02-17 Stephane Letz diff --git a/common/JackControlAPI.cpp b/common/JackControlAPI.cpp index 7fd71a0d..0bec8906 100644 --- a/common/JackControlAPI.cpp +++ b/common/JackControlAPI.cpp @@ -576,8 +576,8 @@ jackctl_wait_signals(sigset_t signals) // driver exit waiting = false; break; - case SIGTTOU: - break; + case SIGTTOU: + break; default: waiting = false; break; diff --git a/common/wscript b/common/wscript index 8c576a15..2a78f433 100644 --- a/common/wscript +++ b/common/wscript @@ -139,6 +139,9 @@ def build(bld): '../posix/JackSocketServerNotifyChannel.cpp', '../posix/JackNetUnixSocket.cpp', ] + + if bld.env['IS_LINUX'] and bld.env['BUILD_JACKDBUS']: + serverlib.source += ['../dbus/reserve.c', '../dbus/audio_reserve.c'] if bld.env['IS_SUN']: serverlib.source += [ diff --git a/dbus/audio_reserve.c b/dbus/audio_reserve.c new file mode 100644 index 00000000..005b1fd5 --- /dev/null +++ b/dbus/audio_reserve.c @@ -0,0 +1,98 @@ +/*** + Copyright 2009 Grame + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#include +#include +#include +#include +#include +#include + +#include "reserve.h" +#include "audio_reserve.h" +#include "JackError.h" + +static DBusConnection* connection = NULL; + +SERVER_EXPORT int audio_reservation_init() +{ + DBusError error; + + dbus_error_init(&error); + + if (!(connection = dbus_bus_get(DBUS_BUS_SESSION, &error))) { + jack_error("Failed to connect to session bus for device reservation %s\n", error.message); + return -1; + } + + return 0; +} + +SERVER_EXPORT int audio_reservation_finish() +{ + if (connection) + dbus_connection_unref(connection); +} + +SERVER_EXPORT void* audio_acquire(int num) +{ + DBusError error; + rd_device* device; + char audio_name[32]; + int e; + + snprintf(audio_name, sizeof(audio_name) - 1, "Audio%d", num); + if ((e = rd_acquire( + &device, + connection, + audio_name, + "Jack audio server", + INT32_MAX, + NULL, + &error)) < 0) { + + jack_error ("Failed to acquire device: %s\n", error.message ? error.message : strerror(-e)); + return NULL; + } + + jack_info("Acquire audio card %s", audio_name); + return (void*)device; +} + +SERVER_EXPORT void audio_reserve_loop() +{ + if (connection) { + while (dbus_connection_read_write_dispatch (connection, -1)) + ; // empty loop body + } +} + +SERVER_EXPORT void audio_release(void* dev) +{ + rd_device* device = (rd_device*)dev; + if (device) { + jack_info("Release audio card"); + rd_release(device); + } +} diff --git a/dbus/audio_reserve.h b/dbus/audio_reserve.h new file mode 100644 index 00000000..473d31ba --- /dev/null +++ b/dbus/audio_reserve.h @@ -0,0 +1,47 @@ + + +/*** + Copyright 2009 GRAME + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#ifndef __audio_reserve__ +#define __audio_reserve__ + +#include "JackCompilerDeps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +SERVER_EXPORT int audio_reservation_init(); +SERVER_EXPORT int audio_reservation_finish(); + +SERVER_EXPORT void* audio_acquire(int num); +SERVER_EXPORT void audio_release(void* dev); +SERVER_EXPORT void audio_reserve_loop(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/dbus/reserve.c b/dbus/reserve.c new file mode 100644 index 00000000..9a9591d2 --- /dev/null +++ b/dbus/reserve.c @@ -0,0 +1,635 @@ +/*** + Copyright 2009 Lennart Poettering + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#include +#include +#include +#include +#include +#include + +#include "reserve.h" + +struct rd_device { + int ref; + + char *device_name; + char *application_name; + char *application_device_name; + char *service_name; + char *object_path; + int32_t priority; + + DBusConnection *connection; + + int owning:1; + int registered:1; + int filtering:1; + int gave_up:1; + + rd_request_cb_t request_cb; + void *userdata; +}; + + +#define SERVICE_PREFIX "org.freedesktop.ReserveDevice1." +#define OBJECT_PREFIX "/org/freedesktop/ReserveDevice1/" + +static const char introspection[] = + DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE + "" + " \n" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + +static dbus_bool_t add_variant( + DBusMessage *m, + int type, + const void *data) { + + DBusMessageIter iter, sub; + char t[2]; + + t[0] = (char) type; + t[1] = 0; + + dbus_message_iter_init_append(m, &iter); + + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, t, &sub)) + return FALSE; + + if (!dbus_message_iter_append_basic(&sub, type, data)) + return FALSE; + + if (!dbus_message_iter_close_container(&iter, &sub)) + return FALSE; + + return TRUE; +} + +static DBusHandlerResult object_handler( + DBusConnection *c, + DBusMessage *m, + void *userdata) { + + rd_device *d; + DBusError error; + DBusMessage *reply = NULL; + + dbus_error_init(&error); + + d = userdata; + assert(d->ref >= 1); + + if (dbus_message_is_method_call( + m, + "org.freedesktop.ReserveDevice1", + "RequestRelease")) { + + int32_t priority; + dbus_bool_t ret; + + if (!dbus_message_get_args( + m, + &error, + DBUS_TYPE_INT32, &priority, + DBUS_TYPE_INVALID)) + goto invalid; + + ret = FALSE; + + if (priority > d->priority && d->request_cb) { + d->ref++; + + if (d->request_cb(d, 0) > 0) { + ret = TRUE; + d->gave_up = 1; + } + + rd_release(d); + } + + if (!(reply = dbus_message_new_method_return(m))) + goto oom; + + if (!dbus_message_append_args( + reply, + DBUS_TYPE_BOOLEAN, &ret, + DBUS_TYPE_INVALID)) + goto oom; + + if (!dbus_connection_send(c, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; + + } else if (dbus_message_is_method_call( + m, + "org.freedesktop.DBus.Properties", + "Get")) { + + const char *interface, *property; + + if (!dbus_message_get_args( + m, + &error, + DBUS_TYPE_STRING, &interface, + DBUS_TYPE_STRING, &property, + DBUS_TYPE_INVALID)) + goto invalid; + + if (strcmp(interface, "org.freedesktop.ReserveDevice1") == 0) { + const char *empty = ""; + + if (strcmp(property, "ApplicationName") == 0 && d->application_name) { + if (!(reply = dbus_message_new_method_return(m))) + goto oom; + + if (!add_variant( + reply, + DBUS_TYPE_STRING, + d->application_name ? (const char**) &d->application_name : &empty)) + goto oom; + + } else if (strcmp(property, "ApplicationDeviceName") == 0) { + if (!(reply = dbus_message_new_method_return(m))) + goto oom; + + if (!add_variant( + reply, + DBUS_TYPE_STRING, + d->application_device_name ? (const char**) &d->application_device_name : &empty)) + goto oom; + + } else if (strcmp(property, "Priority") == 0) { + if (!(reply = dbus_message_new_method_return(m))) + goto oom; + + if (!add_variant( + reply, + DBUS_TYPE_INT32, + &d->priority)) + goto oom; + } else { + if (!(reply = dbus_message_new_error_printf( + m, + DBUS_ERROR_UNKNOWN_METHOD, + "Unknown property %s", + property))) + goto oom; + } + + if (!dbus_connection_send(c, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + } else if (dbus_message_is_method_call( + m, + "org.freedesktop.DBus.Introspectable", + "Introspect")) { + const char *i = introspection; + + if (!(reply = dbus_message_new_method_return(m))) + goto oom; + + if (!dbus_message_append_args( + reply, + DBUS_TYPE_STRING, + &i, + DBUS_TYPE_INVALID)) + goto oom; + + if (!dbus_connection_send(c, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +invalid: + if (reply) + dbus_message_unref(reply); + + if (!(reply = dbus_message_new_error( + m, + DBUS_ERROR_INVALID_ARGS, + "Invalid arguments"))) + goto oom; + + if (!dbus_connection_send(c, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + + dbus_error_free(&error); + + return DBUS_HANDLER_RESULT_HANDLED; + +oom: + if (reply) + dbus_message_unref(reply); + + dbus_error_free(&error); + + return DBUS_HANDLER_RESULT_NEED_MEMORY; +} + +static DBusHandlerResult filter_handler( + DBusConnection *c, + DBusMessage *m, + void *userdata) { + + DBusMessage *reply; + rd_device *d; + DBusError error; + + dbus_error_init(&error); + + d = userdata; + + if (dbus_message_is_signal(m, "org.freedesktop.DBus", "NameLost")) { + const char *name; + + if (!dbus_message_get_args( + m, + &error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) + goto invalid; + + if (strcmp(name, d->service_name) == 0 && d->owning) { + d->owning = 0; + + if (!d->gave_up) { + d->ref++; + + if (d->request_cb) + d->request_cb(d, 1); + d->gave_up = 1; + + rd_release(d); + } + + return DBUS_HANDLER_RESULT_HANDLED; + } + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +invalid: + if (!(reply = dbus_message_new_error( + m, + DBUS_ERROR_INVALID_ARGS, + "Invalid arguments"))) + goto oom; + + if (!dbus_connection_send(c, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + + dbus_error_free(&error); + + return DBUS_HANDLER_RESULT_HANDLED; + +oom: + if (reply) + dbus_message_unref(reply); + + dbus_error_free(&error); + + return DBUS_HANDLER_RESULT_NEED_MEMORY; +} + + +static const struct DBusObjectPathVTable vtable ={ + .message_function = object_handler +}; + +int rd_acquire( + rd_device **_d, + DBusConnection *connection, + const char *device_name, + const char *application_name, + int32_t priority, + rd_request_cb_t request_cb, + DBusError *error) { + + rd_device *d = NULL; + int r, k; + DBusError _error; + DBusMessage *m = NULL, *reply = NULL; + dbus_bool_t good; + + if (!error) + error = &_error; + + dbus_error_init(error); + + if (!_d) + return -EINVAL; + + if (!connection) + return -EINVAL; + + if (!device_name) + return -EINVAL; + + if (!request_cb && priority != INT32_MAX) + return -EINVAL; + + if (!(d = calloc(sizeof(rd_device), 1))) + return -ENOMEM; + + d->ref = 1; + + if (!(d->device_name = strdup(device_name))) { + r = -ENOMEM; + goto fail; + } + + if (!(d->application_name = strdup(application_name))) { + r = -ENOMEM; + goto fail; + } + + d->priority = priority; + d->connection = dbus_connection_ref(connection); + d->request_cb = request_cb; + + if (!(d->service_name = malloc(sizeof(SERVICE_PREFIX) + strlen(device_name)))) { + r = -ENOMEM; + goto fail; + } + sprintf(d->service_name, SERVICE_PREFIX "%s", d->device_name); + + if (!(d->object_path = malloc(sizeof(OBJECT_PREFIX) + strlen(device_name)))) { + r = -ENOMEM; + goto fail; + } + sprintf(d->object_path, OBJECT_PREFIX "%s", d->device_name); + + if ((k = dbus_bus_request_name( + d->connection, + d->service_name, + DBUS_NAME_FLAG_DO_NOT_QUEUE| + (priority < INT32_MAX ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT : 0), + error)) < 0) { + r = -EIO; + goto fail; + } + + if (k == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) + goto success; + + if (k != DBUS_REQUEST_NAME_REPLY_EXISTS) { + r = -EIO; + goto fail; + } + + if (priority <= INT32_MIN) { + r = -EBUSY; + goto fail; + } + + if (!(m = dbus_message_new_method_call( + d->service_name, + d->object_path, + "org.freedesktop.ReserveDevice1", + "RequestRelease"))) { + r = -ENOMEM; + goto fail; + } + + if (!dbus_message_append_args( + m, + DBUS_TYPE_INT32, &d->priority, + DBUS_TYPE_INVALID)) { + r = -ENOMEM; + goto fail; + } + + if (!(reply = dbus_connection_send_with_reply_and_block( + d->connection, + m, + 5000, /* 5s */ + error))) { + + if (dbus_error_has_name(error, DBUS_ERROR_TIMED_OUT) || + dbus_error_has_name(error, DBUS_ERROR_UNKNOWN_METHOD) || + dbus_error_has_name(error, DBUS_ERROR_NO_REPLY)) { + /* This must be treated as denied. */ + r = -EBUSY; + goto fail; + } + + r = -EIO; + goto fail; + } + + if (!dbus_message_get_args( + reply, + error, + DBUS_TYPE_BOOLEAN, &good, + DBUS_TYPE_INVALID)) { + r = -EIO; + goto fail; + } + + if (!good) { + r = -EBUSY; + goto fail; + } + + if ((k = dbus_bus_request_name( + d->connection, + d->service_name, + DBUS_NAME_FLAG_DO_NOT_QUEUE| + (priority < INT32_MAX ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT : 0)| + DBUS_NAME_FLAG_REPLACE_EXISTING, + error)) < 0) { + r = -EIO; + goto fail; + } + + if (k != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + r = -EIO; + goto fail; + } + +success: + d->owning = 1; + + if (!(dbus_connection_register_object_path( + d->connection, + d->object_path, + &vtable, + d))) { + r = -ENOMEM; + goto fail; + } + + d->registered = 1; + + if (!dbus_connection_add_filter( + d->connection, + filter_handler, + d, + NULL)) { + r = -ENOMEM; + goto fail; + } + + d->filtering = 1; + + *_d = d; + return 0; + +fail: + if (m) + dbus_message_unref(m); + + if (reply) + dbus_message_unref(reply); + + if (&_error == error) + dbus_error_free(&_error); + + if (d) + rd_release(d); + + return r; +} + +void rd_release( + rd_device *d) { + + if (!d) + return; + + assert(d->ref > 0); + + if (--d->ref) + return; + + + if (d->filtering) + dbus_connection_remove_filter( + d->connection, + filter_handler, + d); + + if (d->registered) + dbus_connection_unregister_object_path( + d->connection, + d->object_path); + + if (d->owning) { + DBusError error; + dbus_error_init(&error); + + dbus_bus_release_name( + d->connection, + d->service_name, + &error); + + dbus_error_free(&error); + } + + free(d->device_name); + free(d->application_name); + free(d->application_device_name); + free(d->service_name); + free(d->object_path); + + if (d->connection) + dbus_connection_unref(d->connection); + + free(d); +} + +int rd_set_application_device_name(rd_device *d, const char *n) { + char *t; + + if (!d) + return -EINVAL; + + assert(d->ref > 0); + + if (!(t = strdup(n))) + return -ENOMEM; + + free(d->application_device_name); + d->application_device_name = t; + return 0; +} + +void rd_set_userdata(rd_device *d, void *userdata) { + + if (!d) + return; + + assert(d->ref > 0); + d->userdata = userdata; +} + +void* rd_get_userdata(rd_device *d) { + + if (!d) + return NULL; + + assert(d->ref > 0); + + return d->userdata; +} diff --git a/dbus/reserve.h b/dbus/reserve.h new file mode 100644 index 00000000..b315a08c --- /dev/null +++ b/dbus/reserve.h @@ -0,0 +1,69 @@ +#ifndef fooreservehfoo +#define fooreservehfoo + +/*** + Copyright 2009 Lennart Poettering + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#include +#include + +typedef struct rd_device rd_device; + +/* Prototype for a function that is called whenever someone else wants + * your application to release the device it has locked. A return + * value <= 0 denies the request, a positive return value agrees to + * it. Before returning your application should close the device in + * question completely to make sure the new application may access + * it. */ +typedef int (*rd_request_cb_t)( + rd_device *d, + int forced); /* Non-zero if an application forcibly took the lock away without asking. If this is the case then the return value of this call is ignored. */ + +/* Try to lock the device. Returns 0 on success, a negative errno + * style return value on error. The DBus error might be set as well if + * the error was caused D-Bus. */ +int rd_acquire( + rd_device **d, /* On success a pointer to the newly allocated rd_device object will be filled in here */ + DBusConnection *connection, + const char *device_name, /* The device to lock, e.g. "Audio0" */ + const char *application_name, /* A human readable name of the application, e.g. "PulseAudio Sound Server" */ + int32_t priority, /* The priority for this application. If unsure use 0 */ + rd_request_cb_t request_cb, /* Will be called whenever someone requests that this device shall be released. May be NULL if priority is INT32_MAX */ + DBusError *error); /* If we fail due to a D-Bus related issue the error will be filled in here. May be NULL. */ + +/* Unlock (if needed) and destroy an rd_device object again */ +void rd_release(rd_device *d); + +/* Set the application device name for an rd_device object. Returns 0 + * on success, a negative errno style return value on error. */ +int rd_set_application_device_name(rd_device *d, const char *name); + +/* Attach a userdata pointer to an rd_device */ +void rd_set_userdata(rd_device *d, void *userdata); + +/* Query the userdata pointer from an rd_device. Returns NULL if no + * userdata was set. */ +void* rd_get_userdata(rd_device *d); + +#endif diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index 04d85b02..dc538bdc 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -49,7 +49,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "generic.h" #include "memops.h" - +#include "audio_reserve.h" namespace Jack { @@ -2170,6 +2170,29 @@ int JackAlsaDriver::Open(jack_nframes_t nframes, else if (strcmp(midi_driver_name, "raw") == 0) midi = alsa_rawmidi_new((jack_client_t*)this); +#if defined(JACK_DBUS) + if (audio_reservation_init() < 0) { + jack_error("Audio reservation sevice not available...."); + } else if (strcmp(capture_driver_name, playback_driver_name) == 0) { // Same device for input and output + fReservedCaptureDevice = audio_acquire(0); + if (fReservedCaptureDevice == NULL) { + jack_error("Error audio device %s not available...", capture_driver_name); + return -1; + } + } else { + fReservedCaptureDevice = audio_acquire(0); + if (fReservedCaptureDevice == NULL) { + jack_error("Error capture audio device %s not available...", capture_driver_name); + return -1; + } + fReservedPlaybackDevice = audio_acquire(0); + if (fReservedPlaybackDevice == NULL) { + jack_error("Error playback audio device %s not available...", playback_driver_name); + return -1; + } + } +#endif + fDriver = alsa_driver_new ("alsa_pcm", (char*)playback_driver_name, (char*)capture_driver_name, NULL, nframes, @@ -2203,6 +2226,11 @@ int JackAlsaDriver::Close() { JackAudioDriver::Close(); alsa_driver_delete((alsa_driver_t*)fDriver); +#if defined(JACK_DBUS) + audio_release(fReservedCaptureDevice); + audio_release(fReservedPlaybackDevice); + audio_reservation_finish(); +#endif return 0; } diff --git a/linux/alsa/JackAlsaDriver.h b/linux/alsa/JackAlsaDriver.h index c6debff2..6fab0baf 100644 --- a/linux/alsa/JackAlsaDriver.h +++ b/linux/alsa/JackAlsaDriver.h @@ -40,6 +40,8 @@ class JackAlsaDriver : public JackAudioDriver private: jack_driver_t* fDriver; + void* fReservedCaptureDevice; + void* fReservedPlaybackDevice; void alsa_driver_release_channel_dependent_memory(alsa_driver_t *driver); int alsa_driver_check_capabilities(alsa_driver_t *driver); @@ -116,7 +118,11 @@ class JackAlsaDriver : public JackAudioDriver public: - JackAlsaDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table): JackAudioDriver(name, alias, engine, table) + JackAlsaDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) + : JackAudioDriver(name, alias, engine, table) + ,fDriver(NULL) + ,fReservedCaptureDevice(NULL) + ,fReservedPlaybackDevice(NULL) {} virtual ~JackAlsaDriver() {} diff --git a/linux/wscript b/linux/wscript index 0df5e866..5751bf60 100644 --- a/linux/wscript +++ b/linux/wscript @@ -16,7 +16,7 @@ def create_jack_driver_obj(bld, target, sources, uselib = None): driver.features.append('cc') driver.env['shlib_PATTERN'] = 'jack_%s.so' driver.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] - driver.includes = ['.', '../linux', '../posix', '../common', '../common/jack'] + driver.includes = ['.', '../linux', '../posix', '../common', '../common/jack', '../dbus'] driver.target = target driver.source = sources driver.install_path = '${ADDON_DIR}/' @@ -26,7 +26,7 @@ def create_jack_driver_obj(bld, target, sources, uselib = None): def build(bld): jackd = bld.new_task_gen('cxx', 'program') - jackd.includes = ['../linux', '../posix', '../common/jack', '../common'] + jackd.includes = ['../linux', '../posix', '../common/jack', '../common', '../dbus'] jackd.defines = 'HAVE_CONFIG_H' jackd.source = ['../common/Jackdmp.cpp'] jackd.uselib = 'PTHREAD DL RT'