X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fshairplay.c;h=d30d92ebb2fbb712ed9c2aee288ac987b37858ff;hb=c4312a61603ce1d52046cdd4cc9ef5acaf99adec;hp=0486f6c9dec4509ccf089b8b94328ddbc5cd1e91;hpb=ad58f7a2caeeecf25a9d69aecf96a5fcc77fffcd;p=deb_shairplay.git diff --git a/src/shairplay.c b/src/shairplay.c index 0486f6c..d30d92e 100644 --- a/src/shairplay.c +++ b/src/shairplay.c @@ -1,3 +1,26 @@ +/** + * Copyright (C) 2012-2013 Juho Vähä-Herttua + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + #include #include #include @@ -6,7 +29,7 @@ #include #ifdef WIN32 -#include +# include #endif #include @@ -20,6 +43,7 @@ typedef struct { char apname[56]; char password[56]; unsigned short port; + char hwaddr[6]; char ao_driver[56]; char ao_devicename[56]; @@ -37,6 +61,64 @@ typedef struct { } shairplay_session_t; +static int running; + +#ifndef WIN32 + +#include +static void +signal_handler(int sig) +{ + switch (sig) { + case SIGINT: + case SIGTERM: + running = 0; + break; + } +} +static void +init_signals(void) +{ + struct sigaction sigact; + + sigact.sa_handler = signal_handler; + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigaction(SIGINT, &sigact, NULL); + sigaction(SIGTERM, &sigact, NULL); +} + +#endif + + +static int +parse_hwaddr(const char *str, char *hwaddr, int hwaddrlen) +{ + int slen, i; + char *ptr, *endptr; + + slen = 3*hwaddrlen-1; + if (strlen(str) != slen) { + return 1; + } + for (i=0; i= '0' && str[i] <= '9') { + continue; + } + if (str[i] >= 'a' && str[i] <= 'f') { + continue; + } + return 1; + } + for (i=0; iapname); if (strlen(opt->ao_devicename)) { ao_append_option(&ao_options, "dev", opt->ao_devicename); } @@ -170,11 +251,15 @@ audio_set_volume(void *cls, void *opaque, float volume) static int parse_options(shairplay_options_t *opt, int argc, char *argv[]) { + const char default_hwaddr[] = { 0x48, 0x5d, 0x60, 0x7c, 0xee, 0x22 }; + char *path = argv[0]; char *arg; - strcpy(opt->apname, "Shairplay"); + /* Set default values for apname and port */ + strncpy(opt->apname, "Shairplay", sizeof(opt->apname)-1); opt->port = 5000; + memcpy(opt->hwaddr, default_hwaddr, sizeof(opt->hwaddr)); while ((arg = *++argv)) { if (!strcmp(arg, "-a")) { @@ -189,6 +274,12 @@ parse_options(shairplay_options_t *opt, int argc, char *argv[]) opt->port = atoi(*++argv); } else if (!strncmp(arg, "--server_port=", 14)) { opt->port = atoi(arg+14); + } else if (!strncmp(arg, "--hwaddr=", 9)) { + if (parse_hwaddr(arg+9, opt->hwaddr, sizeof(opt->hwaddr))) { + fprintf(stderr, "Invalid format given for hwaddr, aborting...\n"); + fprintf(stderr, "Please use hwaddr format: 01:45:89:ab:cd:ef\n"); + return 1; + } } else if (!strncmp(arg, "--ao_driver=", 12)) { strncpy(opt->ao_driver, arg+12, sizeof(opt->ao_driver)-1); } else if (!strncmp(arg, "--ao_devicename=", 16)) { @@ -211,27 +302,25 @@ parse_options(shairplay_options_t *opt, int argc, char *argv[]) } } - /* Set default values for apname and port */ - if (!strlen(opt->apname)) { - strncpy(opt->apname, "Shairplay", sizeof(opt->apname)-1); - } - if (!opt->port) { - opt->port = 5000; - } return 0; } int main(int argc, char *argv[]) { - const char hwaddr[] = { 0x48, 0x5d, 0x60, 0x7c, 0xee, 0x22 }; - shairplay_options_t options; ao_device *device = NULL; dnssd_t *dnssd; raop_t *raop; raop_callbacks_t raop_cbs; + char *password = NULL; + + int error; + +#ifndef WIN32 + init_signals(); +#endif memset(&options, 0, sizeof(options)); if (parse_options(&options, argc, argv)) { @@ -257,23 +346,40 @@ main(int argc, char *argv[]) raop_cbs.audio_destroy = audio_destroy; raop_cbs.audio_set_volume = audio_set_volume; - raop = raop_init_from_keyfile(10, &raop_cbs, "airport.key"); + raop = raop_init_from_keyfile(10, &raop_cbs, "airport.key", NULL); if (raop == NULL) { fprintf(stderr, "Could not initialize the RAOP service\n"); return -1; } + if (strlen(options.password)) { + password = options.password; + } raop_set_log_level(raop, RAOP_LOG_DEBUG); - raop_start(raop, &options.port, hwaddr, sizeof(hwaddr), NULL); + raop_start(raop, &options.port, options.hwaddr, sizeof(options.hwaddr), password); + + error = 0; + dnssd = dnssd_init(&error); + if (error) { + fprintf(stderr, "ERROR: Could not initialize dnssd library!\n"); + fprintf(stderr, "------------------------------------------\n"); + fprintf(stderr, "You could try the following resolutions based on your OS:\n"); + fprintf(stderr, "Windows: Try installing http://support.apple.com/kb/DL999\n"); + fprintf(stderr, "Debian/Ubuntu: Try installing libavahi-compat-libdnssd-dev package\n"); + raop_destroy(raop); + return -1; + } - dnssd = dnssd_init(NULL); - dnssd_register_raop(dnssd, options.apname, options.port, hwaddr, sizeof(hwaddr), 0); + dnssd_register_raop(dnssd, options.apname, options.port, options.hwaddr, sizeof(options.hwaddr), 0); + running = 1; + while (running) { #ifndef WIN32 - sleep(100); + sleep(1); #else - Sleep(100*1000); + Sleep(1000); #endif + } dnssd_unregister_raop(dnssd); dnssd_destroy(dnssd);