From a3a96cf1bd25c009f10ca215f0971c3b45ca48c0 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Feb 2013 14:52:38 +0000 Subject: [PATCH] shairport: add AirPort Express emulation software Signed-off-by: Florian Fainelli SVN-Revision: 35746 --- multimedia/shairport/Makefile | 56 +++++++++ multimedia/shairport/files/shairport.config | 3 + multimedia/shairport/files/shairport.init | 36 ++++++ .../patches/001-fix_ipv6_fallback.patch | 108 ++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 multimedia/shairport/Makefile create mode 100644 multimedia/shairport/files/shairport.config create mode 100644 multimedia/shairport/files/shairport.init create mode 100644 multimedia/shairport/patches/001-fix_ipv6_fallback.patch diff --git a/multimedia/shairport/Makefile b/multimedia/shairport/Makefile new file mode 100644 index 0000000000..332c41aec0 --- /dev/null +++ b/multimedia/shairport/Makefile @@ -0,0 +1,56 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=shairport +PKG_VERSION:=2012-10-20 +PKG_RELEASE:=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://github.com/albertz/shairport.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=4746bb11395d171ee800f074f489c42020a84932 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz + +include $(INCLUDE_DIR)/package.mk + +define Package/shairport + SECTION:=multimedia + CATEGORY:=Multimedia + DEPENDS:=+libpthread +avahi-utils +libopenssl +libao + TITLE:=ShairPort AirPort Express emulator +endef + +define Package/shairport/description + This program emulates an AirPort Express for the purpose of streaming + music from iTunes and compatible iPods. It implements a server for the + Apple RAOP protocol. + ShairPort does not support AirPlay v2 (video and photo streaming). + + It supports multiple simultaneous streams, if your audio output chain + (as detected by libao) does so. +endef + +TARGET_CFLAGS += $(FPIC) + +LIBS:=-lao -lm -lcrypto -lpthread + +MAKE_FLAGS += \ + CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \ + LDFLAGS="$(TARGET_LDFLAGS) $(LIBS)" + +define Package/shairport/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/shairport $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/etc/init.d/ + $(INSTALL_BIN) files/shairport.init $(1)/etc/init.d/shairport + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DATA) files/shairport.config $(1)/etc/config/shairport +endef + +$(eval $(call BuildPackage,shairport)) diff --git a/multimedia/shairport/files/shairport.config b/multimedia/shairport/files/shairport.config new file mode 100644 index 0000000000..83ba69299c --- /dev/null +++ b/multimedia/shairport/files/shairport.config @@ -0,0 +1,3 @@ +config shairport + option name 'AirPort' + option buffer '256' diff --git a/multimedia/shairport/files/shairport.init b/multimedia/shairport/files/shairport.init new file mode 100644 index 0000000000..f3aa75f6fa --- /dev/null +++ b/multimedia/shairport/files/shairport.init @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common +START=80 + +DAEMON="/usr/sbin/shairport" + +config_shairport() { + local cfg="$1" + local args="" + + config_get name "$cfg" name + config_get password "$cfg" password + config_get port "$cfg" port + config_get buffer "$cfg" buffer + + [ -z $name ] && name="AirPort" + args="$args -a $name" + + [ ! -z "$password" ] && args="$args -p $password" + [ ! -z "$port" ] && args="$args -o $port" + + [ -z $buffer ] && buffer="256" + args="$args -b $buffer" + + args="$args -d" + + service_start $DAEMON $args +} + +start() { + config_load shairport + config_foreach config_shairport shairport +} + +stop() { + service_stop $DAEMON +} diff --git a/multimedia/shairport/patches/001-fix_ipv6_fallback.patch b/multimedia/shairport/patches/001-fix_ipv6_fallback.patch new file mode 100644 index 0000000000..070742b428 --- /dev/null +++ b/multimedia/shairport/patches/001-fix_ipv6_fallback.patch @@ -0,0 +1,108 @@ +diff --git a/socketlib.c b/socketlib.c +index 9efdf22..eb44bcf 100644 +--- a/socketlib.c ++++ b/socketlib.c +@@ -39,9 +39,11 @@ + #include + #include + +-int common_setup(struct addrinfo *pAddrInfo) +-{ ++int common_setup(struct addrinfo **ppAddrInfo, int pPort) ++{ + int tSock; ++ struct addrinfo *pAddrInfo = *ppAddrInfo; ++ + //printAddrs(pAddrInfo); + tSock = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, 0); + #ifdef AF_INET6 +@@ -49,7 +51,17 @@ int common_setup(struct addrinfo *pAddrInfo) + { + //Fallback to ipv4 + perror("Failed to create ipv6 socket. Trying ipv4"); +- pAddrInfo->ai_family = AF_INET; ++ (*ppAddrInfo)->ai_family = AF_INET; ++ if (pPort != -1) ++ { ++ char tService[SERVLEN]; ++ sprintf(tService, "%d", pPort); // copies port to string ++ int tFamily = AF_INET; ++ if(getAddr(NULL, tService, tFamily, SOCK_STREAM, ppAddrInfo)) ++ { ++ return ERROR; // getAddr prints out error message ++ } ++ } + tSock = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, 0); + } + #endif +@@ -63,7 +75,7 @@ int setup_client(struct addrinfo *server_host) + + while(tIdx++ < RETRY_COUNT) + { +- tSockDesc = common_setup(server_host); ++ tSockDesc = common_setup(&server_host, -1); + if (tSockDesc < 0 && tIdx >= RETRY_COUNT) + { + perror("Error: Could not create socket"); +@@ -107,9 +119,23 @@ int getAddr(char *pHostname, char *pService, int pFamily, int pSockType, struct + return tError; + } + +-int setup_server(struct addrinfo *server_addr) ++int setup_server(struct addrinfo *server_addr, int pPort) + { +- int tSock = common_setup(server_addr); ++ char tService[SERVLEN]; ++ sprintf(tService, "%d", pPort); // copies port to string ++ int tFamily = AF_INET; ++ #ifdef AF_INET6 ++ //printf("Listening on IPv6 Socket\n"); ++ tFamily = AF_INET6; ++ #else ++ //printf("Listening on IPv4 Socket"); ++ #endif ++ if(getAddr(NULL, tService, tFamily, SOCK_STREAM, &server_addr)) ++ { ++ return ERROR; // getAddr prints out error message ++ } ++ ++ int tSock = common_setup(&server_addr, pPort); + if (tSock < 0) + { + perror("Error: Could not create server socket"); +@@ -154,21 +180,7 @@ int acceptClient(int pSock, struct addrinfo *server_addr) + + int setupListenServer(struct addrinfo **pAddrInfo, int pPort) + { +- char tService[SERVLEN]; +- sprintf(tService, "%d", pPort); // copies port to string +- int tFamily = AF_INET; +- #ifdef AF_INET6 +- //printf("Listening on IPv6 Socket\n"); +- tFamily = AF_INET6; +- #else +- //printf("Listening on IPv4 Socket"); +- #endif +- if(getAddr(NULL, tService, tFamily, SOCK_STREAM, pAddrInfo)) +- { +- return ERROR; // getAddr prints out error message +- } +- +- int tSocketDescriptor = setup_server(*pAddrInfo); ++ int tSocketDescriptor = setup_server(*pAddrInfo, pPort); + char tAddr[INET6_ADDRSTRLEN]; + socklen_t tSize = INET6_ADDRSTRLEN; + inet_ntop((*pAddrInfo)->ai_family, (*pAddrInfo)->ai_addr, tAddr, tSize); +diff --git a/socketlib.h b/socketlib.h +index 6d501f3..5cb1bf0 100644 +--- a/socketlib.h ++++ b/socketlib.h +@@ -24,7 +24,7 @@ + #define DEFAULT_UNIX "/unix" + + int setup_client(struct addrinfo *server_info); +-int setup_server(struct addrinfo *server_address); ++int setup_server(struct addrinfo *server_address, int pPort); + int setupListenServer(struct addrinfo **pAddrInfo, int pPort); + int acceptClient(int pSock, struct addrinfo *server_addr); + void delay(long pMillisecs, struct timeval *pRes); -- 2.30.2