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:
+61
-6
@@ -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();
|
||||
}
|
||||
@@ -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.*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user