Merge pull request #2473 from thess/squeezelite-work
squeezelite: add new interface/mac address selection
This commit is contained in:
commit
7f4232ea88
5 changed files with 350 additions and 33 deletions
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
338
sound/squeezelite/patches/010-select_broadcast_interface.patch
Normal file
338
sound/squeezelite/patches/010-select_broadcast_interface.patch
Normal file
|
@ -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[]) {
|
|
@ -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]);
|
Loading…
Reference in a new issue