diff --git a/sound/squeezelite/Makefile b/sound/squeezelite/Makefile index 8a1274ccf..086bea868 100644 --- a/sound/squeezelite/Makefile +++ b/sound/squeezelite/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2015 OpenWrt.org +# Copyright (C) 2015-2016 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=squeezelite PKG_VERSION:=1.8 -PKG_RELEASE=1 +PKG_RELEASE=2 PKG_LICENSE:=GPL-3.0 PKG_LICENSE_FILES:=LICENSE.txt diff --git a/sound/squeezelite/files/squeezelite.conf b/sound/squeezelite/files/squeezelite.conf index 57d1b73dd..6bfcaab3a 100644 --- a/sound/squeezelite/files/squeezelite.conf +++ b/sound/squeezelite/files/squeezelite.conf @@ -9,4 +9,5 @@ config options 'options' option decoder_auto_conf '1' option dsd_over_pcm '0' option ircontrol '0' + option interface '' option enabled '1' diff --git a/sound/squeezelite/files/squeezelite.init b/sound/squeezelite/files/squeezelite.init index 3fa008f63..71923120f 100644 --- a/sound/squeezelite/files/squeezelite.init +++ b/sound/squeezelite/files/squeezelite.init @@ -51,6 +51,9 @@ make_cmdline() { config_get model_name options model_name "SqueezeLite" cmdline="$cmdline -M $model_name" + config_get interface options interface "" + [ -n $interface ] && cmdline="$cmdline -I $interface" + config_get device options device "" [ -n $device ] && cmdline="$cmdline -o $device" @@ -96,10 +99,15 @@ make_cmdline() { # ***NOTE: codec lib names are in squeezelite.h (set decode_auto_conf to 0 to ignore) # local excl_codecs="" + local vorbis_lib="libvorbisidec.so.1" + excl_codecs=`checkcodec decode_flac "libFLAC.so.8" flac "$excl_codecs"` excl_codecs=`checkcodec decode_mp3 "libmad.so.0" mp3 "$excl_codecs"` excl_codecs=`checkcodec decode_aac "libfaad.so.2" aac "$excl_codecs"` - excl_codecs=`checkcodec decode_ogg "libvorbisfile.so.3" ogg "$excl_codecs"` + + [ -e "/usr/lib/$vorbis_lib" ] || vorbis_lib="libvorbisfile.so.3" + + excl_codecs=`checkcodec decode_ogg "$vorbis_lib" ogg "$excl_codecs"` excl_codecs=`checkcodec decode_wma_alac "libavcodec.so.56" wma,alac "$excl_codecs"` cmdline="$cmdline $excl_codecs" diff --git a/sound/squeezelite/patches/010-select_broadcast_interface.patch b/sound/squeezelite/patches/010-select_broadcast_interface.patch new file mode 100644 index 000000000..17d083e72 --- /dev/null +++ b/sound/squeezelite/patches/010-select_broadcast_interface.patch @@ -0,0 +1,338 @@ +--- a/main.c ++++ b/main.c +@@ -69,6 +69,7 @@ static void usage(const char *argv0) { + #if IR + " -i []\tEnable lirc remote control support (lirc config file ~/.lircrc used if filename not specified)\n" + #endif ++ " -I \t\tNetwork interface used to send discovery\n" + " -m \t\tSet mac address, format: ab:cd:ef:12:34:56\n" + " -M \tSet the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")\n" + " -n \t\tSet the player name\n" +@@ -197,6 +198,8 @@ int main(int argc, char **argv) { + char *modelname = NULL; + char *logfile = NULL; + u8_t mac[6]; ++ char *iface = NULL; ++ in_addr_t bcast_addr = 0; + unsigned stream_buf_size = STREAMBUF_SIZE; + unsigned output_buf_size = 0; // set later + unsigned rates[MAX_SUPPORTED_SAMPLERATES] = { 0 }; +@@ -233,6 +236,7 @@ int main(int argc, char **argv) { + log_level log_ir = lWARN; + #endif + ++ memset(mac, 0, sizeof(mac)); + char *optarg = NULL; + int optind = 1; + int i; +@@ -240,8 +244,6 @@ int main(int argc, char **argv) { + #define MAXCMDLINE 512 + char cmdline[MAXCMDLINE] = ""; + +- get_mac(mac); +- + for (i = 0; i < argc && (strlen(argv[i]) + strlen(cmdline) + 2 < MAXCMDLINE); i++) { + strcat(cmdline, argv[i]); + strcat(cmdline, " "); +@@ -249,7 +251,7 @@ int main(int argc, char **argv) { + + while (optind < argc && strlen(argv[optind]) >= 2 && argv[optind][0] == '-') { + char *opt = argv[optind] + 1; +- if (strstr("oabcCdefmMnNpPrs" ++ if (strstr("oabcCdefImMnNpPrs" + #if ALSA + "UV" + #endif +@@ -334,6 +336,9 @@ int main(int argc, char **argv) { + case 'f': + logfile = optarg; + break; ++ case 'I': ++ iface = optarg; ++ break; + case 'm': + { + int byte = 0; +@@ -556,6 +561,11 @@ int main(int argc, char **argv) { + winsock_init(); + #endif + ++ if (!(bcast_addr = get_iface_info(log_slimproto, iface, mac))) { ++ fprintf(stderr, "Error binding to network or none given\n"); ++ exit(1); ++ } ++ + stream_init(log_stream, stream_buf_size); + + if (!strcmp(output_device, "-")) { +@@ -599,7 +609,7 @@ int main(int argc, char **argv) { + exit(1); + } + +- slimproto(log_slimproto, server, mac, name, namefile, modelname); ++ slimproto(log_slimproto, server, bcast_addr, mac, name, namefile, modelname); + + decode_close(); + stream_close(); +--- a/squeezelite.h ++++ b/squeezelite.h +@@ -374,7 +374,7 @@ typedef enum { EVENT_TIMEOUT = 0, EVENT_ + + char *next_param(char *src, char c); + u32_t gettime_ms(void); +-void get_mac(u8_t *mac); ++in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac); + void set_nonblock(sockfd s); + int connect_timeout(sockfd sock, const struct sockaddr *addr, socklen_t addrlen, int timeout); + void server_addr(char *server, in_addr_t *ip_ptr, unsigned *port_ptr); +@@ -426,7 +426,7 @@ void buf_init(struct buffer *buf, size_t + void buf_destroy(struct buffer *buf); + + // slimproto.c +-void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname); ++void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t *mac, const char *name, const char *namefile, const char *modelname); + void slimproto_stop(void); + void wake_controller(void); + +--- a/slimproto.c ++++ b/slimproto.c +@@ -107,7 +107,7 @@ void send_packet(u8_t *packet, size_t le + } + } + +-static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t mac[6]) { ++static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t *mac) { + const char *base_cap = "Model=squeezelite,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Firmware=" VERSION; + struct HELO_packet pkt; + +@@ -730,7 +730,7 @@ void wake_controller(void) { + wake_signal(wake_e); + } + +-in_addr_t discover_server(void) { ++in_addr_t discover_server(in_addr_t bcast_addr) { + struct sockaddr_in d; + struct sockaddr_in s; + char *buf; +@@ -746,7 +746,7 @@ in_addr_t discover_server(void) { + memset(&d, 0, sizeof(d)); + d.sin_family = AF_INET; + d.sin_port = htons(PORT); +- d.sin_addr.s_addr = htonl(INADDR_BROADCAST); ++ d.sin_addr.s_addr = bcast_addr; + + pollinfo.fd = disc_sock; + pollinfo.events = POLLIN; +@@ -777,7 +777,7 @@ in_addr_t discover_server(void) { + #define FIXED_CAP_LEN 256 + #define VAR_CAP_LEN 128 + +-void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname) { ++void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t *mac, const char *name, const char *namefile, const char *modelname) { + struct sockaddr_in serv_addr; + static char fixed_cap[FIXED_CAP_LEN], var_cap[VAR_CAP_LEN] = ""; + bool reconnect = false; +@@ -795,7 +795,7 @@ void slimproto(log_level level, char *se + } + + if (!slimproto_ip) { +- slimproto_ip = discover_server(); ++ slimproto_ip = discover_server(bcast_addr); + } + + if (!slimproto_port) { +@@ -870,7 +870,7 @@ void slimproto(log_level level, char *se + + // rediscover server if it was not set at startup + if (!server && ++failed_connect > 5) { +- slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(); ++ slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(bcast_addr); + } + + } else { +--- a/utils.c ++++ b/utils.c +@@ -21,11 +21,11 @@ + #include "squeezelite.h" + + #if LINUX || OSX || FREEBSD +-#include ++#include + #include +-#include +-#if FREEBSD + #include ++#include ++#if FREEBSD || OSX + #include + #include + #endif +@@ -33,15 +33,11 @@ + #if WIN + #include + #endif +-#if OSX +-#include +-#include +-#include +-#include +-#endif + + #include + ++static log_level loglevel; ++ + // logging functions + const char *logtime(void) { + static char buf[100]; +@@ -99,67 +95,101 @@ u32_t gettime_ms(void) { + #endif + } + +-// mac address +-#if LINUX +-// search first 4 interfaces returned by IFCONF +-void get_mac(u8_t mac[]) { +- struct ifconf ifc; +- struct ifreq *ifr, *ifend; +- struct ifreq ifreq; +- struct ifreq ifs[4]; +- +- mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0; +- +- int s = socket(AF_INET, SOCK_DGRAM, 0); +- +- ifc.ifc_len = sizeof(ifs); +- ifc.ifc_req = ifs; +- +- if (ioctl(s, SIOCGIFCONF, &ifc) == 0) { +- ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq)); +- +- for (ifr = ifc.ifc_req; ifr < ifend; ifr++) { +- if (ifr->ifr_addr.sa_family == AF_INET) { +- +- strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); +- if (ioctl (s, SIOCGIFHWADDR, &ifreq) == 0) { +- memcpy(mac, ifreq.ifr_hwaddr.sa_data, 6); +- if (mac[0]+mac[1]+mac[2] != 0) { +- break; +- } ++// Get broadcast address for interface (given or first available) ++// Return MAC address if none given ++#if LINUX || OSX || FREEBSD ++ ++in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac) { ++ struct ifaddrs *addrs, *ifa; ++ struct sockaddr *sdl; ++ char ifname[16]; ++ unsigned char *ptr; ++ in_addr_t bcast_addr = 0; ++ int have_mac = 0, have_ifname = 0; ++ ++ loglevel = level; ++ ++ // Check for non-zero MAC ++ if ((mac[0] | mac[1] | mac[2]) != 0) ++ have_mac = 1; ++ ++ // Copy interface name, if it was provided. ++ if (iface != NULL) ++ { ++ if( strlen(iface) > sizeof(ifname) ) ++ return -1; ++ ++ strncpy(ifname, iface, sizeof(ifname)); ++ have_ifname = 1; ++ } ++ ++ if (getifaddrs(&addrs) == 0) { ++ //iterate to find corresponding ethernet address ++ for (ifa = addrs; ifa; ifa = ifa->ifa_next) { ++ // Skip LOOPBACK interfaces, DOWN interfaces and interfaces that ++ // don't support BROADCAST. ++ if ((ifa->ifa_flags & IFF_LOOPBACK) ++ || !(ifa->ifa_flags & IFF_UP) ++ || !(ifa->ifa_flags & IFF_BROADCAST)) ++ { ++ continue; ++ } ++ ++ if (!have_ifname) ++ { ++ // We have found a valid interface name. Keep it. ++ strncpy(ifname, ifa->ifa_name, sizeof(ifname)); ++ have_ifname = 1; ++ } else { ++ if (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) != 0) ++ { ++ // This is not the interface we're looking for. ++ continue; + } + } +- } +- } + +- close(s); +-} +-#endif + +-#if OSX || FREEBSD +-void get_mac(u8_t mac[]) { +- struct ifaddrs *addrs, *ptr; +- const struct sockaddr_dl *dlAddr; +- const unsigned char *base; +- +- mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0; +- +- if (getifaddrs(&addrs) == 0) { +- ptr = addrs; +- while (ptr) { +- if (ptr->ifa_addr->sa_family == AF_LINK && ((const struct sockaddr_dl *) ptr->ifa_addr)->sdl_type == IFT_ETHER) { +- dlAddr = (const struct sockaddr_dl *)ptr->ifa_addr; +- base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen]; +- memcpy(mac, base, min(dlAddr->sdl_alen, 6)); ++ // Check address family. ++ if ((ifa->ifa_addr->sa_family == AF_INET) && ++ (((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr != 0)) ++ { ++ // Get broadcast address and MAC address ++ bcast_addr = ((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr; + break; + } +- ptr = ptr->ifa_next; ++ else ++ { ++ // Address is not IPv4 ++ if (iface == NULL) ++ have_ifname = 0; ++ } ++ + } ++ ++ // Find MAC address matching interface ++ if (!have_mac && (bcast_addr != 0)) { ++ for (ifa = addrs; ifa; ifa = ifa->ifa_next) { ++ if ((ifa->ifa_addr->sa_family == PF_PACKET) && ++ (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) == 0)) { ++ sdl = (struct sockaddr *)(ifa->ifa_addr); ++ ptr = (unsigned char *)sdl->sa_data; ++ memcpy(mac, ptr + 10, 6); ++ have_mac = 1; ++ } ++ } ++ } ++ + freeifaddrs(addrs); + } ++ ++ LOG_INFO("Interface: %s, broadcast: %08X, macaddr = %02x:%02x:%02x:%02x:%02x:%02x", ++ ifname, bcast_addr, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ ++ return bcast_addr; + } + #endif + ++ + #if WIN + #pragma comment(lib, "IPHLPAPI.lib") + void get_mac(u8_t mac[]) { diff --git a/sound/squeezelite/patches/010-wait_for_nonzero_mac.patch b/sound/squeezelite/patches/010-wait_for_nonzero_mac.patch deleted file mode 100644 index 69d4f34a8..000000000 --- a/sound/squeezelite/patches/010-wait_for_nonzero_mac.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- a/main.c -+++ b/main.c -@@ -187,6 +187,17 @@ static void sighandler(int signum) { - signal(signum, SIG_DFL); - } - -+// Waits for nonzero MAC -+static void get_nonzero_mac(u8_t mac[], u32_t timeout_ms) { -+ u32_t wait_timeout = gettime_ms() + timeout_ms; -+ do{ -+ get_mac(mac); -+ if ((mac[0]+mac[1]+mac[2]+mac[3]+mac[4]+mac[5]) != 0) { -+ break; -+ } -+ }while(wait_timeout > gettime_ms()); -+} -+ - int main(int argc, char **argv) { - char *server = NULL; - char *output_device = "default"; -@@ -240,7 +251,8 @@ int main(int argc, char **argv) { - #define MAXCMDLINE 512 - char cmdline[MAXCMDLINE] = ""; - -- get_mac(mac); -+ // Waits for nonzero MAC -+ get_nonzero_mac(mac,10000); - - for (i = 0; i < argc && (strlen(argv[i]) + strlen(cmdline) + 2 < MAXCMDLINE); i++) { - strcat(cmdline, argv[i]);