shairport: add AirPort Express emulation software

Signed-off-by: Florian Fainelli <florian@openwrt.org>

git-svn-id: svn://svn.openwrt.org/openwrt/packages@35746 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
florian 2013-02-22 14:52:38 +00:00
parent 7f2cae5f49
commit 51584e3ed3
4 changed files with 203 additions and 0 deletions

View File

@ -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))

View File

@ -0,0 +1,3 @@
config shairport
option name 'AirPort'
option buffer '256'

View File

@ -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
}

View File

@ -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 <openssl/bio.h>
#include <openssl/buffer.h>
-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);