squeezelite: add new interface/mac address selection 2473/head
authorTed Hess <thess@kitschensync.net>
Mon, 7 Mar 2016 22:17:53 +0000 (17:17 -0500)
committerTed Hess <thess@kitschensync.net>
Tue, 8 Mar 2016 14:57:15 +0000 (09:57 -0500)
allow dynamic linking to either vorbisifile or vorbisidec

Signed-off-by: Ted Hess <thess@kitschensync.net>
sound/squeezelite/Makefile
sound/squeezelite/files/squeezelite.conf
sound/squeezelite/files/squeezelite.init
sound/squeezelite/patches/010-select_broadcast_interface.patch [new file with mode: 0644]
sound/squeezelite/patches/010-wait_for_nonzero_mac.patch [deleted file]

index 8a1274ccfe63da384062447b0370fbc381e4efe8..086bea8682eab2ceee414fad22871022a596210a 100644 (file)
@@ -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
index 57d1b73dd420e4edab5cc6dcaf721376cb6a583f..6bfcaab3aa77e51e9edc86d6f0ef4e45c0106662 100644 (file)
@@ -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'
index 3fa008f63ee589f1212eb43e444ef6c03defdb98..71923120f7d2691adc52258ddbf8a16c5f491697 100644 (file)
@@ -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 (file)
index 0000000..17d083e
--- /dev/null
@@ -0,0 +1,338 @@
+--- a/main.c
++++ b/main.c
+@@ -69,6 +69,7 @@ static void usage(const char *argv0) {
+ #if IR
+                  "  -i [<filename>]\tEnable lirc remote control support (lirc config file ~/.lircrc used if filename not specified)\n"
+ #endif
++                 "  -I <interface>\t\tNetwork interface used to send discovery\n"
+                  "  -m <mac addr>\t\tSet mac address, format: ab:cd:ef:12:34:56\n"
+                  "  -M <modelname>\tSet the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")\n"
+                  "  -n <name>\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 <sys/ioctl.h>
++#include <sys/types.h>
+ #include <net/if.h>
+-#include <netdb.h>
+-#if FREEBSD
+ #include <ifaddrs.h>
++#include <netdb.h>
++#if FREEBSD || OSX
+ #include <net/if_dl.h>
+ #include <net/if_types.h>
+ #endif
+@@ -33,15 +33,11 @@
+ #if WIN
+ #include <iphlpapi.h>
+ #endif
+-#if OSX
+-#include <net/if_dl.h>
+-#include <net/if_types.h>
+-#include <ifaddrs.h>
+-#include <netdb.h>
+-#endif
+ #include <fcntl.h>
++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 (file)
index 69d4f34..0000000
+++ /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]);