/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ * */ #ifndef kVersionString #include "../revision.h" #endif #include "MP3Broadcaster.h" #include "OSHeaders.h" #include "SocketUtils.h" #include "OSThread.h" #include "OS.h" #include "OSMemory.h" #include #include "getopt.h" MP3Broadcaster* gBroadcaster = NULL; static void RegisterEventHandlers(); static void SignalEventHandler( int signalID ); void version() { /* print PlaylistBroadcaster version and build info see revision.h */ //RoadRunner/2.0.0-v24 Built on: Sep 17 1999 , 16:09:53 //revision.h (project level file) -- include with -i option qtss_printf("MP3Broadcaster/%s Built on: %s, %s\n", kVersionString, __DATE__, __TIME__ ); } void usage() { /* print MP3Broadcaster usage string */ qtss_printf("usage: MP3Broadcaster [-v] [-d] [-i] [-x] [-X] [-a ipAddress] [-p portNum] [-l filename] [-w filename] [-e filename] -c filename\n" ); qtss_printf(" -v: display version\n" ); qtss_printf(" -d: run in foreground\n" ); qtss_printf(" -i: use 'icy-' protocol header prefix (default is 'x-audio-')\n" ); qtss_printf(" -x: preflight configuration\n" ); qtss_printf(" -X: check MP3 files\n" ); qtss_printf(" -a : broadcast to this address (default = local loopback)\n" ); qtss_printf(" -p : broadcast to this port (default = 8000)\n" ); qtss_printf(" -c : path to config file\n" ); qtss_printf(" -l : path to playlist (overrides config file)\n" ); qtss_printf(" -w : path to dir to create temp lists (overrides config file)\n" ); qtss_printf(" -e : print output to error file\n" ); } int main(int argc, char* argv[]) { bool daemonize = true; bool useICY = false; char* ipaddr = NULL; int port = 0; char* config = NULL; char* playList = NULL; char* workingDir = NULL; char ch; bool preflight = false; bool checkMP3s = false; char* errorlog = NULL; // extern int optind; extern char* optarg; #ifdef __Win32__ // // Start Win32 DLLs WORD wsVersion = MAKEWORD(1, 1); WSADATA wsData; (void)::WSAStartup(wsVersion, &wsData); #endif OS::Initialize(); OSThread::Initialize(); OSMemory::SetMemoryError(ENOMEM); Socket::Initialize(); SocketUtils::Initialize(false); if (SocketUtils::GetNumIPAddrs() == 0) { qtss_printf("Network initialization failed. IP must be enabled to run MP3Broadcaster\n"); ::exit(0); } while ( (ch = getopt(argc,argv, "vdixXa:p:c:l:e:w:")) != EOF ) // opt: means requires option { switch(ch) { case 'v': ::version(); ::usage(); return 0; case 'd': daemonize = false; break; case 'i': useICY = true; break; case 'a': ipaddr = (char*)malloc(strlen(optarg)+1); strcpy(ipaddr, optarg); break; case 'p': port = atoi(optarg); break; case 'c': config = (char*)malloc(strlen(optarg)+1); strcpy(config, optarg); break; case 'l': playList = (char*)malloc(strlen(optarg)+1); strcpy(playList, optarg); break; case 'w': workingDir = (char*)malloc(strlen(optarg)+1); break; case 'x': preflight = true; daemonize = false; break; case 'X': preflight = true; daemonize = false; checkMP3s = true; break; case 'e': errorlog = (char*)malloc(strlen(optarg)+1); strcpy(errorlog, optarg); break; default: ::usage(); return 0; } } if (config == NULL) { qtss_printf("missing -c option\n"); ::usage(); return 0; } if (errorlog != NULL) { if (preflight) freopen(errorlog, "w", stdout); else freopen(errorlog, "a", stdout); ::setvbuf(stdout, (char *)NULL, _IONBF, 0); } gBroadcaster = new MP3Broadcaster(ipaddr, port, config, playList, workingDir, useICY); if (!gBroadcaster->IsValid()) { qtss_printf("Bad config--exiting\n"); qtss_printf("Warnings: 0\nErrors: 1\n"); return 0; } RegisterEventHandlers(); gBroadcaster->PreFlightOrBroadcast(preflight, daemonize, false, false, checkMP3s, errorlog); return 0; } static void RegisterEventHandlers() { #ifdef __Win32__ SetConsoleCtrlHandler( (PHANDLER_ROUTINE) SignalEventHandler, true); return; #endif #ifndef __Win32__ struct sigaction act; #if defined(sun) || defined(i386) || defined(__MacOSX__) || defined(__sgi__) || defined(__osf__) || defined(__hpux__) || defined(__linux) || defined(__linuxppc__) sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = (void(*)(int))&SignalEventHandler; #else act.sa_mask = 0; act.sa_flags = 0; act.sa_handler = (void(*)(...))&SignalEventHandler; #endif if ( ::signal(SIGTERM, SIG_IGN) != SIG_IGN) { // from kill... if ( ::sigaction(SIGTERM, &act, NULL) != 0 ) { qtss_printf( "- PlaylistBroadcaster: System error (%"_SPOINTERSIZEARG_").\n", (PointerSizedInt)SIG_ERR ); } } if ( ::signal(SIGINT, SIG_IGN) != SIG_IGN) { // ^C signal if ( ::sigaction(SIGINT, &act, NULL) != 0 ) { qtss_printf( "- PlaylistBroadcaster: System error (%"_SPOINTERSIZEARG_").\n", (PointerSizedInt)SIG_ERR ); } } if ( ::signal(SIGPIPE, SIG_IGN) != SIG_IGN) { // broken pipe probably from a failed RTSP session (the server went down?) if ( ::sigaction(SIGPIPE, &act, NULL) != 0 ) { qtss_printf( "- PlaylistBroadcaster: System error (%"_SPOINTERSIZEARG_").\n", (PointerSizedInt)SIG_ERR ); } } if ( ::signal(SIGHUP, SIG_IGN) != SIG_IGN) { // catch any SIGHUP if ( ::sigaction(SIGHUP, &act, NULL) != 0) { qtss_printf( "- PlaylistBroadcaster: System error (%"_SPOINTERSIZEARG_").\n", (PointerSizedInt)SIG_ERR ); } } if ( ::signal(SIGALRM, SIG_IGN) != SIG_IGN) { // catch any SIGALRM if ( ::sigaction(SIGALRM, &act, NULL) != 0) { qtss_printf( "- PlaylistBroadcaster: System error (%"_SPOINTERSIZEARG_").\n", (PointerSizedInt)SIG_ERR ); } } #endif } /* ======================================================================== * Signal and error handler. */ static void SignalEventHandler( int signalID ) { if (gBroadcaster) { #ifdef __Win32__ if ( (signalID != SIGINT) && (signalID != SIGTERM) ) #else if ( (signalID == SIGALRM) || (signalID == SIGHUP) ) // unexpected SIGALRM || SIGHUP { qtss_printf( "- PlaylistBroadcaster: Unexpected signal type (%"_SPOINTERSIZEARG_").\n", signalID ); // just ignore it... return; } if (signalID == SIGPIPE) // broken pipe from server #endif gBroadcaster->Cleanup(true); else // kill or ^C gBroadcaster->Cleanup(false); } ::exit(-1); }