parent
73ba0c72d2
commit
5fbdf2edf6
|
@ -45,3 +45,4 @@ with contributions by:
|
|||
Adrian Knoth <adi@drcomp.erfurt.thur.de>
|
||||
Filipe Roque <flip.roque@gmail.com>
|
||||
Johann Fot <johann.fot@dunkelfuerst.com>
|
||||
Alban Peignier <alban.peignier@gmail.com>
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
next version
|
||||
o Issue #56: Wrong icecast2 password isn't properly reported, fixed.
|
||||
thanks to Filipe Roque <flip.roque@gmail.com>
|
||||
o Issue #57: BufferedSink makes streams invalid, fixed.
|
||||
thanks to Alban Peignier <alban.peignier@gmail.com>
|
||||
|
||||
27-10-2011 Darkice 1.1 released
|
||||
o Updated aac+ encoding to use libaacplus-2.0.0 api.
|
||||
thanks to Sergiy <piratfm@gmail.com>
|
||||
|
|
|
@ -61,8 +61,7 @@ CastSink :: init ( TcpSocket * socket,
|
|||
const char * name,
|
||||
const char * url,
|
||||
const char * genre,
|
||||
bool isPublic,
|
||||
unsigned int bufferDuration )
|
||||
bool isPublic )
|
||||
throw ( Exception )
|
||||
{
|
||||
this->socket = socket;
|
||||
|
@ -73,13 +72,6 @@ CastSink :: init ( TcpSocket * socket,
|
|||
this->url = url ? Util::strDup( url) : 0;
|
||||
this->genre = genre ? Util::strDup( genre) : 0;
|
||||
this->isPublic = isPublic;
|
||||
this->bufferDuration = bufferDuration;
|
||||
|
||||
int bufferSize = bitRate ? (bitRate * 1024 / 8) * bufferDuration
|
||||
: (128 * 1024 / 8) * bufferDuration;
|
||||
|
||||
bufferedSink = socket ? new BufferedSink( socket, bufferSize)
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -118,7 +110,7 @@ CastSink :: open ( void ) throw ( Exception )
|
|||
return false;
|
||||
}
|
||||
|
||||
if ( !bufferedSink->open() ) {
|
||||
if ( !getSink()->open() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,21 +68,11 @@ class CastSink : public Sink, public virtual Reporter
|
|||
*/
|
||||
Ref<TcpSocket> socket;
|
||||
|
||||
/**
|
||||
* The BufferedSink encapsulating the socket connection to the server.
|
||||
*/
|
||||
Ref<BufferedSink> bufferedSink;
|
||||
|
||||
/**
|
||||
* An optional Sink to enable stream dumps.
|
||||
*/
|
||||
Ref<Sink> streamDump;
|
||||
|
||||
/**
|
||||
* Duration of the BufferedSink buffer in seconds.
|
||||
*/
|
||||
unsigned int bufferDuration;
|
||||
|
||||
/**
|
||||
* Password to the server.
|
||||
*/
|
||||
|
@ -123,8 +113,6 @@ class CastSink : public Sink, public virtual Reporter
|
|||
* @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
|
||||
*/
|
||||
void
|
||||
|
@ -135,8 +123,7 @@ class CastSink : public Sink, public virtual Reporter
|
|||
const char * name,
|
||||
const char * url,
|
||||
const char * genre,
|
||||
bool isPublic,
|
||||
unsigned int bufferDuration )
|
||||
bool isPublic)
|
||||
throw ( Exception );
|
||||
|
||||
/**
|
||||
|
@ -178,7 +165,7 @@ class CastSink : public Sink, public virtual Reporter
|
|||
inline Sink *
|
||||
getSink ( void ) const throw ()
|
||||
{
|
||||
return bufferedSink.get();
|
||||
return getSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -206,8 +193,7 @@ class CastSink : public Sink, public virtual Reporter
|
|||
* @param bitRate bitrate of the stream (e.g. mp3 bitrate).
|
||||
* @param isPublic is the stream public?
|
||||
* @param streamDump a Sink to dump the streamed binary data to
|
||||
* @param bufferDuration duration of the BufferedSink buffer
|
||||
* in seconds.
|
||||
*
|
||||
* @exception Exception
|
||||
*/
|
||||
inline
|
||||
|
@ -218,8 +204,7 @@ class CastSink : public Sink, public virtual Reporter
|
|||
const char * url = 0,
|
||||
const char * genre = 0,
|
||||
bool isPublic = false,
|
||||
Sink * streamDump = 0,
|
||||
unsigned int bufferDuration = 10 )
|
||||
Sink * streamDump = 0)
|
||||
throw ( Exception )
|
||||
{
|
||||
init( socket,
|
||||
|
@ -229,8 +214,7 @@ class CastSink : public Sink, public virtual Reporter
|
|||
name,
|
||||
url,
|
||||
genre,
|
||||
isPublic,
|
||||
bufferDuration );
|
||||
isPublic );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,8 +233,7 @@ class CastSink : public Sink, public virtual Reporter
|
|||
cs.name,
|
||||
cs.url,
|
||||
cs.genre,
|
||||
cs.isPublic,
|
||||
cs.bufferDuration );
|
||||
cs.isPublic );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -284,8 +267,7 @@ class CastSink : public Sink, public virtual Reporter
|
|||
cs.name,
|
||||
cs.url,
|
||||
cs.genre,
|
||||
cs.isPublic,
|
||||
cs.bufferDuration );
|
||||
cs.isPublic );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -308,7 +290,7 @@ class CastSink : public Sink, public virtual Reporter
|
|||
inline virtual bool
|
||||
isOpen ( void ) const throw ()
|
||||
{
|
||||
return bufferedSink != NULL ? bufferedSink->isOpen() : false;
|
||||
return getSink()->isOpen();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -455,17 +437,6 @@ class CastSink : public Sink, public virtual Reporter
|
|||
{
|
||||
return isPublic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the duration of the BufferedSink buffer in seconds.
|
||||
*
|
||||
* @return the the duration of the BufferedSink buffer in seconds.
|
||||
*/
|
||||
inline unsigned int
|
||||
getBufferDuration ( void ) const throw ()
|
||||
{
|
||||
return bufferDuration;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -258,6 +258,8 @@ DarkIce :: configIceCast ( const Config & config,
|
|||
FileSink * localDumpFile = 0;
|
||||
bool fileAddDate = false;
|
||||
const char * fileDateFormat = 0;
|
||||
AudioEncoder * encoder = 0;
|
||||
int bufferSize = 0;
|
||||
|
||||
str = cs->get( "sampleRate");
|
||||
sampleRate = str ? Util::strToL( str) : dsp->getSampleRate();
|
||||
|
@ -326,6 +328,9 @@ DarkIce :: configIceCast ( const Config & config,
|
|||
fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false;
|
||||
fileDateFormat = cs->get("fileDateFormat");
|
||||
|
||||
bufferSize = dsp->getBitsPerSample() / 8 * dsp->getSampleRate() * dsp->getChannel() * bufferSecs;
|
||||
reportEvent( 3, "buffer size: ", bufferSize);
|
||||
|
||||
localDumpName = cs->get( "localDumpFile");
|
||||
|
||||
// go on and create the things
|
||||
|
@ -366,8 +371,7 @@ DarkIce :: configIceCast ( const Config & config,
|
|||
genre,
|
||||
isPublic,
|
||||
remoteDumpFile,
|
||||
localDumpFile,
|
||||
bufferSecs );
|
||||
localDumpFile);
|
||||
|
||||
str = cs->getForSure( "format", " missing in section ", stream);
|
||||
|
||||
|
@ -379,29 +383,30 @@ DarkIce :: configIceCast ( const Config & config,
|
|||
|
||||
#ifdef HAVE_LAME_LIB
|
||||
if ( Util::strEq( str, "mp3") ) {
|
||||
audioOuts[u].encoder = new LameLibEncoder( audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
channel,
|
||||
lowpass,
|
||||
highpass );
|
||||
encoder = new LameLibEncoder( audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
channel,
|
||||
lowpass,
|
||||
highpass );
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_TWOLAME_LIB
|
||||
if ( Util::strEq( str, "mp2") ) {
|
||||
audioOuts[u].encoder = new TwoLameLibEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
sampleRate,
|
||||
channel );
|
||||
encoder = new TwoLameLibEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
sampleRate,
|
||||
channel );
|
||||
}
|
||||
#endif
|
||||
|
||||
audioOuts[u].encoder = new BufferedSink(encoder, bufferSize, dsp->getBitsPerSample() / 8);
|
||||
encConnector->attach( audioOuts[u].encoder.get());
|
||||
#endif // HAVE_LAME_LIB || HAVE_TWOLAME_LIB
|
||||
}
|
||||
|
@ -458,6 +463,8 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
FileSink * localDumpFile = 0;
|
||||
bool fileAddDate = false;
|
||||
const char * fileDateFormat = 0;
|
||||
AudioEncoder * encoder = 0;
|
||||
int bufferSize = 0;
|
||||
|
||||
str = cs->getForSure( "format", " missing in section ", stream);
|
||||
if ( Util::strEq( str, "vorbis") ) {
|
||||
|
@ -538,6 +545,9 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false;
|
||||
fileDateFormat = cs->get( "fileDateFormat");
|
||||
|
||||
bufferSize = dsp->getBitsPerSample() / 8 * dsp->getSampleRate() * dsp->getChannel() * bufferSecs;
|
||||
reportEvent( 3, "buffer size: ", bufferSize);
|
||||
|
||||
localDumpName = cs->get( "localDumpFile");
|
||||
|
||||
// go on and create the things
|
||||
|
@ -579,8 +589,7 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
url,
|
||||
genre,
|
||||
isPublic,
|
||||
localDumpFile,
|
||||
bufferSecs );
|
||||
localDumpFile);
|
||||
|
||||
switch ( format ) {
|
||||
case IceCast2::mp3:
|
||||
|
@ -590,16 +599,19 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
"thus can't create mp3 stream: ",
|
||||
stream);
|
||||
#else
|
||||
audioOuts[u].encoder = new LameLibEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
channel,
|
||||
lowpass,
|
||||
highpass );
|
||||
encoder = new LameLibEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
channel,
|
||||
lowpass,
|
||||
highpass );
|
||||
|
||||
audioOuts[u].encoder = new BufferedSink(encoder, bufferSize, dsp->getBitsPerSample() / 8);
|
||||
|
||||
#endif // HAVE_LAME_LIB
|
||||
break;
|
||||
|
||||
|
@ -611,15 +623,18 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
"thus can't Ogg Vorbis stream: ",
|
||||
stream);
|
||||
#else
|
||||
audioOuts[u].encoder = new VorbisLibEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
dsp->getChannel(),
|
||||
maxBitrate);
|
||||
|
||||
encoder = new VorbisLibEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
dsp->getChannel(),
|
||||
maxBitrate);
|
||||
|
||||
audioOuts[u].encoder = new BufferedSink(encoder, bufferSize, dsp->getBitsPerSample() / 8);
|
||||
#endif // HAVE_VORBIS_LIB
|
||||
break;
|
||||
|
||||
|
@ -630,13 +645,15 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
"thus can't create mp2 stream: ",
|
||||
stream);
|
||||
#else
|
||||
audioOuts[u].encoder = new TwoLameLibEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
sampleRate,
|
||||
channel );
|
||||
encoder = new TwoLameLibEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
sampleRate,
|
||||
channel );
|
||||
|
||||
audioOuts[u].encoder = new BufferedSink(encoder, bufferSize, dsp->getBitsPerSample() / 8);
|
||||
#endif // HAVE_TWOLAME_LIB
|
||||
break;
|
||||
|
||||
|
@ -648,14 +665,16 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
"thus can't aac stream: ",
|
||||
stream);
|
||||
#else
|
||||
audioOuts[u].encoder = new FaacEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
dsp->getChannel());
|
||||
encoder = new FaacEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
dsp->getChannel());
|
||||
|
||||
audioOuts[u].encoder = new BufferedSink(encoder, bufferSize, dsp->getBitsPerSample() / 8);
|
||||
#endif // HAVE_FAAC_LIB
|
||||
break;
|
||||
|
||||
|
@ -666,14 +685,16 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
"thus can't aacp stream: ",
|
||||
stream);
|
||||
#else
|
||||
audioOuts[u].encoder = new aacPlusEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
channel );
|
||||
encoder = new aacPlusEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
channel );
|
||||
|
||||
audioOuts[u].encoder = new BufferedSink(encoder, bufferSize, dsp->getBitsPerSample() / 8);
|
||||
#endif // HAVE_AACPLUS_LIB
|
||||
break;
|
||||
|
||||
|
@ -744,6 +765,8 @@ DarkIce :: configShoutCast ( const Config & config,
|
|||
FileSink * localDumpFile = 0;
|
||||
bool fileAddDate = false;
|
||||
const char * fileDateFormat = 0;
|
||||
AudioEncoder * encoder = 0;
|
||||
int bufferSize = 0;
|
||||
|
||||
str = cs->get( "sampleRate");
|
||||
sampleRate = str ? Util::strToL( str) : dsp->getSampleRate();
|
||||
|
@ -809,6 +832,9 @@ DarkIce :: configShoutCast ( const Config & config,
|
|||
fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false;
|
||||
fileDateFormat = cs->get( "fileDateFormat");
|
||||
|
||||
bufferSize = dsp->getBitsPerSample() / 8 * dsp->getSampleRate() * dsp->getChannel() * bufferSecs;
|
||||
reportEvent( 3, "buffer size: ", bufferSize);
|
||||
|
||||
localDumpName = cs->get( "localDumpFile");
|
||||
|
||||
// go on and create the things
|
||||
|
@ -851,18 +877,19 @@ DarkIce :: configShoutCast ( const Config & config,
|
|||
irc,
|
||||
aim,
|
||||
icq,
|
||||
localDumpFile,
|
||||
bufferSecs );
|
||||
localDumpFile);
|
||||
|
||||
audioOuts[u].encoder = new LameLibEncoder( audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
channel,
|
||||
lowpass,
|
||||
highpass );
|
||||
|
||||
encoder = new LameLibEncoder( audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
channel,
|
||||
lowpass,
|
||||
highpass );
|
||||
audioOuts[u].encoder = new BufferedSink(encoder, bufferSize, dsp->getBitsPerSample() / 8);
|
||||
|
||||
encConnector->attach( audioOuts[u].encoder.get());
|
||||
#endif // HAVE_LAME_LIB
|
||||
|
|
|
@ -89,7 +89,7 @@ class DarkIce : public virtual Referable, public virtual Reporter
|
|||
* Type describing each lame library output.
|
||||
*/
|
||||
typedef struct {
|
||||
Ref<AudioEncoder> encoder;
|
||||
Ref<Sink> encoder;
|
||||
Ref<TcpSocket> socket;
|
||||
Ref<CastSink> server;
|
||||
} Output;
|
||||
|
|
|
@ -198,6 +198,11 @@ IceCast :: sendLogin ( void ) throw ( Exception )
|
|||
|
||||
/* read the anticipated response: "OK" */
|
||||
len = source->read( resp, STRBUF_SIZE);
|
||||
|
||||
if ( Util::strEq( resp, "ERROR - Bad Password",20) ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"Icecast - wrong password");
|
||||
}
|
||||
if ( len < 2 || resp[0] != 'O' || resp[1] != 'K' ) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -153,8 +153,7 @@ class IceCast : public CastSink
|
|||
const char * genre = 0,
|
||||
bool isPublic = false,
|
||||
const char * remoteDumpFile = 0,
|
||||
Sink * streamDump = 0,
|
||||
unsigned int bufferDuration = 10 )
|
||||
Sink * streamDump = 0 )
|
||||
throw ( Exception )
|
||||
: CastSink( socket,
|
||||
password,
|
||||
|
@ -163,8 +162,7 @@ class IceCast : public CastSink
|
|||
url,
|
||||
genre,
|
||||
isPublic,
|
||||
streamDump,
|
||||
bufferDuration )
|
||||
streamDump )
|
||||
{
|
||||
init( mountPoint, description, remoteDumpFile);
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ static const char fileid[] = "$Id$";
|
|||
* Expected positive response from server begins like this.
|
||||
*----------------------------------------------------------------------------*/
|
||||
static const char responseOK[] = "HTTP/1.0 200";
|
||||
|
||||
static const char responseWrongPasswd[] = "HTTP/1.0 401";
|
||||
|
||||
/* =============================================== local function prototypes */
|
||||
|
||||
|
@ -246,6 +246,12 @@ IceCast2 :: sendLogin ( void ) throw ( Exception )
|
|||
return false;
|
||||
}
|
||||
resp[lenExpected] = 0;
|
||||
|
||||
if ( Util::strEq( resp, responseWrongPasswd) ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"Icecast2 - wrong password");
|
||||
}
|
||||
|
||||
if ( !Util::strEq( resp, responseOK) ) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -161,8 +161,7 @@ class IceCast2 : public CastSink
|
|||
const char * url = 0,
|
||||
const char * genre = 0,
|
||||
bool isPublic = false,
|
||||
Sink * streamDump = 0,
|
||||
unsigned int bufferDuration = 10 )
|
||||
Sink * streamDump = 0 )
|
||||
throw ( Exception )
|
||||
: CastSink( socket,
|
||||
password,
|
||||
|
@ -171,8 +170,7 @@ class IceCast2 : public CastSink
|
|||
url,
|
||||
genre,
|
||||
isPublic,
|
||||
streamDump,
|
||||
bufferDuration )
|
||||
streamDump )
|
||||
{
|
||||
init( format, mountPoint, description);
|
||||
}
|
||||
|
|
|
@ -182,6 +182,12 @@ ShoutCast :: sendLogin ( void ) throw ( Exception )
|
|||
len = source->read( resp, STRBUF_SIZE);
|
||||
reportEvent(8, "server response length: ", len);
|
||||
reportEvent(8, "server response: ", resp);
|
||||
|
||||
if ( Util::strEq( resp, "invalid password",16) ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"ShoutCast - wrong password");
|
||||
}
|
||||
|
||||
if ( len < 2 || resp[0] != 'O' || resp[1] != 'K' ) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -162,8 +162,7 @@ class ShoutCast : public CastSink
|
|||
const char * irc = 0,
|
||||
const char * aim = 0,
|
||||
const char * icq = 0,
|
||||
Sink * streamDump = 0,
|
||||
unsigned int bufferDuration = 10 )
|
||||
Sink * streamDump = 0 )
|
||||
throw ( Exception )
|
||||
: CastSink( socket,
|
||||
password,
|
||||
|
@ -172,8 +171,7 @@ class ShoutCast : public CastSink
|
|||
url,
|
||||
genre,
|
||||
isPublic,
|
||||
streamDump,
|
||||
bufferDuration )
|
||||
streamDump )
|
||||
{
|
||||
init( irc, aim, icq, mountPoint );
|
||||
}
|
||||
|
|
|
@ -402,7 +402,7 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return getSink()->canWrite(sec, usec);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue