From c445510d5a322bf395a09d8f9bce77a730fc52b6 Mon Sep 17 00:00:00 2001 From: Till Zimmermann Date: Tue, 19 Jun 2018 20:25:22 +0200 Subject: [PATCH] minor improvements on the mqtt feature --- README.md | 3 +++ configure.ac | 4 ++-- mqtt.c | 40 +++++++++++++++++++++++----------------- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 7301968ea..20ef018f6 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ What else? * Metadata — Shairport Sync can deliver metadata supplied by the source, such as Album Name, Artist Name, Cover Art, etc. through a pipe or UDP socket to a recipient application program — see https://github.com/mikebrady/shairport-sync-metadata-reader for a sample recipient. Sources that supply metadata include iTunes and the Music app in iOS. * Raw Audio — Shairport Sync can deliver raw PCM audio to standard output or to a pipe. This output is delivered synchronously with the source after the appropriate latency and is not interpolated or "stuffed" on its way through Shairport Sync. * Autotools and Libtool Support — the Shairport Sync build process uses GNU `autotools` and `libtool` to examine and configure the build environment — important for portability and for cross compilation. Previous versions of Shairport looked at the current system to determine which packages were available, instead of looking at the target system for what packages were available. +* A native mqtt interface for metadata and/or controls Heritage ------- @@ -124,6 +125,7 @@ The following libraries are required: Optional: * libsoxr * libalac (This is a library containing the Apple ALAC decoder.) +* libmosquitto (To enable the mqtt-metadata-interface) Many Linux distributions have Avahi and OpenSSL already in place, so normally it probably makes sense to choose those options rather than tinysvcmdns or mbed TLS. The `libsoxr` library is available in recent Linux distributions, but it requires lots of processor power — chances are an embedded processor won't be able to keep up. @@ -166,6 +168,7 @@ $ autoreconf -i -f - `--with-soxr` for libsoxr-based resampling. - `--with-piddir` for specifying where the PID file should be stored. This directory is normally chosen automatically. The directory must be writable. If you use this option, you may have to edit the init script to search for the PID file in your new location. - `--with-metadata` to add support for Shairport Sync to pipe metadata to a compatible application of your choice. See https://github.com/mikebrady/shairport-sync-metadata-reader for a sample metadata reader. +- `--with-mqtt-client` to add support for publishing metadata and remote control via [MQTT](https://en.wikipedia.org/wiki/MQTT) - `--with-configfiles` to install a configuration file and a separate sample file at the `make install` stage. Default is to install. An existing `/etc/shairport-sync.conf` will not be overwritten. - `--with-pkg-config` to use pkg-config to find libraries. Default is to use pkg-config — this option is for special purpose use. - `--with-apple-alac` to include the Apple ALAC Decoder. diff --git a/configure.ac b/configure.ac index f79041c5e..5b1520c79 100644 --- a/configure.ac +++ b/configure.ac @@ -315,7 +315,7 @@ AM_CONDITIONAL([USE_MPRIS_CLIENT], [test "x$HAS_MPRIS_CLIENT" = "x1"]) #AM_CONDITIONAL([USE_DBUS_CORE_AND_DACP], [test "x$HAS_MPRIS" = "x1" -o "x$HAS_DBUS" = "x1"]) # Look for mqtt flag -AC_ARG_WITH(mqtt-interface, [ --with-mqtt-interface = include support for the native Shairport Sync MQTT interface], [ +AC_ARG_WITH(mqtt-client, [ --with-mqtt-client = include support for the native Shairport Sync MQTT interface], [ AC_MSG_RESULT(>>Including MQTT support) HAS_MQTT=1 AC_DEFINE([HAVE_MQTT], 1, [Needed by the compiler.]) @@ -332,7 +332,7 @@ AC_ARG_WITH(mqtt-interface, [ --with-mqtt-interface = include support for the n AM_CONDITIONAL([USE_MQTT], [test "x$HAS_MQTT" = "x1"]) -if test "x$HAS_MPRIS" = "x1" -o "x$HAS_DBUS" = "x1" -o "x$HAS_MQTT"; then +if test "x$HAS_MPRIS" = "x1" || test "x$HAS_DBUS" = "x1" || test "x$HAS_MQTT" = "x1"; then AC_MSG_RESULT(>>Including the metadata hub) HAS_METADATA_HUB=1 AC_DEFINE([HAVE_METADATA_HUB], 1, [Needed by the compiler.]) diff --git a/mqtt.c b/mqtt.c index 478c476fa..85efcf6e2 100644 --- a/mqtt.c +++ b/mqtt.c @@ -15,11 +15,12 @@ #include "mqtt.h" //this holds the mosquitto client -struct mosquitto *mosq = NULL; +struct mosquitto *global_mosq = NULL; char *topic = NULL; //mosquitto logging -void _cb_log(struct mosquitto *mosq, void *userdata, int level, const char *str){ +void _cb_log( __attribute__((unused)) struct mosquitto *mosq, + __attribute__((unused)) void *userdata, int level, const char *str){ switch(level){ case MOSQ_LOG_DEBUG: debug(1, str); @@ -40,7 +41,8 @@ void _cb_log(struct mosquitto *mosq, void *userdata, int level, const char *str) } //mosquitto message handler -void on_message(struct mosquitto* mosq, void* userdata, const struct mosquitto_message* msg){ +void on_message( __attribute__((unused)) struct mosquitto* mosq, + __attribute__((unused)) void* userdata, const struct mosquitto_message* msg){ //null-terminate the payload char payload[msg->payloadlen+1]; @@ -59,7 +61,7 @@ void on_message(struct mosquitto* mosq, void* userdata, const struct mosquitto_m //send command if it's a valid one while(commands[it++]!=NULL){ - if( msg->payloadlen>=strlen(commands[it]) && + if( (size_t)msg->payloadlen>=strlen(commands[it]) && strncmp(msg->payload, commands[it], strlen(commands[it]))==0 ){ debug(1, "[MQTT]: DACP Command: %s\n",commands[it]); @@ -69,11 +71,15 @@ void on_message(struct mosquitto* mosq, void* userdata, const struct mosquitto_m } } -void on_disconnect(struct mosquitto* mosq, void* userdata, int rc){ +void on_disconnect( __attribute__((unused)) struct mosquitto* mosq, + __attribute__((unused)) void* userdata, + __attribute__((unused)) int rc){ debug(1, "[MQTT]: disconnected"); } -void on_connect(struct mosquitto* mosq, void* userdata, int rc){ +void on_connect(struct mosquitto* mosq, + __attribute__((unused)) void* userdata, + __attribute__((unused)) int rc){ debug(1, "[MQTT]: connected"); //subscribe if requested @@ -89,7 +95,7 @@ void mqtt_publish(char* topic, char* data, uint32_t length){ char fulltopic[strlen(config.mqtt_topic)+strlen(topic)+3]; snprintf(fulltopic, strlen(config.mqtt_topic)+strlen(topic)+2, "%s/%s", config.mqtt_topic, topic); debug(1, "[MQTT]: publishing under %s",fulltopic); - mosquitto_publish(mosq, NULL, fulltopic, length, data, 0, 0); + mosquitto_publish(global_mosq, NULL, fulltopic, length, data, 0, 0); } //handler for incoming metadata @@ -167,8 +173,8 @@ int initialise_mqtt() { } int keepalive = 60; mosquitto_lib_init(); - if( !(mosq = mosquitto_new(config.service_name, true, NULL)) ){ - die("[MQTT]: FATAL: Could not create mosquitto object! %d\n", mosq); + if( !(global_mosq = mosquitto_new(config.service_name, true, NULL)) ){ + die("[MQTT]: FATAL: Could not create mosquitto object! %d\n", global_mosq); } if( @@ -177,7 +183,7 @@ int initialise_mqtt() { config.mqtt_certfile != NULL || config.mqtt_keyfile != NULL ){ - if(mosquitto_tls_set(mosq,config.mqtt_cafile, config.mqtt_capath, config.mqtt_certfile, config.mqtt_keyfile, NULL) != MOSQ_ERR_SUCCESS) { + if(mosquitto_tls_set(global_mosq,config.mqtt_cafile, config.mqtt_capath, config.mqtt_certfile, config.mqtt_keyfile, NULL) != MOSQ_ERR_SUCCESS) { die("[MQTT]: TLS Setup failed"); } } @@ -186,22 +192,22 @@ int initialise_mqtt() { config.mqtt_username != NULL || config.mqtt_password != NULL ){ - if(mosquitto_username_pw_set(mosq,config.mqtt_username,config.mqtt_password) != MOSQ_ERR_SUCCESS) { + if(mosquitto_username_pw_set(global_mosq,config.mqtt_username,config.mqtt_password) != MOSQ_ERR_SUCCESS) { die("[MQTT]: Username/Password set failed"); } } - mosquitto_log_callback_set(mosq, _cb_log); + mosquitto_log_callback_set(global_mosq, _cb_log); if(config.mqtt_enable_remote){ - mosquitto_message_callback_set(mosq, on_message); + mosquitto_message_callback_set(global_mosq, on_message); } - mosquitto_disconnect_callback_set(mosq, on_disconnect); - mosquitto_connect_callback_set(mosq, on_connect); - if(mosquitto_connect(mosq, config.mqtt_hostname, config.mqtt_port, keepalive)){ + mosquitto_disconnect_callback_set(global_mosq, on_disconnect); + mosquitto_connect_callback_set(global_mosq, on_connect); + if(mosquitto_connect(global_mosq, config.mqtt_hostname, config.mqtt_port, keepalive)){ inform("[MQTT]: Could not establish a mqtt connection"); } - if(mosquitto_loop_start(mosq) != MOSQ_ERR_SUCCESS){ + if(mosquitto_loop_start(global_mosq) != MOSQ_ERR_SUCCESS){ inform("[MQTT]: Could start MQTT Main loop"); }