diff --git a/darkice/trunk/configure.in b/darkice/trunk/configure.in index a2ed3a8..8e28040 100644 --- a/darkice/trunk/configure.in +++ b/darkice/trunk/configure.in @@ -9,7 +9,7 @@ AC_PROG_INSTALL dnl AC_STDC_HEADERS AC_HAVE_HEADERS(errno.h fcntl.h stdio.h stdlib.h string.h unistd.h limits.h) -AC_HAVE_HEADERS(signal.h time.h sys/time.h sys/types.h) +AC_HAVE_HEADERS(signal.h time.h sys/time.h sys/types.h sys/wait.h) AC_HAVE_HEADERS(netdb.h netinet/in.h sys/ioctl.h sys/socket.h sys/stat.h) AC_HAVE_HEADERS(sched.h) AC_HAVE_HEADERS(sys/soundcard.h sys/audio.h) @@ -25,6 +25,8 @@ AC_SUBST(LINK_STATIC) AC_CHECK_LIB( socket, socket) AC_CHECK_LIB( nsl, gethostbyname) AC_CHECK_LIB( rt, sched_getscheduler) +AC_CHECK_LIB( vorbis, vorbis_info_init) +AC_CHECK_LIB( vorbisenc, vorbis_encode_init) dnl checkin for lame library AC_MSG_CHECKING(lame library) diff --git a/darkice/trunk/src/AudioEncoder.h b/darkice/trunk/src/AudioEncoder.h index 54c0624..0bab8bf 100644 --- a/darkice/trunk/src/AudioEncoder.h +++ b/darkice/trunk/src/AudioEncoder.h @@ -37,6 +37,7 @@ /* ============================================================ include files */ #include "Referable.h" +#include "Sink.h" #include "AudioSource.h" @@ -54,7 +55,7 @@ * @author $Author$ * @version $Revision$ */ -class AudioEncoder : public virtual Referable +class AudioEncoder : public Sink, public virtual Referable { private: @@ -359,6 +360,9 @@ class AudioEncoder : public virtual Referable $Source$ $Log$ + Revision 1.3 2001/09/14 19:31:06 darkeye + added IceCast2 / vorbis support + Revision 1.2 2000/11/12 14:54:50 darkeye added kdoc-style documentation comments diff --git a/darkice/trunk/src/DarkIce.cpp b/darkice/trunk/src/DarkIce.cpp index c39425d..99eb6cc 100644 --- a/darkice/trunk/src/DarkIce.cpp +++ b/darkice/trunk/src/DarkIce.cpp @@ -73,7 +73,10 @@ #include "Util.h" #include "IceCast.h" +#include "IceCast2.h" #include "ShoutCast.h" +#include "LameLibEncoder.h" +#include "VorbisLibEncoder.h" #include "DarkIce.h" @@ -148,7 +151,9 @@ DarkIce :: init ( const Config & config ) throw ( Exception ) channel ); encConnector = new Connector( dsp.get()); + noAudioOuts = 0; configIceCast( config, bufferSecs); + configIceCast2( config, bufferSecs); configShoutCast( config, bufferSecs); } @@ -223,30 +228,116 @@ DarkIce :: configIceCast ( const Config & config, reportEvent( 6, "using buffer size", bs); // streaming related stuff - 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 ); + audioOuts[u].socket = new TcpSocket( server, port); + audioOuts[u].server = new IceCast( audioOuts[u].socket.get(), + password, + mountPoint, + bitrate, + name, + description, + url, + genre, + isPublic, + remoteDumpFile ); - lameLibOuts[u].encoder = new LameLibEncoder(lameLibOuts[u].server.get(), - dsp.get(), - bitrate, - dsp->getSampleRate(), - dsp->getChannel(), - lowpass, - highpass ); + audioOuts[u].encoder = new LameLibEncoder( audioOuts[u].server.get(), + dsp.get(), + bitrate, + dsp->getSampleRate(), + dsp->getChannel(), + lowpass, + highpass ); - encConnector->attach( lameLibOuts[u].encoder.get()); + encConnector->attach( audioOuts[u].encoder.get()); } - noLameLibOuts = u; + noAudioOuts += u; +} + + +/*------------------------------------------------------------------------------ + * Look for the IceCast2 stream outputs in the config file + *----------------------------------------------------------------------------*/ +void +DarkIce :: configIceCast2 ( const Config & config, + unsigned int bufferSecs ) + throw ( Exception ) +{ + // look for IceCast2 encoder output streams, + // sections [icecast2-0], [icecast2-1], ... + char stream[] = "icecast2- "; + 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 * mountPoint = 0; + const char * name = 0; + const char * description = 0; + const char * url = 0; + const char * genre = 0; + bool isPublic = false; + + 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); + mountPoint = cs->getForSure( "mountPoint", + " missing in section ", + stream); + name = cs->get( "name"); + description = cs->get("description"); + url = cs->get( "url"); + genre = cs->get( "genre"); + str = cs->get( "public"); + isPublic = str ? (Util::strEq( str, "yes") ? true : false) : false; + + // 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 + audioOuts[u].socket = new TcpSocket( server, port); + audioOuts[u].server = new IceCast2( audioOuts[u].socket.get(), + password, + mountPoint, + bitrate, + name, + description, + url, + genre, + isPublic ); + + audioOuts[u].encoder = new VorbisLibEncoder( audioOuts[u].server.get(), + dsp.get(), + bitrate, + dsp->getSampleRate(), + dsp->getChannel() ); + + encConnector->attach( audioOuts[u].encoder.get()); + } + + noAudioOuts += u; } @@ -318,30 +409,30 @@ DarkIce :: configShoutCast ( const Config & config, 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 ); + audioOuts[u].socket = new TcpSocket( server, port); + audioOuts[u].server = new ShoutCast( audioOuts[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 ); + audioOuts[u].encoder = new LameLibEncoder( audioOuts[u].server.get(), + dsp.get(), + bitrate, + dsp->getSampleRate(), + dsp->getChannel(), + lowpass, + highpass ); - encConnector->attach( lameLibOuts[u].encoder.get()); + encConnector->attach( audioOuts[u].encoder.get()); } - noLameLibOuts = u; + noAudioOuts += u; } @@ -477,6 +568,9 @@ DarkIce :: run ( void ) throw ( Exception ) $Source$ $Log$ + Revision 1.19 2001/09/14 19:31:06 darkeye + added IceCast2 / vorbis support + Revision 1.18 2001/09/11 15:05:21 darkeye added Solaris support diff --git a/darkice/trunk/src/DarkIce.h b/darkice/trunk/src/DarkIce.h index 67fd753..39c841f 100644 --- a/darkice/trunk/src/DarkIce.h +++ b/darkice/trunk/src/DarkIce.h @@ -55,7 +55,7 @@ #include "AudioSource.h" #include "BufferedSink.h" #include "Connector.h" -#include "LameLibEncoder.h" +#include "AudioEncoder.h" #include "TcpSocket.h" #include "CastSink.h" #include "Config.h" @@ -82,26 +82,26 @@ class DarkIce : public virtual Referable, public virtual Reporter /** * The maximum number of supported outputs. */ - static const unsigned int maxOutput = 8; + static const unsigned int maxOutput = 24; /** * Type describing each lame library output. */ typedef struct { - Ref encoder; + Ref encoder; Ref socket; Ref server; - } LameLibOutput; + } Output; /** - * The lame library outputs. + * The outputs. */ - LameLibOutput lameLibOuts[maxOutput]; + Output audioOuts[maxOutput]; /** * Number of lame library outputs. */ - unsigned int noLameLibOuts; + unsigned int noAudioOuts; /** * Duration of playing, in seconds. @@ -150,6 +150,18 @@ class DarkIce : public virtual Referable, public virtual Reporter configIceCast ( const Config & config, unsigned int bufferSecs ) throw ( Exception ); + /** + * Look for the icecast2 stream outputs from the config file. + * Called from init() + * + * @param config the config Object to read initialization + * information from. + * @exception Exception + */ + void + configIceCast2 ( const Config & config, + unsigned int bufferSecs ) throw ( Exception ); + /** * Look for the shoutcast stream outputs from the config file. * Called from init() @@ -281,6 +293,9 @@ class DarkIce : public virtual Referable, public virtual Reporter $Source$ $Log$ + Revision 1.12 2001/09/14 19:31:06 darkeye + added IceCast2 / vorbis support + Revision 1.11 2001/09/11 15:05:21 darkeye added Solaris support diff --git a/darkice/trunk/src/FileSink.cpp b/darkice/trunk/src/FileSink.cpp deleted file mode 100644 index 638ad28..0000000 --- a/darkice/trunk/src/FileSink.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/*------------------------------------------------------------------------------ - - Copyright (c) 2000 Tyrell Corporation. All rights reserved. - - Tyrell DarkIce - - File : FileSink.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 "configure.h" -#endif - -#ifdef HAVE_UNISTD_H -#include -#else -#error need unistd.h -#endif - -#ifdef HAVE_STDLIB_H -#include -#else -#error need stdlib.h -#endif - -#ifdef HAVE_SYS_TYPES_H -#include -#else -#error need sys/types.h -#endif - -#ifdef HAVE_ERRNO_H -#include -#else -#error need errno.h -#endif - -#ifdef HAVE_SYS_STAT_H -#include -#else -#error need sys/stat.h -#endif - -#ifdef HAVE_FCNTL_H -#include -#else -#error need fcntl.h -#endif - -#ifdef HAVE_SYS_TIME_H -#include -#else -#error need sys/time.h -#endif - -#ifdef HAVE_STRING_H -#include -#else -#error need string.h -#endif - - -#include "Util.h" -#include "Exception.h" -#include "FileSink.h" - - -/* =================================================== local data structures */ - - -/* ================================================ local constants & macros */ - -/*------------------------------------------------------------------------------ - * File identity - *----------------------------------------------------------------------------*/ -static const char fileid[] = "$Id$"; - - -/* =============================================== local function prototypes */ - - -/* ============================================================= module code */ - -/*------------------------------------------------------------------------------ - * Initialize the object - *----------------------------------------------------------------------------*/ -void -FileSink :: init ( const char * name ) throw ( Exception ) -{ - fileName = Util::strDup( name); - fileDescriptor = 0; -} - - -/*------------------------------------------------------------------------------ - * De-initialize the object - *----------------------------------------------------------------------------*/ -void -FileSink :: strip ( void) throw ( Exception ) -{ - if ( isOpen() ) { - close(); - } - - delete[] fileName; -} - - -/*------------------------------------------------------------------------------ - * Copy Constructor - *----------------------------------------------------------------------------*/ -FileSink :: FileSink ( const FileSink & fs ) throw ( Exception ) - : Sink( fs ) -{ - int fd; - - init( fs.fileName); - - if ( (fd = fs.fileDescriptor ? dup( fs.fileDescriptor) : 0) == -1 ) { - strip(); - throw Exception( __FILE__, __LINE__, "dup failure"); - } - - fileDescriptor = fd; -} - - -/*------------------------------------------------------------------------------ - * Assignment operator - *----------------------------------------------------------------------------*/ -FileSink & -FileSink :: operator= ( const FileSink & fs ) throw ( Exception ) -{ - if ( this != &fs ) { - int fd; - - /* first strip */ - strip(); - - - /* then build up */ - Sink::operator=( fs ); - - init( fs.fileName); - - if ( (fd = fs.fileDescriptor ? dup( fs.fileDescriptor) : 0) == -1 ) { - strip(); - throw Exception( __FILE__, __LINE__, "dup failure"); - } - - fileDescriptor = fd; - } - - return *this; -} - - -/*------------------------------------------------------------------------------ - * Check wether a file exists - *----------------------------------------------------------------------------*/ -bool -FileSink :: exists ( void ) const throw () -{ - struct stat st; - - if ( stat( (const char*)fileName, &st) == -1 ) { - return false; - } - - return true; -} - - -/*------------------------------------------------------------------------------ - * Create a file, truncate if already exists - *----------------------------------------------------------------------------*/ -bool -FileSink :: create ( void ) throw ( Exception ) -{ - int fd; - - if ( isOpen() ) { - return false; - } - - if ( (fd = ::creat( fileName, S_IRUSR | S_IWUSR)) == -1 ) { - throw Exception( __FILE__, __LINE__, "creat error", errno); - } - - ::close( fd); - return true; -} - - -/*------------------------------------------------------------------------------ - * Open the file - *----------------------------------------------------------------------------*/ -bool -FileSink :: open ( void ) throw ( Exception ) -{ - if ( isOpen() ) { - return false; - } - - if ( (fileDescriptor = ::open( fileName, O_WRONLY | O_TRUNC, 0)) == -1 ) { - fileDescriptor = 0; - return false; - } - - return true; -} - - -/*------------------------------------------------------------------------------ - * Check wether read() would return anything - *----------------------------------------------------------------------------*/ -bool -FileSink :: canWrite ( unsigned int sec, - unsigned int usec ) throw ( Exception ) -{ - fd_set fdset; - struct timeval tv; - int ret; - - if ( !isOpen() ) { - return false; - } - - FD_ZERO( &fdset); - FD_SET( fileDescriptor, &fdset); - tv.tv_sec = sec; - tv.tv_usec = usec; - - ret = select( fileDescriptor + 1, NULL, &fdset, NULL, &tv); - - if ( ret == -1 ) { - throw Exception( __FILE__, __LINE__, "select error"); - } - - return ret > 0; -} - - -/*------------------------------------------------------------------------------ - * Read from the audio source - *----------------------------------------------------------------------------*/ -unsigned int -FileSink :: write ( const void * buf, - unsigned int len ) throw ( Exception ) -{ - ssize_t ret; - - if ( !isOpen() ) { - return 0; - } - - ret = ::write( fileDescriptor, buf, len); - - if ( ret == -1 ) { - if ( errno == EAGAIN ) { - ret = 0; - } else { - throw Exception( __FILE__, __LINE__, "write error", errno); - } - } - - return ret; -} - - -/*------------------------------------------------------------------------------ - * Close the audio source - *----------------------------------------------------------------------------*/ -void -FileSink :: close ( void ) throw ( Exception ) -{ - if ( !isOpen() ) { - return; - } - - flush(); - ::close( fileDescriptor); - fileDescriptor = 0; -} - - - -/*------------------------------------------------------------------------------ - - $Source$ - - $Log$ - Revision 1.5 2001/09/11 15:05:21 darkeye - added Solaris support - - Revision 1.4 2001/08/26 20:44:30 darkeye - removed external command-line encoder support - replaced it with a shared-object support for lame with the possibility - of static linkage - - Revision 1.3 2000/11/11 12:33:13 darkeye - added kdoc-style documentation - - Revision 1.2 2000/11/05 14:08:27 darkeye - changed builting to an automake / autoconf environment - - Revision 1.1.1.1 2000/11/05 10:05:51 darkeye - initial version - - -------------------------------------------------------------------------------*/ - diff --git a/darkice/trunk/src/IceCast.cpp b/darkice/trunk/src/IceCast.cpp index ea0fd8d..2e6d97b 100644 --- a/darkice/trunk/src/IceCast.cpp +++ b/darkice/trunk/src/IceCast.cpp @@ -135,12 +135,22 @@ IceCast :: sendLogin ( void ) throw ( Exception ) sink->write( str, strlen( str)); str = getMountPoint(); sink->write( str, strlen( str)); - str = "\n"; - sink->write( str, strlen( str)); /* send the x-audiocast headers */ + str = "\nx-audiocast-bitrate: "; + 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 = "\nx-audiocast-public: "; + sink->write( str, strlen( str)); + str = getIsPublic() ? "yes" : "no"; + sink->write( str, strlen( str)); + if ( getName() ) { - str = "x-audiocast-name: "; + str = "\nx-audiocast-name: "; sink->write( str, strlen( str)); str = getName(); sink->write( str, strlen( str)); @@ -167,18 +177,6 @@ IceCast :: sendLogin ( void ) throw ( Exception ) sink->write( str, strlen( str)); } - str = "\nx-audiocast-bitrate: "; - 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 = "\nx-audiocast-public: "; - sink->write( str, strlen( str)); - str = getIsPublic() ? "yes" : "no"; - sink->write( str, strlen( str)); - if ( getRemoteDumpFile() ) { str = "\nx-audiocast-dumpfile: "; sink->write( str, strlen( str)); @@ -213,6 +211,9 @@ IceCast :: sendLogin ( void ) throw ( Exception ) $Source$ $Log$ + Revision 1.8 2001/09/14 19:31:06 darkeye + added IceCast2 / vorbis support + Revision 1.7 2001/09/09 11:27:31 darkeye added support for ShoutCast servers diff --git a/darkice/trunk/src/IceCast2.cpp b/darkice/trunk/src/IceCast2.cpp new file mode 100644 index 0000000..207a0cb --- /dev/null +++ b/darkice/trunk/src/IceCast2.cpp @@ -0,0 +1,197 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : IceCast2.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 "IceCast2.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 +IceCast2 :: init ( const char * mountPoint, + const char * description ) + throw ( Exception ) +{ + this->mountPoint = Util::strDup( mountPoint); + this->description = description ? Util::strDup( description) : 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +IceCast2 :: strip ( void ) throw ( Exception ) +{ + delete[] mountPoint; + if ( description ) { + delete[] description; + } +} + + +/*------------------------------------------------------------------------------ + * Log in to the IceCast2 server + *----------------------------------------------------------------------------*/ +bool +IceCast2 :: sendLogin ( void ) throw ( Exception ) +{ + Sink * sink = getSink(); + Source * source = getSocket(); + const char * str; + char resp[STRBUF_SIZE]; + + if ( !source->isOpen() ) { + return false; + } + if ( !sink->isOpen() ) { + return false; + } + + /* send the request, a string like: + * "SOURCE ICE/1.0" */ + str = "SOURCE /"; + sink->write( str, strlen( str)); + str = getMountPoint(); + sink->write( str, strlen( str)); + str = " ICE/1.0"; + sink->write( str, strlen( str)); + + /* send the ice- headers */ + str = "\nice-password: "; + sink->write( str, strlen(str)); + str = getPassword(); + sink->write( str, strlen(str)); + + str = "\nice-bitrate: "; + 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 = "\nice-public: "; + sink->write( str, strlen( str)); + str = getIsPublic() ? "yes" : "no"; + sink->write( str, strlen( str)); + + if ( getName() ) { + str = "\nice-name: "; + sink->write( str, strlen( str)); + str = getName(); + sink->write( str, strlen( str)); + } + + if ( getDescription() ) { + str = "\nice-description: "; + sink->write( str, strlen( str)); + str = getDescription(); + sink->write( str, strlen( str)); + } + + if ( getUrl() ) { + str = "\nice-url: "; + sink->write( str, strlen( str)); + str = getUrl(); + sink->write( str, strlen( str)); + } + + if ( getGenre() ) { + str = "\nice-genre: "; + sink->write( str, strlen( str)); + str = getGenre(); + sink->write( str, strlen( str)); + } + + str = "\n\n"; + sink->write( str, strlen( str)); + sink->flush(); + + return true; +} + + + +/*------------------------------------------------------------------------------ + + $Source$ + + $Log$ + Revision 1.1 2001/09/14 19:31:06 darkeye + added IceCast2 / vorbis support + + + +------------------------------------------------------------------------------*/ + diff --git a/darkice/trunk/src/IceCast2.h b/darkice/trunk/src/IceCast2.h new file mode 100644 index 0000000..cc9095d --- /dev/null +++ b/darkice/trunk/src/IceCast2.h @@ -0,0 +1,249 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : IceCast2.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 ICE_CAST2_H +#define ICE_CAST2_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 an IceCast2 server with + * ice login + * + * @author $Author$ + * @version $Revision$ + */ +class IceCast2 : public CastSink +{ + private: + + /** + * Mount point of the stream on the server. + */ + char * mountPoint; + + /** + * 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 ) + throw ( Exception ); + + /** + * De-initalize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + IceCast2 ( 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 mountPoint mount point of the stream on the server. + * @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). + * @param isPublic is the stream public? + * @param bufferDuration duration of the BufferedSink buffer + * in seconds. + * @exception Exception + */ + inline + IceCast2 ( 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, + unsigned int bufferDuration = 10 ) + throw ( Exception ) + : CastSink( socket, + password, + bitRate, + name, + url, + genre, + isPublic, + bufferDuration ) + { + init( mountPoint, description); + } + + /** + * Copy constructor. + * + * @param cs the IceCast2 to copy. + */ + inline + IceCast2( const IceCast2 & cs ) throw ( Exception ) + : CastSink( cs ) + { + init( cs.getMountPoint(), + cs.getDescription() ); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~IceCast2( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param cs the IceCast2 to assign this to. + * @return a reference to this IceCast2. + * @exception Exception + */ + inline virtual IceCast2 & + operator= ( const IceCast2 & cs ) throw ( Exception ) + { + if ( this != &cs ) { + strip(); + CastSink::operator=( cs ); + init( cs.getMountPoint(), + cs.getDescription() ); + } + 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 description of the stream. + * + * @return the description of the stream. + */ + inline const char * + getDescription ( void ) const throw () + { + return description; + } + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* ICE_CAST2_H */ + + +/*------------------------------------------------------------------------------ + + $Source$ + + $Log$ + Revision 1.1 2001/09/14 19:31:06 darkeye + added IceCast2 / vorbis support + + + +------------------------------------------------------------------------------*/ + diff --git a/darkice/trunk/src/LameLibEncoder.h b/darkice/trunk/src/LameLibEncoder.h index a5a14cd..b8025ce 100644 --- a/darkice/trunk/src/LameLibEncoder.h +++ b/darkice/trunk/src/LameLibEncoder.h @@ -69,8 +69,7 @@ * @author $Author$ * @version $Revision$ */ -class LameLibEncoder : public AudioEncoder, public virtual Reporter, - public Sink +class LameLibEncoder : public AudioEncoder, public virtual Reporter { private: @@ -463,6 +462,9 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter, $Source$ $Log$ + Revision 1.6 2001/09/14 19:31:06 darkeye + added IceCast2 / vorbis support + Revision 1.5 2001/09/02 09:54:12 darkeye fixed typos in CVS substition keywords diff --git a/darkice/trunk/src/Makefile.am b/darkice/trunk/src/Makefile.am index cb62ba9..83e0b34 100644 --- a/darkice/trunk/src/Makefile.am +++ b/darkice/trunk/src/Makefile.am @@ -17,10 +17,14 @@ darkice_SOURCES = AudioEncoder.h\ Exception.h\ IceCast.cpp\ IceCast.h\ + IceCast2.cpp\ + IceCast2.h\ ShoutCast.cpp\ ShoutCast.h\ LameLibEncoder.cpp\ LameLibEncoder.h\ + VorbisLibEncoder.cpp\ + VorbisLibEncoder.h\ OssDspSource.cpp\ OssDspSource.h\ SolarisDspSource.cpp\ diff --git a/darkice/trunk/src/VorbisLibEncoder.cpp b/darkice/trunk/src/VorbisLibEncoder.cpp new file mode 100644 index 0000000..855cbf0 --- /dev/null +++ b/darkice/trunk/src/VorbisLibEncoder.cpp @@ -0,0 +1,340 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : VorbisLibEncoder.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_STRING_H +#include +#else +#error need string.h +#endif + + +#include "Exception.h" +#include "Util.h" +#include "VorbisLibEncoder.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Open an encoding session + *----------------------------------------------------------------------------*/ +bool +VorbisLibEncoder :: open ( void ) + throw ( Exception ) +{ + int ret; + + if ( isOpen() ) { + close(); + } + + vorbis_info_init( &vorbisInfo); + if ( (ret = vorbis_encode_init( &vorbisInfo, + getInChannel(), + getInSampleRate(), + getOutBitrate(), + getOutBitrate(), + getOutBitrate() )) ) { + throw Exception( __FILE__, __LINE__, "vorbis encode init error", ret); + } + + if ( (ret = vorbis_analysis_init( &vorbisDspState, &vorbisInfo)) ) { + throw Exception( __FILE__, __LINE__, "vorbis analysis init error", ret); + } + + if ( (ret = vorbis_block_init( &vorbisDspState, &vorbisBlock)) ) { + throw Exception( __FILE__, __LINE__, "vorbis block init error", ret); + } + + if ( (ret = ogg_stream_init( &oggStreamState, 0)) ) { + throw Exception( __FILE__, __LINE__, "ogg stream init error", ret); + } + + // open the underlying sink + if ( !sink->open() ) { + throw Exception( __FILE__, __LINE__, + "vorbis lib opening underlying sink error"); + } + + // create an empty vorbis_comment structure + vorbis_comment vorbisComment; + + vorbis_comment_init( &vorbisComment); + + // create the vorbis stream headers and send them to the underlying sink + ogg_packet header; + ogg_packet commentHeader; + ogg_packet codeHeader; + + if ( (ret = vorbis_analysis_headerout( &vorbisDspState, + &vorbisComment, + &header, + &commentHeader, + &codeHeader )) ) { + throw Exception( __FILE__, __LINE__, "vorbis header init error", ret); + } + + vorbis_comment_clear( &vorbisComment ); + + ogg_stream_packetin( &oggStreamState, &header); + ogg_stream_packetin( &oggStreamState, &commentHeader); + ogg_stream_packetin( &oggStreamState, &codeHeader); + + ogg_page oggPage; + while ( ogg_stream_flush( &oggStreamState, &oggPage) ) { + sink->write( oggPage.header, oggPage.header_len); + sink->write( oggPage.body, oggPage.body_len); + } + + encoderOpen = true; + + return true; +} + +/*------------------------------------------------------------------------------ + * Convert an unsigned char buffer holding 8 bit PCM values with channels + * interleaved to two float buffers (one for each channel) + *----------------------------------------------------------------------------*/ +void +VorbisLibEncoder :: conv8 ( unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + float * leftBuffer, + float * rightBuffer, + unsigned int channels ) +{ + if ( channels == 1 ) { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + short int value; + + value = pcmBuffer[i++]; + leftBuffer[j] = ((float) value) / 32768.f; + rightBuffer[j] = leftBuffer[j]; + ++j; + } + } else { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + short int value; + + value = pcmBuffer[i++]; + leftBuffer[j] = ((float) value) / 32768.f; + value = pcmBuffer[i++]; + rightBuffer[j] = ((float) value) / 32768.f; + ++j; + } + } +} + + +/*------------------------------------------------------------------------------ + * Convert an unsigned char buffer holding 16 bit PCM values with channels + * interleaved to two float buffers (one for each channel) + *----------------------------------------------------------------------------*/ +void +VorbisLibEncoder :: conv16 ( unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + float * leftBuffer, + float * rightBuffer, + unsigned int channels ) +{ + if ( channels == 1 ) { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + short int value; + + value = pcmBuffer[i++]; + value += pcmBuffer[i++] << 8; + leftBuffer[j] = ((float) value) / 32768.f; + rightBuffer[j] = leftBuffer[j]; + ++j; + } + } else { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + short int value; + + value = pcmBuffer[i++]; + value += pcmBuffer[i++] << 8; + leftBuffer[j] = ((float) value) / 32768.f; + value = pcmBuffer[i++]; + value += pcmBuffer[i++] << 8; + rightBuffer[j] = ((float) value) / 32768.f; + ++j; + } + } +} + + +/*------------------------------------------------------------------------------ + * Write data to the encoder + *----------------------------------------------------------------------------*/ +unsigned int +VorbisLibEncoder :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + if ( !isOpen() ) { + return 0; + } + + unsigned int bitsPerSample = getInBitsPerSample(); + unsigned int channels = getInChannel(); + + if ( channels != 1 && channels != 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of channels for the encoder", + channels ); + } + + unsigned int sampleSize = (bitsPerSample / 8) * channels; + unsigned char * b = (unsigned char*) buf; + unsigned int processed = len - (len % sampleSize); + unsigned int nSamples = processed / sampleSize; + float ** vorbisBuffer; + + vorbisBuffer = vorbis_analysis_buffer( &vorbisDspState, nSamples); + + if ( bitsPerSample == 8 ) { + conv8( b, processed, vorbisBuffer[0], vorbisBuffer[1], channels); + } else if ( bitsPerSample == 16 ) { + conv16( b, processed, vorbisBuffer[0], vorbisBuffer[1], channels); + } else { + throw Exception( __FILE__, __LINE__, + "unsupported number of bits per sample for the encoder", + bitsPerSample ); + } + + vorbis_analysis_wrote( &vorbisDspState, nSamples); + + while ( 1 == vorbis_analysis_blockout( &vorbisDspState, &vorbisBlock) ) { + ogg_packet oggPacket; + ogg_page oggPage; + + vorbis_analysis( &vorbisBlock, &oggPacket); + ogg_stream_packetin( &oggStreamState, &oggPacket); + + while ( ogg_stream_pageout( &oggStreamState, &oggPage) ) { + int written; + + written = sink->write( oggPage.header, oggPage.header_len); +reportEvent( 5, "written to server ", written, " bytes."); + if ( written < oggPage.header_len ) { + // just let go data that could not be written + reportEvent( 2, + "couldn't write full vorbis header to underlying sink", + oggPage.header_len - written); + } + + written = sink->write( oggPage.body, oggPage.body_len); +reportEvent( 5, "written to server ", written, " bytes."); + if ( written < oggPage.body_len ) { + // just let go data that could not be written + reportEvent( 2, + "couldn't write full vorbis body to underlying sink", + oggPage.body_len - written); + } + } + } + + return processed; +} + + +/*------------------------------------------------------------------------------ + * Flush the data from the encoder + *----------------------------------------------------------------------------*/ +void +VorbisLibEncoder :: flush ( void ) + throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + vorbis_analysis_wrote( &vorbisDspState, 0); + // ??? +} + + +/*------------------------------------------------------------------------------ + * Close the encoding session + *----------------------------------------------------------------------------*/ +void +VorbisLibEncoder :: close ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + flush(); + + ogg_stream_clear( &oggStreamState); + vorbis_block_clear( &vorbisBlock); + vorbis_dsp_clear( &vorbisDspState); + vorbis_info_clear( &vorbisInfo); + + encoderOpen = false; + } +} + + + +/*------------------------------------------------------------------------------ + + $Source$ + + $Log$ + Revision 1.1 2001/09/14 19:31:06 darkeye + added IceCast2 / vorbis support + + + +------------------------------------------------------------------------------*/ + diff --git a/darkice/trunk/src/VorbisLibEncoder.h b/darkice/trunk/src/VorbisLibEncoder.h new file mode 100644 index 0000000..ddb0968 --- /dev/null +++ b/darkice/trunk/src/VorbisLibEncoder.h @@ -0,0 +1,442 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : VorbisLibEncoder.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 VORBIS_LIB_ENCODER_H +#define VORBIS_LIB_ENCODER_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// TODO +#include + + +#include "Ref.h" +#include "Exception.h" +#include "Reporter.h" +#include "AudioEncoder.h" +#include "Sink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A class representing the ogg vorbis encoder linked as a shared object or + * as a static library. + * + * @author $Author$ + * @version $Revision$ + */ +class VorbisLibEncoder : public AudioEncoder, public virtual Reporter +{ + private: + + /** + * Value indicating if the encoding process is going on + */ + bool encoderOpen; + + /** + * Ogg Vorbis library global info + */ + vorbis_info vorbisInfo; + + /** + * Ogg Vorbis library global DSP state + */ + vorbis_dsp_state vorbisDspState; + + /** + * Ogg Vorbis library global block + */ + vorbis_block vorbisBlock; + + /** + * Ogg library global stream state + */ + ogg_stream_state oggStreamState; + + /** + * The Sink to dump mp3 data to + */ + Ref sink; + + /** + * Initialize the object. + * + * @param sink the sink to send mp3 output to + * @exception Exception + */ + inline void + init ( Sink * sink ) throw ( Exception ) + { + this->sink = sink; + + if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 8 ) { + throw Exception( __FILE__, __LINE__, + "specified bits per sample not supported", + getInBitsPerSample() ); + } + + if ( getOutSampleRate() != getInSampleRate() ) { + throw Exception( __FILE__, __LINE__, + "different in and out sample rate not supported"); + } + + if ( getInChannel() != getOutChannel() ) { + throw Exception( __FILE__, __LINE__, + "different in and out channels not supported"); + } + + encoderOpen = false; + } + + /** + * De-initialize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + } + + /** + * Convert a char buffer holding 8 bit PCM values to a short buffer + * + * @param pcmBuffer buffer holding 8 bit PCM audio values, + * channels are interleaved + * @param lenPcmBuffer length of pcmBuffer + * @param leftBuffer put the left channel here (must be big enough) + * @param rightBuffer put the right channel here (if mono, same + * as leftChannel, must be big enough) + * @param channels number of channels (1 = mono, 2 = stereo) + */ + void + conv8 ( unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + float * leftBuffer, + float * rightBuffer, + unsigned int channels ); + + /** + * Convert a char buffer holding 16 bit PCM values to a short buffer + * + * @param pcmBuffer buffer holding 16 bit PCM audio values, + * channels are interleaved + * @param lenPcmBuffer length of pcmBuffer + * @param leftBuffer put the left channel here (must be big enough) + * @param rightBuffer put the right channel here (if mono, same + * as leftChannel, must be big enough) + * @param channels number of channels (1 = mono, 2 = stereo) + */ + void + conv16 ( unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + float * leftBuffer, + float * rightBuffer, + unsigned int channels ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + VorbisLibEncoder ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor. + * + * @param sink the sink to send mp3 output to + * @param inSampleRate sample rate of the input. + * @param inBitsPerSample number of bits per sample of the input. + * @param inChannel number of channels of the input. + * @param outBitrate bit rate of the output (bits/sec). + * @param outSampleRate sample rate of the output. + * If 0, inSampleRate is used. + * @param outChannel number of channels of the output. + * If 0, inChannel is used. + * @exception Exception + */ + inline + VorbisLibEncoder ( Sink * sink, + unsigned int inSampleRate, + unsigned int inBitsPerSample, + unsigned int inChannel, + unsigned int outBitrate, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0 ) + throw ( Exception ) + + : AudioEncoder ( inSampleRate, + inBitsPerSample, + inChannel, + outBitrate, + outSampleRate, + outChannel ) + { + init( sink); + } + + /** + * Constructor. + * + * @param sink the sink to send mp3 output to + * @param as get input sample rate, bits per sample and channels + * from this AudioSource. + * @param outBitrate bit rate of the output (bits/sec). + * @param outSampleRate sample rate of the output. + * If 0, input sample rate is used. + * @param outChannel number of channels of the output. + * If 0, input channel is used. + * @exception Exception + */ + inline + VorbisLibEncoder ( Sink * sink, + const AudioSource * as, + unsigned int outBitrate, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0 ) + throw ( Exception ) + + : AudioEncoder ( as, + outBitrate, + outSampleRate, + outChannel ) + { + init( sink); + } + + /** + * Copy constructor. + * + * @param encoder the VorbisLibEncoder to copy. + */ + inline + VorbisLibEncoder ( const VorbisLibEncoder & encoder ) + throw ( Exception ) + : AudioEncoder( encoder ) + { + if( encoder.isOpen() ) { + throw Exception(__FILE__, __LINE__, "don't copy open encoders"); + } + init( encoder.sink.get()); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~VorbisLibEncoder ( void ) throw ( Exception ) + { + if ( isOpen() ) { + close(); + } + strip(); + } + + /** + * Assignment operator. + * + * @param encoder the VorbisLibEncoder to assign this to. + * @return a reference to this VorbisLibEncoder. + * @exception Exception + */ + inline virtual VorbisLibEncoder & + operator= ( const VorbisLibEncoder & encoder ) throw ( Exception ) + { + if( encoder.isOpen() ) { + throw Exception(__FILE__, __LINE__, "don't copy open encoders"); + } + + if ( this != &encoder ) { + strip(); + AudioEncoder::operator=( encoder); + init( encoder.sink.get()); + } + + return *this; + } + + /** + * Check wether encoding is in progress. + * + * @return true if encoding is in progress, false otherwise. + */ + inline virtual bool + isRunning ( void ) const throw () + { + return isOpen(); + } + + /** + * Start encoding. This function returns as soon as possible, + * with encoding started in the background. + * + * @return true if encoding has started, false otherwise. + * @exception Exception + */ + inline virtual bool + start ( void ) throw ( Exception ) + { + return open(); + } + + /** + * Stop encoding. Stops the encoding running in the background. + * + * @exception Exception + */ + inline virtual void + stop ( void ) throw ( Exception ) + { + return close(); + } + + /** + * Open an encoding session. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the encoding session is open. + * + * @return true if the encoding session is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return encoderOpen; + } + + /** + * Check if the encoder is ready to accept data. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the encoder is ready to accept data, + * false otherwise. + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + if ( !isOpen() ) { + return false; + } + + return true; + } + + /** + * Write data to the encoder. + * Buf is expected to be a sequence of big-endian 16 bit values, + * with left and right channels interleaved. Len is the number of + * bytes, must be a multiple of 4. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Flush all data that was written to the encoder to the underlying + * connection. + * + * @exception Exception + */ + virtual void + flush ( void ) throw ( Exception ); + + /** + * Close the encoding session. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* VORBIS_LIB_ENCODER_H */ + + +/*------------------------------------------------------------------------------ + + $Source$ + + $Log$ + Revision 1.1 2001/09/14 19:31:06 darkeye + added IceCast2 / vorbis support + + + +------------------------------------------------------------------------------*/ +