From d8d71099e2366fe69340c7ad4c46a412b92a8754 Mon Sep 17 00:00:00 2001 From: darkeye Date: Sun, 9 Sep 2001 11:27:31 +0000 Subject: [PATCH] added support for ShoutCast servers --- darkice/trunk/src/CastSink.cpp | 16 +- darkice/trunk/src/CastSink.h | 72 +-------- darkice/trunk/src/DarkIce.cpp | 168 ++++++++++++++++---- darkice/trunk/src/DarkIce.h | 23 ++- darkice/trunk/src/IceCast.cpp | 52 +++++-- darkice/trunk/src/IceCast.h | 86 ++++++++++- darkice/trunk/src/Makefile.am | 2 + darkice/trunk/src/ShoutCast.cpp | 224 +++++++++++++++++++++++++++ darkice/trunk/src/ShoutCast.h | 266 ++++++++++++++++++++++++++++++++ 9 files changed, 773 insertions(+), 136 deletions(-) create mode 100644 darkice/trunk/src/ShoutCast.cpp create mode 100644 darkice/trunk/src/ShoutCast.h diff --git a/darkice/trunk/src/CastSink.cpp b/darkice/trunk/src/CastSink.cpp index 123bada..4a916ec 100644 --- a/darkice/trunk/src/CastSink.cpp +++ b/darkice/trunk/src/CastSink.cpp @@ -56,27 +56,21 @@ static const char fileid[] = "$Id$"; void CastSink :: init ( TcpSocket * socket, const char * password, - const char * mountPoint, unsigned int bitRate, const char * name, - const char * description, const char * url, const char * genre, bool isPublic, - const char * remoteDumpFile, unsigned int bufferDuration ) throw ( Exception ) { this->socket = socket; this->password = Util::strDup( password); - this->mountPoint = Util::strDup( mountPoint); this->bitRate = bitRate; this->name = name ? Util::strDup( name) : 0; - this->description = description ? Util::strDup( description) : 0; this->url = url ? Util::strDup( url) : 0; this->genre = genre ? Util::strDup( genre) : 0; this->isPublic = isPublic; - this->remoteDumpFile = remoteDumpFile ? Util::strDup( remoteDumpFile) : 0; this->bufferDuration = bufferDuration; bufferedSink = new BufferedSink( socket, @@ -96,22 +90,15 @@ CastSink :: strip ( void ) throw ( Exception ) } delete[] password; - delete[] mountPoint; if ( name ) { delete[] name; } - if ( description ) { - delete[] description; - } if ( url ) { delete[] url; } if ( genre ) { delete[] genre; } - if ( remoteDumpFile ) { - delete[] remoteDumpFile; - } } @@ -144,6 +131,9 @@ CastSink :: open ( void ) throw ( Exception ) $Source$ $Log$ + Revision 1.5 2001/09/09 11:27:31 darkeye + added support for ShoutCast servers + Revision 1.4 2001/08/29 21:08:30 darkeye made some description options in the darkice config file optional diff --git a/darkice/trunk/src/CastSink.h b/darkice/trunk/src/CastSink.h index d99a5c0..817e3fd 100644 --- a/darkice/trunk/src/CastSink.h +++ b/darkice/trunk/src/CastSink.h @@ -82,26 +82,11 @@ class CastSink : public Sink */ char * password; - /** - * Mount point of the stream on the server. - */ - char * mountPoint; - - /** - * Remote dump file if any. - */ - char * remoteDumpFile; - /** * Name of the stream. */ char * name; - /** - * Description of the stream. - */ - char * description; - /** * URL associated with the stream. */ @@ -127,10 +112,7 @@ class CastSink : public Sink * * @param socket socket connection to the server. * @param password password to the server. - * @param mountPoint mount point of the stream on the server. - * @param remoteDumpFile remote dump file (may be NULL). * @param name name of the stream. - * @param description description of the stream. * @param url URL associated with the stream. * @param genre genre of the stream. * @param bitRate bitrate of the stream (e.g. mp3 bitrate). @@ -142,14 +124,11 @@ class CastSink : public Sink void init ( TcpSocket * socket, const char * password, - const char * mountPoint, unsigned int bitRate, const char * name, - const char * description, const char * url, const char * genre, bool isPublic, - const char * remoteDumpFile, unsigned int bufferDuration ) throw ( Exception ); @@ -214,10 +193,7 @@ class CastSink : public Sink * * @param socket socket connection to the server. * @param password password to the server. - * @param mountPoint mount point of the stream on the server. - * @param remoteDumpFile remote dump file (may be NULL). * @param name name of the stream. - * @param description description of the stream. * @param url URL associated with the stream. * @param genre genre of the stream. * @param bitRate bitrate of the stream (e.g. mp3 bitrate). @@ -229,27 +205,21 @@ class CastSink : public Sink inline CastSink ( TcpSocket * socket, const char * password, - const char * mountPoint, unsigned int bitRate, const char * name = 0, - const char * description = 0, const char * url = 0, const char * genre = 0, bool isPublic = false, - const char * remoteDumpFile = 0, unsigned int bufferDuration = 10 ) throw ( Exception ) { init( socket, password, - mountPoint, bitRate, name, - description, url, genre, isPublic, - remoteDumpFile, bufferDuration ); } @@ -264,14 +234,11 @@ class CastSink : public Sink { init( cs.socket.get(), cs.password, - cs.mountPoint, cs.bitRate, cs.name, - cs.description, cs.url, cs.genre, cs.isPublic, - cs.remoteDumpFile, cs.bufferDuration ); } @@ -301,14 +268,11 @@ class CastSink : public Sink Sink::operator=( cs ); init( cs.socket.get(), cs.password, - cs.mountPoint, cs.bitRate, cs.name, - cs.description, cs.url, cs.genre, cs.isPublic, - cs.remoteDumpFile, cs.bufferDuration ); } return *this; @@ -400,28 +364,6 @@ class CastSink : public Sink return password; } - /** - * Get the mount point of the stream on the server. - * - * @return the mount point of the stream on the server. - */ - inline const char * - getMountPoint ( void ) const throw () - { - return mountPoint; - } - - /** - * Get the remote dump file if any. - * - * @return the remote dump file. May be NULL. - */ - inline const char * - getRemoteDumpFile ( void ) const throw () - { - return remoteDumpFile; - } - /** * Get the name of the stream. * @@ -433,17 +375,6 @@ class CastSink : public Sink return name; } - /** - * Get the description of the stream. - * - * @return the description of the stream. - */ - inline const char * - getDescription ( void ) const throw () - { - return description; - } - /** * Get the URL associated with the stream. * @@ -516,6 +447,9 @@ class CastSink : public Sink $Source$ $Log$ + Revision 1.6 2001/09/09 11:27:31 darkeye + added support for ShoutCast servers + Revision 1.5 2001/08/29 21:08:30 darkeye made some description options in the darkice config file optional diff --git a/darkice/trunk/src/DarkIce.cpp b/darkice/trunk/src/DarkIce.cpp index f823226..0d02f82 100644 --- a/darkice/trunk/src/DarkIce.cpp +++ b/darkice/trunk/src/DarkIce.cpp @@ -72,6 +72,8 @@ #include "Util.h" +#include "IceCast.h" +#include "ShoutCast.h" #include "DarkIce.h" @@ -146,31 +148,33 @@ DarkIce :: init ( const Config & config ) throw ( Exception ) channel ); encConnector = new Connector( dsp.get()); - configLameLib( config, bufferSecs); + configIceCast( config, bufferSecs); + configShoutCast( config, bufferSecs); } /*------------------------------------------------------------------------------ - * Look for the lame library outputs from the config file. + * Look for the IceCast stream outputs in the config file *----------------------------------------------------------------------------*/ void -DarkIce :: configLameLib ( const Config & config, +DarkIce :: configIceCast ( const Config & config, unsigned int bufferSecs ) throw ( Exception ) { - // look for lame encoder output streams, sections [lamelib0], [lamelib1]... - char lame[] = "lame "; - size_t lameLen = Util::strLen( lame); + // look for IceCast encoder output streams, + // sections [icecast-0], [icecast-1], ... + char stream[] = "icecast- "; + size_t streamLen = Util::strLen( stream); unsigned int u; for ( u = 0; u < maxOutput; ++u ) { const ConfigSection * cs; const char * str; - // ugly hack to change the section name to "lame0", "lame1", etc. - lame[lameLen-1] = '0' + u; + // ugly hack to change the section name to "stream0", "stream1", etc. + stream[streamLen-1] = '0' + u; - if ( !(cs = config.get( lame)) ) { + if ( !(cs = config.get( stream)) ) { break; } @@ -188,13 +192,15 @@ DarkIce :: configLameLib ( const Config & config, unsigned int lowpass = 0; unsigned int highpass = 0; - str = cs->getForSure( "bitrate", " missing in section ", lame); + str = cs->getForSure("bitrate", " missing in section ", stream); bitrate = Util::strToL( str); - server = cs->getForSure( "server", " missing in section ", lame); - str = cs->getForSure( "port", " missing in section ", lame); + server = cs->getForSure( "server", " missing in section ", stream); + str = cs->getForSure( "port", " missing in section ", stream); port = Util::strToL( str); - password = cs->getForSure( "password", " missing in section ", lame); - mountPoint = cs->getForSure( "mountPoint"," missing in section ",lame); + password = cs->getForSure("password"," missing in section ",stream); + mountPoint = cs->getForSure( "mountPoint", + " missing in section ", + stream); remoteDumpFile = cs->get( "remoteDumpFile"); name = cs->get( "name"); description = cs->get("description"); @@ -217,25 +223,120 @@ DarkIce :: configLameLib ( const Config & config, reportEvent( 6, "using buffer size", bs); // streaming related stuff - lameLibOuts[u].socket = new TcpSocket( server, port); - lameLibOuts[u].ice = new IceCast( lameLibOuts[u].socket.get(), - password, - mountPoint, - bitrate, - name, - description, - url, - genre, - isPublic, - remoteDumpFile ); + lameLibOuts[u].socket = new TcpSocket( server, port); + lameLibOuts[u].server = new IceCast( lameLibOuts[u].socket.get(), + password, + mountPoint, + bitrate, + name, + description, + url, + genre, + isPublic, + remoteDumpFile ); - lameLibOuts[u].encoder = new LameLibEncoder( lameLibOuts[u].ice.get(), - dsp.get(), - bitrate, - dsp->getSampleRate(), - dsp->getChannel(), - lowpass, - highpass ); + lameLibOuts[u].encoder = new LameLibEncoder(lameLibOuts[u].server.get(), + dsp.get(), + bitrate, + dsp->getSampleRate(), + dsp->getChannel(), + lowpass, + highpass ); + + encConnector->attach( lameLibOuts[u].encoder.get()); + } + + noLameLibOuts = u; +} + + +/*------------------------------------------------------------------------------ + * Look for the ShoutCast stream outputs in the config file + *----------------------------------------------------------------------------*/ +void +DarkIce :: configShoutCast ( const Config & config, + unsigned int bufferSecs ) + throw ( Exception ) +{ + // look for IceCast encoder output streams, + // sections [shoutcast-0], [shoutcast-1], ... + char stream[] = "shoutcast- "; + size_t streamLen = Util::strLen( stream); + unsigned int u; + + for ( u = 0; u < maxOutput; ++u ) { + const ConfigSection * cs; + const char * str; + + // ugly hack to change the section name to "stream0", "stream1", etc. + stream[streamLen-1] = '0' + u; + + if ( !(cs = config.get( stream)) ) { + break; + } + + unsigned int bitrate = 0; + const char * server = 0; + unsigned int port = 0; + const char * password = 0; + const char * name = 0; + const char * url = 0; + const char * genre = 0; + bool isPublic = false; + unsigned int lowpass = 0; + unsigned int highpass = 0; + const char * irc = 0; + const char * aim = 0; + const char * icq = 0; + + str = cs->getForSure("bitrate", " missing in section ", stream); + bitrate = Util::strToL( str); + server = cs->getForSure( "server", " missing in section ", stream); + str = cs->getForSure( "port", " missing in section ", stream); + port = Util::strToL( str); + password = cs->getForSure("password"," missing in section ",stream); + name = cs->get( "name"); + url = cs->get( "url"); + genre = cs->get( "genre"); + str = cs->get( "public"); + isPublic = str ? (Util::strEq( str, "yes") ? true : false) : false; + str = cs->get( "lowpass"); + lowpass = str ? Util::strToL( str) : 0; + str = cs->get( "highpass"); + highpass = str ? Util::strToL( str) : 0; + irc = cs->get( "irc"); + aim = cs->get( "aim"); + icq = cs->get( "icq"); + + // go on and create the things + + // encoder related stuff + unsigned int bs = bufferSecs * + (dsp->getBitsPerSample() / 8) * + dsp->getChannel() * + dsp->getSampleRate(); + reportEvent( 6, "using buffer size", bs); + + // streaming related stuff + lameLibOuts[u].socket = new TcpSocket( server, port); + lameLibOuts[u].server = new ShoutCast( lameLibOuts[u].socket.get(), + password, + bitrate, + name, + url, + genre, + isPublic, + irc, + aim, + icq ); + + lameLibOuts[u].encoder = new LameLibEncoder(lameLibOuts[u].server.get(), + dsp.get(), + bitrate, + dsp->getSampleRate(), + dsp->getChannel(), + lowpass, + highpass ); encConnector->attach( lameLibOuts[u].encoder.get()); } @@ -376,6 +477,9 @@ DarkIce :: run ( void ) throw ( Exception ) $Source$ $Log$ + Revision 1.17 2001/09/09 11:27:31 darkeye + added support for ShoutCast servers + Revision 1.16 2001/09/05 20:11:15 darkeye removed dependency on locally stored SGI STL header files now compiler-supplied C++ library STL header files are used diff --git a/darkice/trunk/src/DarkIce.h b/darkice/trunk/src/DarkIce.h index 54deb58..e095d89 100644 --- a/darkice/trunk/src/DarkIce.h +++ b/darkice/trunk/src/DarkIce.h @@ -57,7 +57,7 @@ #include "Connector.h" #include "LameLibEncoder.h" #include "TcpSocket.h" -#include "IceCast.h" +#include "CastSink.h" #include "Config.h" @@ -90,7 +90,7 @@ class DarkIce : public virtual Referable, public virtual Reporter typedef struct { Ref encoder; Ref socket; - Ref ice; + Ref server; } LameLibOutput; /** @@ -139,7 +139,7 @@ class DarkIce : public virtual Referable, public virtual Reporter init ( const Config & config ) throw ( Exception ); /** - * Look for the lame library outputs from the config file. + * Look for the icecast stream outputs from the config file. * Called from init() * * @param config the config Object to read initialization @@ -147,9 +147,21 @@ class DarkIce : public virtual Referable, public virtual Reporter * @exception Exception */ void - configLameLib ( const Config & config, + configIceCast ( const Config & config, unsigned int bufferSecs ) throw ( Exception ); + /** + * Look for the shoutcast stream outputs from the config file. + * Called from init() + * + * @param config the config Object to read initialization + * information from. + * @exception Exception + */ + void + configShoutCast ( const Config & config, + unsigned int bufferSecs ) throw ( Exception ); + /** * Set POSIX real-time scheduling for the encoding process, * if user permissions enable it. @@ -269,6 +281,9 @@ class DarkIce : public virtual Referable, public virtual Reporter $Source$ $Log$ + Revision 1.10 2001/09/09 11:27:31 darkeye + added support for ShoutCast servers + Revision 1.9 2001/08/30 17:25:56 darkeye renamed configure.h to config.h diff --git a/darkice/trunk/src/IceCast.cpp b/darkice/trunk/src/IceCast.cpp index f2835e7..ea0fd8d 100644 --- a/darkice/trunk/src/IceCast.cpp +++ b/darkice/trunk/src/IceCast.cpp @@ -49,6 +49,7 @@ #include "Exception.h" #include "Source.h" #include "Sink.h" +#include "Util.h" #include "IceCast.h" @@ -77,6 +78,37 @@ static const char fileid[] = "$Id$"; /*------------------------------------------------------------------------------ * Initialize the object *----------------------------------------------------------------------------*/ +void +IceCast :: init ( const char * mountPoint, + const char * description, + const char * remoteDumpFile ) + throw ( Exception ) +{ + this->mountPoint = Util::strDup( mountPoint); + this->description = description ? Util::strDup( description) : 0; + this->remoteDumpFile = remoteDumpFile ? Util::strDup( remoteDumpFile) : 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +IceCast :: strip ( void ) throw ( Exception ) +{ + delete[] mountPoint; + if ( description ) { + delete[] description; + } + if ( remoteDumpFile ) { + delete[] remoteDumpFile; + } +} + + +/*------------------------------------------------------------------------------ + * Log in to the IceCast server + *----------------------------------------------------------------------------*/ bool IceCast :: sendLogin ( void ) throw ( Exception ) { @@ -94,7 +126,7 @@ IceCast :: sendLogin ( void ) throw ( Exception ) } /* send the request, a string like: - * "SOURCE /\n\n" */ + * "SOURCE /\n" */ str = "SOURCE "; sink->write( str, strlen( str)); str = getPassword(); @@ -103,21 +135,8 @@ IceCast :: sendLogin ( void ) throw ( Exception ) sink->write( str, strlen( str)); str = getMountPoint(); sink->write( str, strlen( str)); - str = "\n\n"; + str = "\n"; sink->write( str, strlen( str)); - sink->flush(); - - /* read the anticipated response: "OK" */ - len = source->read( resp, STRBUF_SIZE); - if ( len < 2 || resp[0] != 'O' || resp[1] != 'K' ) { - return false; - } - - /* suck anything that the other side has to say */ - while ( source->canRead( 0, 0) && - (len = source->read( resp, STRBUF_SIZE)) ) { - ; - } /* send the x-audiocast headers */ if ( getName() ) { @@ -194,6 +213,9 @@ IceCast :: sendLogin ( void ) throw ( Exception ) $Source$ $Log$ + Revision 1.7 2001/09/09 11:27:31 darkeye + added support for ShoutCast servers + Revision 1.6 2001/08/30 17:25:56 darkeye renamed configure.h to config.h diff --git a/darkice/trunk/src/IceCast.h b/darkice/trunk/src/IceCast.h index 72c2fae..143b4c7 100644 --- a/darkice/trunk/src/IceCast.h +++ b/darkice/trunk/src/IceCast.h @@ -60,6 +60,43 @@ class IceCast : public CastSink { private: + /** + * Mount point of the stream on the server. + */ + char * mountPoint; + + /** + * Remote dump file if any. + */ + char * remoteDumpFile; + + /** + * Description of the stream. + */ + char * description; + + /** + * Initalize the object. + * + * @param mountPoint mount point of the stream on the server. + * @param remoteDumpFile remote dump file (may be NULL). + * @param description description of the stream. + * @exception Exception + */ + void + init ( const char * mountPoint, + const char * description, + const char * remoteDumpFile ) + throw ( Exception ); + + /** + * De-initalize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + protected: @@ -118,16 +155,14 @@ class IceCast : public CastSink throw ( Exception ) : CastSink( socket, password, - mountPoint, bitRate, name, - description, url, genre, isPublic, - remoteDumpFile, bufferDuration ) { + init( mountPoint, description, remoteDumpFile); } /** @@ -139,6 +174,9 @@ class IceCast : public CastSink IceCast( const IceCast & cs ) throw ( Exception ) : CastSink( cs ) { + init( cs.getMountPoint(), + cs.getDescription(), + cs.getRemoteDumpFile() ); } /** @@ -149,6 +187,7 @@ class IceCast : public CastSink inline virtual ~IceCast( void ) throw ( Exception ) { + strip(); } /** @@ -162,10 +201,48 @@ class IceCast : public CastSink operator= ( const IceCast & cs ) throw ( Exception ) { if ( this != &cs ) { + strip(); CastSink::operator=( cs ); + init( cs.getMountPoint(), + cs.getDescription(), + cs.getRemoteDumpFile() ); } return *this; } + + /** + * Get the mount point of the stream on the server. + * + * @return the mount point of the stream on the server. + */ + inline const char * + getMountPoint ( void ) const throw () + { + return mountPoint; + } + + /** + * Get the remote dump file if any. + * + * @return the remote dump file. May be NULL. + */ + inline const char * + getRemoteDumpFile ( void ) const throw () + { + return remoteDumpFile; + } + + /** + * Get the description of the stream. + * + * @return the description of the stream. + */ + inline const char * + getDescription ( void ) const throw () + { + return description; + } + }; @@ -184,6 +261,9 @@ class IceCast : public CastSink $Source$ $Log$ + Revision 1.6 2001/09/09 11:27:31 darkeye + added support for ShoutCast servers + Revision 1.5 2001/08/29 21:08:30 darkeye made some description options in the darkice config file optional diff --git a/darkice/trunk/src/Makefile.am b/darkice/trunk/src/Makefile.am index 547d89d..453462d 100644 --- a/darkice/trunk/src/Makefile.am +++ b/darkice/trunk/src/Makefile.am @@ -17,6 +17,8 @@ darkice_SOURCES = AudioEncoder.h\ Exception.h\ IceCast.cpp\ IceCast.h\ + ShoutCast.cpp\ + ShoutCast.h\ LameLibEncoder.cpp\ LameLibEncoder.h\ OssDspSource.cpp\ diff --git a/darkice/trunk/src/ShoutCast.cpp b/darkice/trunk/src/ShoutCast.cpp new file mode 100644 index 0000000..8ee6b2f --- /dev/null +++ b/darkice/trunk/src/ShoutCast.cpp @@ -0,0 +1,224 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : ShoutCast.cpp + Version : $Revision$ + Author : $Author$ + Location : $Source$ + + Copyright notice: + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDIO_H +#include +#else +#error need stdio.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + + +#include "Exception.h" +#include "Source.h" +#include "Sink.h" +#include "Util.h" +#include "ShoutCast.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * Size of string conversion buffer + *----------------------------------------------------------------------------*/ +#define STRBUF_SIZE 32 + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +ShoutCast :: init ( const char * irc, + const char * aim, + const char * icq ) + throw ( Exception ) +{ + this->irc = irc ? Util::strDup( irc) : 0; + this->aim = aim ? Util::strDup( aim) : 0; + this->icq = icq ? Util::strDup( icq) : 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +ShoutCast :: strip ( void ) throw ( Exception ) +{ + if ( irc ) { + delete[] irc; + } + if ( aim ) { + delete[] aim; + } + if ( icq ) { + delete[] icq; + } +} + + +/*------------------------------------------------------------------------------ + * Log in to the ShoutCast server using the icy login scheme + *----------------------------------------------------------------------------*/ +bool +ShoutCast :: sendLogin ( void ) throw ( Exception ) +{ + Sink * sink = getSink(); + Source * source = getSocket(); + const char * str; + char resp[STRBUF_SIZE]; + unsigned int len; + + if ( !source->isOpen() ) { + return false; + } + if ( !sink->isOpen() ) { + return false; + } + + /* first line is the password in itself */ + str = getPassword(); + sink->write( str, strlen( str)); + str = "\n"; + sink->write( str, strlen( str)); + sink->flush(); + + /* send the icy headers */ + if ( getName() ) { + str = "icy-name:"; + sink->write( str, strlen( str)); + str = getName(); + sink->write( str, strlen( str)); + } + + if ( getUrl() ) { + str = "\nicy-url:"; + sink->write( str, strlen( str)); + str = getUrl(); + sink->write( str, strlen( str)); + } + + if ( getGenre() ) { + str = "\nicy-genre:"; + sink->write( str, strlen( str)); + str = getGenre(); + sink->write( str, strlen( str)); + } + + if ( getIrc() ) { + str = "\nicy-irc:"; + sink->write( str, strlen( str)); + str = getIrc(); + sink->write( str, strlen( str)); + } + + if ( getAim() ) { + str = "\nicy-aim:"; + sink->write( str, strlen( str)); + str = getAim(); + sink->write( str, strlen( str)); + } + + if ( getIcq() ) { + str = "\nicy-icq:"; + sink->write( str, strlen( str)); + str = getIcq(); + sink->write( str, strlen( str)); + } + + str = "\nicy-br:"; + sink->write( str, strlen( str)); + if ( snprintf( resp, STRBUF_SIZE, "%d", getBitRate()) == -1 ) { + throw Exception( __FILE__, __LINE__, "snprintf overflow"); + } + sink->write( resp, strlen( resp)); + + str = "\nicy-pub:"; + sink->write( str, strlen( str)); + str = getIsPublic() ? "yes" : "no"; + sink->write( str, strlen( str)); + + str = "\n\n"; + sink->write( str, strlen( str)); + sink->flush(); + + /* read the anticipated response: "OK" */ + len = source->read( resp, STRBUF_SIZE); + if ( len < 2 || resp[0] != 'O' || resp[1] != 'K' ) { + return false; + } + + /* suck anything that the other side has to say */ + while ( source->canRead( 0, 0) && + (len = source->read( resp, STRBUF_SIZE)) ) { + ; + } + + return true; +} + + + +/*------------------------------------------------------------------------------ + + $Source$ + + $Log$ + Revision 1.1 2001/09/09 11:27:31 darkeye + added support for ShoutCast servers + + + +------------------------------------------------------------------------------*/ + diff --git a/darkice/trunk/src/ShoutCast.h b/darkice/trunk/src/ShoutCast.h new file mode 100644 index 0000000..ec5dd91 --- /dev/null +++ b/darkice/trunk/src/ShoutCast.h @@ -0,0 +1,266 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : ShoutCast.h + Version : $Revision$ + Author : $Author$ + Location : $Source$ + + Copyright notice: + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef SHOUT_CAST_H +#define SHOUT_CAST_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Sink.h" +#include "TcpSocket.h" +#include "CastSink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Class representing output to a ShoutCast server with + * icy login + * + * @author $Author$ + * @version $Revision$ + */ +class ShoutCast : public CastSink +{ + private: + + /** + * IRC info string for the stream + */ + char * irc; + + /** + * AIM info string for the stream + */ + char * aim; + + /** + * ICQ info string for the stream + */ + char * icq; + + /** + * Initalize the object. + * + * @param irc IRC info string for the stream. + * @param aim AIM info string for the stream. + * @param icq ICQ info string for the stream. + * @exception Exception + */ + void + init ( const char * irc, + const char * aim, + const char * icq ) + throw ( Exception ); + + /** + * De-initalize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + ShoutCast ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Log in to the server using the socket avialable. + * + * @return true if login was successful, false otherwise. + * @exception Exception + */ + virtual bool + sendLogin ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param socket socket connection to the server. + * @param password password to the server. + * @param name name of the stream. + * @param url URL associated with the stream. + * @param genre genre of the stream. + * @param bitRate bitrate of the stream (e.g. mp3 bitrate). + * @param isPublic is the stream public? + * @param irc IRC info string for the stream. + * @param aim AIM info string for the stream. + * @param icq ICQ info string for the stream. + * @param bufferDuration duration of the BufferedSink buffer + * in seconds. + * @exception Exception + */ + inline + ShoutCast ( TcpSocket * socket, + const char * password, + unsigned int bitRate, + const char * name = 0, + const char * url = 0, + const char * genre = 0, + bool isPublic = false, + const char * irc = 0, + const char * aim = 0, + const char * icq = 0, + unsigned int bufferDuration = 10 ) + throw ( Exception ) + : CastSink( socket, + password, + bitRate, + name, + url, + genre, + isPublic, + bufferDuration ) + { + init( irc, aim, icq); + } + + /** + * Copy constructor. + * + * @param cs the ShoutCast to copy. + */ + inline + ShoutCast( const ShoutCast & cs ) throw ( Exception ) + : CastSink( cs ) + { + init( cs.getIrc(), cs.getAim(), cs.getIcq()); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~ShoutCast( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param cs the ShoutCast to assign this to. + * @return a reference to this ShoutCast. + * @exception Exception + */ + inline virtual ShoutCast & + operator= ( const ShoutCast & cs ) throw ( Exception ) + { + if ( this != &cs ) { + strip(); + CastSink::operator=( cs ); + init( cs.getIrc(), cs.getAim(), cs.getIcq()); + } + return *this; + } + + /** + * Get the IRC info string for the stream. + * + * @return the IRC info string for the stream. + */ + inline const char * + getIrc ( void ) const throw () + { + return irc; + } + + /** + * Get the AIM info string for the stream. + * + * @return the AIM info string for the stream. + */ + inline const char * + getAim ( void ) const throw () + { + return aim; + } + + /** + * Get the ICQ info string for the stream. + * + * @return the ICQ info string for the stream. + */ + inline const char * + getIcq ( void ) const throw () + { + return icq; + } + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* SHOUT_CAST_H */ + + +/*------------------------------------------------------------------------------ + + $Source$ + + $Log$ + Revision 1.1 2001/09/09 11:27:31 darkeye + added support for ShoutCast servers + + + +------------------------------------------------------------------------------*/ +