@@ -746,6 +746,14 @@ get_realtime_priority_constraint() | |||||
SERVER_EXPORT jackctl_server_t * jackctl_server_create( | SERVER_EXPORT jackctl_server_t * jackctl_server_create( | ||||
bool (* on_device_acquire)(const char * device_name), | bool (* on_device_acquire)(const char * device_name), | ||||
void (* on_device_release)(const char * device_name)) | void (* on_device_release)(const char * device_name)) | ||||
{ | |||||
return jackctl_server_create2(on_device_acquire, on_device_release, NULL); | |||||
} | |||||
SERVER_EXPORT jackctl_server_t * jackctl_server_create2( | |||||
bool (* on_device_acquire)(const char * device_name), | |||||
void (* on_device_release)(const char * device_name), | |||||
void (* on_device_reservation_loop)(void)) | |||||
{ | { | ||||
struct jackctl_server * server_ptr; | struct jackctl_server * server_ptr; | ||||
union jackctl_parameter_value value; | union jackctl_parameter_value value; | ||||
@@ -922,6 +930,7 @@ SERVER_EXPORT jackctl_server_t * jackctl_server_create( | |||||
JackServerGlobals::on_device_acquire = on_device_acquire; | JackServerGlobals::on_device_acquire = on_device_acquire; | ||||
JackServerGlobals::on_device_release = on_device_release; | JackServerGlobals::on_device_release = on_device_release; | ||||
JackServerGlobals::on_device_reservation_loop = on_device_reservation_loop; | |||||
if (!jackctl_drivers_load(server_ptr)) | if (!jackctl_drivers_load(server_ptr)) | ||||
{ | { | ||||
@@ -94,6 +94,12 @@ jackctl_server_create( | |||||
bool (* on_device_acquire)(const char * device_name), | bool (* on_device_acquire)(const char * device_name), | ||||
void (* on_device_release)(const char * device_name)); | void (* on_device_release)(const char * device_name)); | ||||
SERVER_EXPORT jackctl_server_t * | |||||
jackctl_server_create2( | |||||
bool (* on_device_acquire)(const char * device_name), | |||||
void (* on_device_release)(const char * device_name), | |||||
void (* on_device_reservation_loop)(void)); | |||||
SERVER_EXPORT void | SERVER_EXPORT void | ||||
jackctl_server_destroy( | jackctl_server_destroy( | ||||
jackctl_server_t * server); | jackctl_server_t * server); | ||||
@@ -36,6 +36,7 @@ std::map<std::string, int> JackServerGlobals::fInternalsList; | |||||
bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL; | bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL; | ||||
void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL; | void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL; | ||||
void (* JackServerGlobals::on_device_reservation_loop)(void) = NULL; | |||||
int JackServerGlobals::Start(const char* server_name, | int JackServerGlobals::Start(const char* server_name, | ||||
jack_driver_desc_t* driver_desc, | jack_driver_desc_t* driver_desc, | ||||
@@ -44,6 +44,7 @@ struct SERVER_EXPORT JackServerGlobals | |||||
static bool (* on_device_acquire)(const char* device_name); | static bool (* on_device_acquire)(const char* device_name); | ||||
static void (* on_device_release)(const char* device_name); | static void (* on_device_release)(const char* device_name); | ||||
static void (* on_device_reservation_loop)(void); | |||||
JackServerGlobals(); | JackServerGlobals(); | ||||
~JackServerGlobals(); | ~JackServerGlobals(); | ||||
@@ -328,11 +328,11 @@ int main(int argc, char** argv) | |||||
copyright(stdout); | copyright(stdout); | ||||
#if defined(JACK_DBUS) && defined(__linux__) | #if defined(JACK_DBUS) && defined(__linux__) | ||||
if (getenv("JACK_NO_AUDIO_RESERVATION")) | if (getenv("JACK_NO_AUDIO_RESERVATION")) | ||||
server_ctl = jackctl_server_create(NULL, NULL); | |||||
server_ctl = jackctl_server_create2(NULL, NULL, NULL); | |||||
else | else | ||||
server_ctl = jackctl_server_create(audio_acquire, audio_release); | |||||
server_ctl = jackctl_server_create2(audio_acquire, audio_release, audio_reserve_loop); | |||||
#else | #else | ||||
server_ctl = jackctl_server_create(NULL, NULL); | |||||
server_ctl = jackctl_server_create2(NULL, NULL, NULL); | |||||
#endif | #endif | ||||
if (server_ctl == NULL) { | if (server_ctl == NULL) { | ||||
fprintf(stderr, "Failed to create server object\n"); | fprintf(stderr, "Failed to create server object\n"); | ||||
@@ -119,20 +119,33 @@ void | |||||
jackctl_wait_signals( | jackctl_wait_signals( | ||||
jackctl_sigmask_t * signals); | jackctl_sigmask_t * signals); | ||||
/** | |||||
* \bold THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED IN | |||||
* NEW JACK PROJECTS | |||||
* | |||||
* @deprecated Please use jackctl_server_create2(). | |||||
*/ | |||||
jackctl_server_t * | |||||
jackctl_server_create( | |||||
bool (* on_device_acquire)(const char * device_name), | |||||
void (* on_device_release)(const char * device_name)); | |||||
/** | /** | ||||
* Call this function to create server object. | * Call this function to create server object. | ||||
* | * | ||||
* @param on_device_acquire - Optional callback to be called before device is acquired. If false is returned, device usage will fail | * @param on_device_acquire - Optional callback to be called before device is acquired. If false is returned, device usage will fail | ||||
* @param on_device_release - Optional callback to be called after device is released. | * @param on_device_release - Optional callback to be called after device is released. | ||||
* @param on_device_reservation_loop - Optional callback to be called when looping/idling the reservation. | |||||
* | * | ||||
* @return server object handle, NULL if creation of server object | * @return server object handle, NULL if creation of server object | ||||
* failed. Successfully created server object must be destroyed with | * failed. Successfully created server object must be destroyed with | ||||
* paired call to ::jackctl_server_destroy | * paired call to ::jackctl_server_destroy | ||||
*/ | */ | ||||
jackctl_server_t * | jackctl_server_t * | ||||
jackctl_server_create( | |||||
jackctl_server_create2( | |||||
bool (* on_device_acquire)(const char * device_name), | bool (* on_device_acquire)(const char * device_name), | ||||
void (* on_device_release)(const char * device_name)); | |||||
void (* on_device_release)(const char * device_name), | |||||
void (* on_device_reservation_loop)(void)); | |||||
/** | /** | ||||
* Call this function to destroy server object. | * Call this function to destroy server object. | ||||
@@ -128,8 +128,7 @@ SERVER_EXPORT void audio_release(const char * device_name) | |||||
SERVER_EXPORT void audio_reserve_loop() | SERVER_EXPORT void audio_reserve_loop() | ||||
{ | { | ||||
if (gConnection != NULL) { | if (gConnection != NULL) { | ||||
while (dbus_connection_read_write_dispatch (gConnection, -1)) | |||||
; // empty loop body | |||||
dbus_connection_read_write_dispatch (gConnection, 200); | |||||
} | } | ||||
} | } | ||||
@@ -548,7 +548,7 @@ jack_controller_create( | |||||
INIT_LIST_HEAD(&controller_ptr->session_pending_commands); | INIT_LIST_HEAD(&controller_ptr->session_pending_commands); | ||||
controller_ptr->server = jackctl_server_create(on_device_acquire, on_device_release); | |||||
controller_ptr->server = jackctl_server_create2(on_device_acquire, on_device_release, NULL); | |||||
if (controller_ptr->server == NULL) | if (controller_ptr->server == NULL) | ||||
{ | { | ||||
jack_error("Failed to create server object"); | jack_error("Failed to create server object"); | ||||
@@ -170,7 +170,7 @@ int main(int argc, char *argv[]) | |||||
} | } | ||||
} | } | ||||
server = jackctl_server_create(NULL, NULL); | |||||
server = jackctl_server_create2(NULL, NULL, NULL); | |||||
parameters = jackctl_server_get_parameters(server); | parameters = jackctl_server_get_parameters(server); | ||||
/* | /* | ||||
@@ -67,6 +67,18 @@ static struct jack_constraint_enum_char_descriptor dither_constraint_descr_array | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
static volatile bool device_reservation_loop_running = false; | |||||
static void* on_device_reservation_loop(void*) | |||||
{ | |||||
while (device_reservation_loop_running && JackServerGlobals::on_device_reservation_loop != NULL) { | |||||
JackServerGlobals::on_device_reservation_loop(); | |||||
usleep(50*1000); | |||||
} | |||||
return NULL; | |||||
} | |||||
int JackAlsaDriver::SetBufferSize(jack_nframes_t buffer_size) | int JackAlsaDriver::SetBufferSize(jack_nframes_t buffer_size) | ||||
{ | { | ||||
jack_log("JackAlsaDriver::SetBufferSize %ld", buffer_size); | jack_log("JackAlsaDriver::SetBufferSize %ld", buffer_size); | ||||
@@ -344,6 +356,12 @@ int JackAlsaDriver::Open(jack_nframes_t nframes, | |||||
// ALSA driver may have changed the in/out values | // ALSA driver may have changed the in/out values | ||||
fCaptureChannels = ((alsa_driver_t *)fDriver)->capture_nchannels; | fCaptureChannels = ((alsa_driver_t *)fDriver)->capture_nchannels; | ||||
fPlaybackChannels = ((alsa_driver_t *)fDriver)->playback_nchannels; | fPlaybackChannels = ((alsa_driver_t *)fDriver)->playback_nchannels; | ||||
if (JackServerGlobals::on_device_reservation_loop != NULL) { | |||||
device_reservation_loop_running = true; | |||||
if (JackPosixThread::StartImp(&fReservationLoopThread, 0, 0, on_device_reservation_loop, NULL) != 0) { | |||||
device_reservation_loop_running = false; | |||||
} | |||||
} | |||||
return 0; | return 0; | ||||
} else { | } else { | ||||
Close(); | Close(); | ||||
@@ -360,6 +378,11 @@ int JackAlsaDriver::Close() | |||||
alsa_driver_delete((alsa_driver_t*)fDriver); | alsa_driver_delete((alsa_driver_t*)fDriver); | ||||
} | } | ||||
if (device_reservation_loop_running) { | |||||
device_reservation_loop_running = false; | |||||
JackPosixThread::StopImp(fReservationLoopThread); | |||||
} | |||||
if (JackServerGlobals::on_device_release != NULL) | if (JackServerGlobals::on_device_release != NULL) | ||||
{ | { | ||||
char audio_name[32]; | char audio_name[32]; | ||||
@@ -39,6 +39,7 @@ class JackAlsaDriver : public JackAudioDriver | |||||
private: | private: | ||||
jack_driver_t* fDriver; | jack_driver_t* fDriver; | ||||
jack_native_thread_t fReservationLoopThread; | |||||
void UpdateLatencies(); | void UpdateLatencies(); | ||||