Add ability for the jack back end to automaticlly connect a client when the jack server comes up and to drop the client when a play session is finished.

This commit is contained in:
Mike Brady
2018-09-02 17:25:29 +01:00
parent 959aa08b8f
commit 6c6dda9cce
5 changed files with 87 additions and 24 deletions
+61 -6
View File
@@ -42,10 +42,13 @@ enum ift_type {
#define buffer_size 44100 * 4 * 2 * 2
static pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t client_mutex = PTHREAD_MUTEX_INITIALIZER;
char *audio_lmb, *audio_umb, *audio_toq, *audio_eoq;
size_t audio_occupancy; // this is in frames, not bytes. A frame is a left and
// right sample, each 16 bits, hence 4 bytes
pthread_t *open_client_if_necessary_thread = NULL;
// static void help(void);
int init(int, char **);
@@ -220,6 +223,7 @@ int jack_is_running() {
}
int jack_client_open_if_needed(void) {
pthread_mutex_lock(&client_mutex);
if (client_is_open == 0) {
jack_status_t status;
client = jack_client_open(config.jack_client_name, JackNoStartServer, &status);
@@ -245,21 +249,46 @@ int jack_client_open_if_needed(void) {
}
}
}
pthread_mutex_unlock(&client_mutex);
return client_is_open;
}
void jack_deinit() {
void jack_close(void) {
pthread_mutex_lock(&client_mutex);
if (client_is_open) {
if (jack_deactivate(client))
debug(1, "Error deactivating jack client");
if (jack_client_close(client))
debug(1, "Error closing jack client");
client_is_open = 0;
}
pthread_mutex_unlock(&client_mutex);
}
void jack_deinit() {
jack_close();
if (open_client_if_necessary_thread) {
pthread_cancel(*open_client_if_necessary_thread);
free((char *)open_client_if_necessary_thread);
}
}
void *open_client_if_necessary_thread_function(void *arg) {
int *interval = (int *)arg;
while (*interval != 0) {
if (client_is_open == 0) {
debug(1, "Try to open the jack client");
jack_client_open_if_needed();
}
sleep(*interval);
}
pthread_exit(NULL);
}
int init(__attribute__((unused)) int argc, __attribute__((unused)) char **argv) {
config.audio_backend_latency_offset = 0;
config.audio_backend_buffer_desired_length = 0.15;
config.jack_auto_client_open_interval = 1; // check every second
// get settings from settings file first, allow them to be overridden by
// command line options
@@ -272,6 +301,7 @@ int init(__attribute__((unused)) int argc, __attribute__((unused)) char **argv)
// now the specific options
if (config.cfg != NULL) {
const char *str;
int value;
/* Get the Client Name. */
if (config_lookup_string(config.cfg, "jack.client_name", &str)) {
config.jack_client_name = (char *)str;
@@ -284,6 +314,21 @@ int init(__attribute__((unused)) int argc, __attribute__((unused)) char **argv)
if (config_lookup_string(config.cfg, "jack.right_channel_name", &str)) {
config.jack_right_channel_name = (char *)str;
}
/* See if we should attempt to connect to the jack server automatically, and, if so, how often we should try. */
if (config_lookup_int(config.cfg, "jack.auto_client_open_interval", &value)) {
if ((value < 0) || (value > 300))
die("Invalid jack auto_client_open_interval \"%sd\". It should be between 0 and 300, default is %d",
value,config.jack_auto_client_open_interval);
else
config.jack_auto_client_open_interval = value;
}
/* See if we should close the client at then end of a play session. */
config_set_lookup_bool(config.cfg, "jack.auto_client_disconnect", &config.jack_auto_client_disconnect);
// now, start a thread to automatically open a client when there is a server.
}
if (config.jack_client_name == NULL)
@@ -305,16 +350,22 @@ int init(__attribute__((unused)) int argc, __attribute__((unused)) char **argv)
audio_occupancy = 0; // frames
client_is_open = 0;
jack_client_open_if_needed();
if (config.jack_auto_client_open_interval != 0) {
open_client_if_necessary_thread = malloc(sizeof(pthread_t));
if (open_client_if_necessary_thread == NULL)
die("Couldn't allocate space for jack server scanner thread");
pthread_create(open_client_if_necessary_thread, NULL, open_client_if_necessary_thread_function, &config.jack_auto_client_open_interval);
} else {
jack_client_open_if_needed();
}
return 0;
}
void jack_start(__attribute__((unused)) int i_sample_rate,
__attribute__((unused)) int i_sample_format) {
debug(1, "jack start");
// int reply = -1;
// debug(1, "jack start");
// see if the client is running. If not, try to open and initialise it
if (jack_client_open_if_needed() == 0)
@@ -358,4 +409,8 @@ void jack_flush() {
// unlock
}
void jack_stop(void) { debug(1, "jack stop"); }
void jack_stop(void) {
// debug(1, "jack stop");
if (config.jack_auto_client_disconnect)
jack_close();
}
+20
View File
@@ -568,6 +568,26 @@ uint8_t *rsa_apply(uint8_t *input, int inlen, int *outlen, int mode) {
}
#endif
int config_set_lookup_bool(config_t *cfg, char *where, int *dst) {
const char *str = 0;
if (config_lookup_string(cfg, where, &str)) {
if (strcasecmp(str, "no") == 0) {
(*dst) = 0;
return 1;
} else if (strcasecmp(str, "yes") == 0) {
(*dst) = 1;
return 1;
} else {
die("Invalid %s option choice \"%s\". It should be \"yes\" or \"no\"", where, str);
return 0;
}
} else {
return 0;
}
}
void command_set_volume(double volume) {
if (config.cmd_set_volume) {
/*Spawn a child to run the program.*/
+4
View File
@@ -205,6 +205,8 @@ typedef struct {
// debugging. Currently audio packets only...
#ifdef CONFIG_JACK
char *jack_client_name, *jack_left_channel_name, *jack_right_channel_name;
int jack_auto_client_open_interval; // will try to open a client automatically every second
int jack_auto_client_disconnect; // will disconnect from the server on end of session if set, normally clear.
#endif
} shairport_cfg;
@@ -276,6 +278,8 @@ pthread_t main_thread_id;
shairport_cfg config;
config_t config_file_stuff;
int config_set_lookup_bool(config_t *cfg, char *where, int *dst);
void command_start(void);
void command_stop(void);
void command_set_volume(double volume);
+2
View File
@@ -97,6 +97,8 @@ jack =
// client_name = "Shairport Sync"; //Set this to the name of the client that should appear in "Connections" when Shairport Sync is active.
// left_channel_name = "left"; //Set this to the name of the left output port that should appear in "Connections" when Shairport Sync is active.
// right_channel_name = "right"; //Set this to the name of the right output port that should appear in "Connections" when Shairport Sync is active.
// auto_client_open_interval = 1; // Set this to the interval in seconds between automatic attempts to open a client on the jack server. Set to zero to disable this behaviour.
// auto_client_disconnet = "no"; // Set this to "yes" to close the jack client automatically at then end of a play session. Default is no -- the client stays connected.
};
// Parameters for the "pipe" audio back end, a back end that directs raw CD-style audio output to a pipe. No interpolation is done.
-18
View File
@@ -94,24 +94,6 @@
#include <FFTConvolver/convolver.h>
#endif
static inline int config_set_lookup_bool(config_t *cfg, char *where, int *dst) {
const char *str = 0;
if (config_lookup_string(cfg, where, &str)) {
if (strcasecmp(str, "no") == 0) {
(*dst) = 0;
return 1;
} else if (strcasecmp(str, "yes") == 0) {
(*dst) = 1;
return 1;
} else {
die("Invalid %s option choice \"%s\". It should be \"yes\" or \"no\"", where, str);
return 0;
}
} else {
return 0;
}
}
static int shutting_down = 0;
char configuration_file_path[4096 + 1];
char actual_configuration_file_path[4096 + 1];