added initial implementation of file dump cutting, re #3

This commit is contained in:
darkeye 2007-01-14 16:12:32 +00:00
parent cf2d4c85f0
commit ee4ae648d0
28 changed files with 462 additions and 124 deletions

View File

@ -1,12 +1,14 @@
DarkIce next release
o added logging facility - [file-X] targets will cut the saved file
and rename it as needed when darkice recieves the SIGUSR1 signal
o added default configuration file handling - if no configuration file
is specified, /etc/darkice.cfg is used
o fix to enable compiling on 64 bit platforms
thanks to Alexander Vlasov <zulu@galaradio.com> and
is specified, /etc/darkice.cfg is used
o fix to enable compiling on 64 bit platforms
thanks to Alexander Vlasov <zulu@galaradio.com> and
Mariusz Mazur <mmazur@kernel.pl>
o fix to enable file dump feature using ogg vorbis.
thanks to <derrick@csociety.org>
o fix to enable file dump feature using ogg vorbis.
thanks to <derrick@csociety.org>
19-05-2006 DarkIce 0.17.1 released

View File

@ -71,6 +71,11 @@ class AudioEncoder : public Sink, public virtual Referable
private:
/**
* The Sink to dump the encoded data to
*/
Ref<Sink> sink;
/**
* Sample rate of the input.
*/
@ -119,6 +124,7 @@ class AudioEncoder : public Sink, public virtual Referable
/**
* Initialize the object.
*
* @param sink the sink to send encoded 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.
@ -130,7 +136,8 @@ class AudioEncoder : public Sink, public virtual Referable
* @exception Exception
*/
inline void
init ( unsigned int inSampleRate,
init ( Sink * sink,
unsigned int inSampleRate,
unsigned int inBitsPerSample,
unsigned int inChannel,
bool inBigEndian,
@ -140,6 +147,7 @@ class AudioEncoder : public Sink, public virtual Referable
unsigned int outSampleRate,
unsigned int outChannel ) throw ( Exception )
{
this->sink = sink;
this->inSampleRate = inSampleRate;
this->inBitsPerSample = inBitsPerSample;
this->inChannel = inChannel;
@ -182,6 +190,7 @@ class AudioEncoder : public Sink, public virtual Referable
/**
* Constructor.
*
* @param sink the sink to send encoded 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.
@ -196,7 +205,8 @@ class AudioEncoder : public Sink, public virtual Referable
* @exception Exception
*/
inline
AudioEncoder ( unsigned int inSampleRate,
AudioEncoder ( Sink * sink,
unsigned int inSampleRate,
unsigned int inBitsPerSample,
unsigned int inChannel,
bool inBigEndian,
@ -207,7 +217,8 @@ class AudioEncoder : public Sink, public virtual Referable
unsigned int outChannel = 0 )
throw ( Exception )
{
init ( inSampleRate,
init ( sink,
inSampleRate,
inBitsPerSample,
inChannel,
inBigEndian,
@ -221,6 +232,7 @@ class AudioEncoder : public Sink, public virtual Referable
/**
* Constructor.
*
* @param sink the sink to send encoded output to
* @param as get input sample rate, bits per sample and channels
* from this AudioSource.
* @param outBitrateMode the bit rate mode of the output.
@ -233,7 +245,8 @@ class AudioEncoder : public Sink, public virtual Referable
* @exception Exception
*/
inline
AudioEncoder ( const AudioSource * as,
AudioEncoder ( Sink * sink,
const AudioSource * as,
BitrateMode outBitrateMode,
unsigned int outBitrate,
double outQuality,
@ -241,7 +254,8 @@ class AudioEncoder : public Sink, public virtual Referable
unsigned int outChannel = 0 )
throw ( Exception)
{
init( as->getSampleRate(),
init( sink,
as->getSampleRate(),
as->getBitsPerSample(),
as->getChannel(),
as->isBigEndian(),
@ -260,7 +274,8 @@ class AudioEncoder : public Sink, public virtual Referable
inline
AudioEncoder ( const AudioEncoder & encoder ) throw ( Exception )
{
init ( encoder.inSampleRate,
init ( encoder.sink.get(),
encoder.inSampleRate,
encoder.inBitsPerSample,
encoder.inChannel,
encoder.inBigEndian,
@ -284,7 +299,8 @@ class AudioEncoder : public Sink, public virtual Referable
if ( this != &encoder ) {
strip();
init ( encoder.inSampleRate,
init ( encoder.sink.get(),
encoder.inSampleRate,
encoder.inBitsPerSample,
encoder.inChannel,
encoder.inBigEndian,
@ -312,6 +328,17 @@ class AudioEncoder : public Sink, public virtual Referable
strip();
}
/**
* Get the underlying sink, that the encoded content is sent to.
*
* @return the underlying sink
*/
inline virtual Ref<Sink>
getSink(void) throw ()
{
return sink;
}
/**
* Get the number of channels of the input.
*
@ -438,6 +465,20 @@ class AudioEncoder : public Sink, public virtual Referable
*/
virtual void
stop ( void ) throw ( Exception ) = 0;
/**
* Cut what the sink has been doing so far, and start anew.
* This usually means separating the data sent to the sink up
* until now, and start saving a new chunk of data.
*
* Typically this action is delegated to the underlying sink.
*/
inline virtual void
cut ( void ) throw ()
{
sink->cut();
}
};

View File

@ -366,6 +366,18 @@ class BufferedSink : public Sink, public virtual Reporter
write( b, 0);
}
/**
* Cut what the sink has been doing so far, and start anew.
* This usually means separating the data sent to the sink up
* until now, and start saving a new chunk of data.
*/
inline virtual void
cut ( void ) throw ()
{
flush();
sink->cut();
}
/**
* Close the BufferedSink. Closes the underlying Sink.
*

View File

@ -362,6 +362,19 @@ class CastSink : public Sink, public virtual Reporter
return getSink()->flush();
}
/**
* Cut what the sink has been doing so far, and start anew.
* This usually means separating the data sent to the sink up
* until now, and start saving a new chunk of data.
*/
inline virtual void
cut ( void ) throw ()
{
if ( streamDump != 0 ) {
streamDump->cut();
}
}
/**
* Close the CastSink.
*

View File

@ -325,6 +325,22 @@ Connector :: transfer ( unsigned long bytes,
}
/*------------------------------------------------------------------------------
* Signal to each sink to cut what they've done so far, and start anew.
*----------------------------------------------------------------------------*/
void
Connector :: cut ( void ) throw ()
{
unsigned int u;
for ( u = 0; u < numSinks; ++u ) {
if ( sinks[u]->isOpen() ) {
sinks[u]->cut();
}
}
}
/*------------------------------------------------------------------------------
* Close the source and all the sinks if needed
*----------------------------------------------------------------------------*/

View File

@ -234,6 +234,15 @@ class Connector : public virtual Referable, public virtual Reporter
unsigned int sec,
unsigned int usec ) throw ( Exception );
/**
* Signal to each sink we have that they need to cut what they are
* doing, and start again. For FileSinks, this usually means to
* save the archive file recorded so far, and start a new archive
* file.
*/
virtual void
cut ( void ) throw ();
/**
* Close the Connector. The Source and all Sinks are closed.
*

View File

@ -1137,6 +1137,20 @@ DarkIce :: run ( void ) throw ( Exception )
}
/*------------------------------------------------------------------------------
* Tell each sink to cut what they are doing, and start again.
*----------------------------------------------------------------------------*/
void
DarkIce :: cut ( void ) throw ()
{
reportEvent( 5, "cutting");
encConnector->cut();
reportEvent( 5, "cutting ends");
}
/*------------------------------------------------------------------------------
$Source$

View File

@ -296,6 +296,15 @@ class DarkIce : public virtual Referable, public virtual Reporter
virtual int
run ( void ) throw ( Exception );
/**
* Signal to each sink we have that they need to cut what they are
* doing, and start again. For FileSinks, this usually means to
* save the archive file recorded so far, and start a new archive
* file.
*/
virtual void
cut ( void ) throw ();
};

View File

@ -71,7 +71,7 @@ FaacEncoder :: open ( void )
}
// open the underlying sink
if ( !sink->open() ) {
if ( !getSink()->open() ) {
throw Exception( __FILE__, __LINE__,
"faac lib opening underlying sink error");
}
@ -145,7 +145,7 @@ FaacEncoder :: write ( const void * buf,
inSamples,
faacBuf,
maxOutputBytes);
sink->write(faacBuf, outputBytes);
getSink()->write(faacBuf, outputBytes);
processedSamples += inSamples;
}
@ -167,7 +167,7 @@ FaacEncoder :: flush ( void )
return;
}
sink->flush();
getSink()->flush();
}
@ -182,7 +182,7 @@ FaacEncoder :: close ( void ) throw ( Exception )
faacEncClose(encoderHandle);
faacOpen = false;
sink->close();
getSink()->close();
}
}

View File

@ -98,15 +98,9 @@ class FaacEncoder : public AudioEncoder, public virtual Reporter
*/
int lowpass;
/**
* The Sink to dump mp3 data to
*/
Ref<Sink> sink;
/**
* Initialize the object.
*
* @param sink the sink to send mp3 output to
* @param lowpass frequency threshold for the lowpass filter.
* Input above this frequency is cut.
* If 0, faac's default values are used,
@ -114,11 +108,9 @@ class FaacEncoder : public AudioEncoder, public virtual Reporter
* @exception Exception
*/
inline void
init ( Sink * sink,
int lowpass) throw (Exception)
init ( int lowpass) throw (Exception)
{
this->faacOpen = false;
this->sink = sink;
this->lowpass = lowpass;
if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 8 ) {
@ -205,7 +197,8 @@ class FaacEncoder : public AudioEncoder, public virtual Reporter
int lowpass = 0)
throw ( Exception )
: AudioEncoder ( inSampleRate,
: AudioEncoder ( sink,
inSampleRate,
inBitsPerSample,
inChannel,
inBigEndian,
@ -215,7 +208,7 @@ class FaacEncoder : public AudioEncoder, public virtual Reporter
outSampleRate,
outChannel )
{
init( sink, lowpass);
init( lowpass);
}
/**
@ -248,14 +241,15 @@ class FaacEncoder : public AudioEncoder, public virtual Reporter
int lowpass = 0)
throw ( Exception )
: AudioEncoder ( as,
: AudioEncoder ( sink,
as,
outBitrateMode,
outBitrate,
outQuality,
outSampleRate,
outChannel )
{
init( sink, lowpass);
init( lowpass);
}
/**
@ -268,7 +262,7 @@ class FaacEncoder : public AudioEncoder, public virtual Reporter
throw ( Exception )
: AudioEncoder( encoder )
{
init( encoder.sink.get(), encoder.lowpass);
init( encoder.lowpass);
}
@ -299,7 +293,7 @@ class FaacEncoder : public AudioEncoder, public virtual Reporter
if ( this != &encoder ) {
strip();
AudioEncoder::operator=( encoder);
init( encoder.sink.get(), encoder.lowpass);
init( encoder.lowpass);
}
return *this;

View File

@ -238,6 +238,17 @@ class FileCast : public CastSink
return targetFile->flush();
}
/**
* Cut what the sink has been doing so far, and start anew.
* This usually means separating the data sent to the sink up
* until now, and start saving a new chunk of data.
*/
inline virtual void
cut ( void ) throw ()
{
targetFile->cut();
}
/**
* Close the FileCast.
*

View File

@ -81,6 +81,17 @@
#error need string.h
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#else
#error need signal.h
#endif
#include <iostream>
#include <sstream>
#include <fstream>
#include "Util.h"
#include "Exception.h"
@ -242,7 +253,8 @@ FileSink :: canWrite ( unsigned int sec,
unsigned int usec ) throw ( Exception )
{
fd_set fdset;
struct timeval tv;
struct timespec timespec;
sigset_t sigset;
int ret;
if ( !isOpen() ) {
@ -251,10 +263,15 @@ FileSink :: canWrite ( unsigned int sec,
FD_ZERO( &fdset);
FD_SET( fileDescriptor, &fdset);
tv.tv_sec = sec;
tv.tv_usec = usec;
ret = select( fileDescriptor + 1, NULL, &fdset, NULL, &tv);
timespec.tv_sec = sec;
timespec.tv_nsec = usec * 1000L;
// mask out SIGUSR1, as we're expecting that signal for other reasons
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
ret = pselect( fileDescriptor + 1, NULL, &fdset, NULL, &timespec, &sigset);
if ( ret == -1 ) {
throw Exception( __FILE__, __LINE__, "select error");
@ -291,6 +308,58 @@ FileSink :: write ( const void * buf,
}
/*------------------------------------------------------------------------------
* Get the file name to where to move the data saved so far.
* The trick is to read the file name from a file named
* /tmp/darkice.$PID , where $PID is the current process id
*----------------------------------------------------------------------------*/
std::string
FileSink :: getArchiveFileName ( void ) throw ( Exception )
{
pid_t pid = getpid();
std::stringstream metaFileName;
metaFileName << "/tmp/darkice." << pid;
std::ifstream ifs(metaFileName.str().c_str());
if (!ifs.good()) {
throw Exception(__FILE__, __LINE__,
"can't find file ", metaFileName.str().c_str(), 0);
}
std::string archiveFileName;
ifs >> archiveFileName;
ifs.close();
return archiveFileName;
}
/*------------------------------------------------------------------------------
* Cut what we've done so far, and start anew.
*----------------------------------------------------------------------------*/
void
FileSink :: cut ( void ) throw ()
{
flush();
close();
try {
std::string archiveFileName = getArchiveFileName();
if (::rename(fileName, archiveFileName.c_str()) != 0) {
reportEvent(2, "couldn't move file", fileName,
"to", archiveFileName);
}
} catch ( Exception &e ) {
reportEvent(2, "error during archive cut", e);
}
create();
open();
}
/*------------------------------------------------------------------------------
* Close the FileSink
*----------------------------------------------------------------------------*/

View File

@ -80,6 +80,16 @@ class FileSink : public Sink, public virtual Reporter
void
strip ( void ) throw ( Exception );
/**
* Get the file name to where to move the data saved so far.
* Used in cut().
*
* @return the file name where to move the data saved so far.
* @throws Exception on file operation errors
*/
std::string
getArchiveFileName( void ) throw ( Exception );
protected:
@ -227,6 +237,14 @@ class FileSink : public Sink, public virtual Reporter
{
}
/**
* Cut what the sink has been doing so far, and start anew.
* This usually means separating the data sent to the sink up
* until now, and start saving a new chunk of data.
*/
virtual void
cut ( void ) throw ();
/**
* Close the FileSink.
*

View File

@ -69,6 +69,12 @@
#error need string.h
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#else
#error need signal.h
#endif
#include "Exception.h"
#include "Util.h"
@ -197,7 +203,8 @@ FileSource :: canRead ( unsigned int sec,
unsigned int usec ) throw ( Exception )
{
fd_set fdset;
struct timeval tv;
struct timespec timespec;
sigset_t sigset;
int ret;
if ( !isOpen() ) {
@ -206,10 +213,15 @@ FileSource :: canRead ( unsigned int sec,
FD_ZERO( &fdset);
FD_SET( fileDescriptor, &fdset);
tv.tv_sec = sec;
tv.tv_usec = usec;
ret = select( fileDescriptor + 1, &fdset, NULL, NULL, &tv);
timespec.tv_sec = sec;
timespec.tv_nsec = usec * 1000L;
// mask out SIGUSR1, as we're expecting that signal for other reasons
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
ret = pselect( fileDescriptor + 1, &fdset, NULL, NULL, &timespec, &sigset);
if ( ret == -1 ) {
throw Exception( __FILE__, __LINE__, "select error");

View File

@ -71,7 +71,7 @@ LameLibEncoder :: open ( void )
}
// open the underlying sink
if ( !sink->open() ) {
if ( !getSink()->open() ) {
throw Exception( __FILE__, __LINE__,
"lame lib opening underlying sink error");
}
@ -331,7 +331,7 @@ LameLibEncoder :: write ( const void * buf,
return 0;
}
unsigned int written = sink->write( mp3Buf, ret);
unsigned int written = getSink()->write( mp3Buf, ret);
delete[] mp3Buf;
// just let go data that could not be written
if ( written < (unsigned int) ret ) {
@ -362,7 +362,7 @@ LameLibEncoder :: flush ( void )
ret = lame_encode_flush( lameGlobalFlags, mp3Buf, mp3Size );
unsigned int written = sink->write( mp3Buf, ret);
unsigned int written = getSink()->write( mp3Buf, ret);
delete[] mp3Buf;
// just let go data that could not be written
@ -372,7 +372,7 @@ LameLibEncoder :: flush ( void )
ret - written);
}
sink->flush();
getSink()->flush();
}
@ -387,7 +387,7 @@ LameLibEncoder :: close ( void ) throw ( Exception )
lame_close( lameGlobalFlags);
lameGlobalFlags = 0;
sink->close();
getSink()->close();
}
}

View File

@ -78,11 +78,6 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
*/
lame_global_flags * lameGlobalFlags;
/**
* The Sink to dump mp3 data to
*/
Ref<Sink> sink;
/**
* Lowpass filter. Sound frequency in Hz, from where up the
* input is cut.
@ -98,7 +93,6 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
/**
* Initialize the object.
*
* @param sink the sink to send mp3 output to
* @param lowpass frequency threshold for the lowpass filter.
* Input above this frequency is cut.
* If 0, lame's default values are used,
@ -110,12 +104,10 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
* @exception Exception
*/
inline void
init ( Sink * sink,
int lowpass,
init ( int lowpass,
int highpass ) throw ( Exception )
{
this->lameGlobalFlags = NULL;
this->sink = sink;
this->lowpass = lowpass;
this->highpass = highpass;
@ -209,7 +201,8 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
int highpass = 0 )
throw ( Exception )
: AudioEncoder ( inSampleRate,
: AudioEncoder ( sink,
inSampleRate,
inBitsPerSample,
inChannel,
inBigEndian,
@ -219,7 +212,7 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
outSampleRate,
outChannel )
{
init( sink, lowpass, highpass);
init( lowpass, highpass);
}
/**
@ -257,14 +250,15 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
int highpass = 0 )
throw ( Exception )
: AudioEncoder ( as,
: AudioEncoder ( sink,
as,
outBitrateMode,
outBitrate,
outQuality,
outSampleRate,
outChannel )
{
init( sink, lowpass, highpass);
init( lowpass, highpass);
}
/**
@ -277,7 +271,7 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
throw ( Exception )
: AudioEncoder( encoder )
{
init( encoder.sink.get(), encoder.lowpass, encoder.highpass );
init( encoder.lowpass, encoder.highpass );
}
@ -308,7 +302,7 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
if ( this != &encoder ) {
strip();
AudioEncoder::operator=( encoder);
init( encoder.sink.get(), encoder.lowpass, encoder.highpass );
init( encoder.lowpass, encoder.highpass );
}
return *this;

View File

@ -293,6 +293,11 @@ MultiThreadedConnector :: sinkThread( int ixSink )
break;
}
if ( threadData->cut) {
sink->cut();
threadData->cut = false;
}
if ( threadData->accepting ) {
if ( sink->canWrite( 0, 0) ) {
try {
@ -337,6 +342,22 @@ MultiThreadedConnector :: sinkThread( int ixSink )
}
/*------------------------------------------------------------------------------
* Signal to each sink to cut what they've done so far, and start anew.
*----------------------------------------------------------------------------*/
void
MultiThreadedConnector :: cut ( void ) throw ()
{
for ( unsigned int i = 0; i < numSinks; ++i ) {
threads[i].cut = true;
}
// TODO: it might be more appropriate to signal all the threads here
// but, they'll get signaled on new data anyway, and it might be
// enough for them to cut at that time
}
/*------------------------------------------------------------------------------
* Stop the treads
* Close the source and all the sinks if needed

View File

@ -107,6 +107,12 @@ class MultiThreadedConnector : public virtual Connector
*/
bool isDone;
/**
* A flag to show that the sink should be made to cut in the
* next iteration.
*/
bool cut;
/**
* Default constructor.
*/
@ -118,6 +124,7 @@ class MultiThreadedConnector : public virtual Connector
this->thread = 0;
this->accepting = false;
this->isDone = false;
this->cut = false;
}
/**
@ -313,6 +320,15 @@ class MultiThreadedConnector : public virtual Connector
unsigned int sec,
unsigned int usec ) throw ( Exception );
/**
* Signal to each sink we have that they need to cut what they are
* doing, and start again. For FileSinks, this usually means to
* save the archive file recorded so far, and start a new archive
* file.
*/
virtual void
cut ( void ) throw ();
/**
* Close the Connector. The Source and all Sinks are closed.
*
@ -322,7 +338,7 @@ class MultiThreadedConnector : public virtual Connector
close ( void ) throw ( Exception );
/**
* This is the function for each thread.
* This is the worker function for each thread.
* This function has to return fast
*
* @param ixSink the index of the sink this thread works on.

View File

@ -80,6 +80,12 @@
#error need sys/ioctl.h
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#else
#error need signal.h
#endif
#ifdef HAVE_SYS_SOUNDCARD_H
#include <sys/soundcard.h>
#else
@ -230,7 +236,8 @@ OssDspSource :: canRead ( unsigned int sec,
unsigned int usec ) throw ( Exception )
{
fd_set fdset;
struct timeval tv;
struct timespec timespec;
sigset_t sigset;
int ret;
if ( !isOpen() ) {
@ -247,10 +254,15 @@ OssDspSource :: canRead ( unsigned int sec,
FD_ZERO( &fdset);
FD_SET( fileDescriptor, &fdset);
tv.tv_sec = sec;
tv.tv_usec = usec;
ret = select( fileDescriptor + 1, &fdset, NULL, NULL, &tv);
timespec.tv_sec = sec;
timespec.tv_nsec = usec * 1000L;
// mask out SIGUSR1, as we're expecting that signal for other reasons
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
ret = pselect( fileDescriptor + 1, &fdset, NULL, NULL, &timespec, &sigset);
if ( ret == -1 ) {
throw Exception( __FILE__, __LINE__, "select error");

View File

@ -156,6 +156,14 @@ class Sink : public virtual Referable
virtual void
flush ( void ) throw ( Exception ) = 0;
/**
* Cut what the sink has been doing so far, and start anew.
* This usually means separating the data sent to the sink up
* until now, and start saving a new chunk of data.
*/
virtual void
cut ( void ) throw () = 0;
/**
* Close the Sink.
*

View File

@ -80,6 +80,12 @@
#error need sys/ioctl.h
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#else
#error need signal.h
#endif
#if defined( HAVE_SYS_AUDIO_H )
#include <sys/audio.h>
#elif defined( HAVE_SYS_AUDIOIO_H )
@ -202,7 +208,8 @@ SolarisDspSource :: canRead ( unsigned int sec,
unsigned int usec ) throw ( Exception )
{
fd_set fdset;
struct timeval tv;
struct timespec timespec;
sigset_t sigset;
int ret;
if ( !isOpen() ) {
@ -211,10 +218,15 @@ SolarisDspSource :: canRead ( unsigned int sec,
FD_ZERO( &fdset);
FD_SET( fileDescriptor, &fdset);
tv.tv_sec = sec;
tv.tv_usec = usec;
ret = select( fileDescriptor + 1, &fdset, NULL, NULL, &tv);
timespec.tv_sec = sec;
timespec.tv_nsec = usec * 1000L;
// mask out SIGUSR1, as we're expecting that signal for other reasons
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
ret = pselect( fileDescriptor + 1, &fdset, NULL, NULL, &timespec, &sigset);
if ( ret == -1 ) {
throw Exception( __FILE__, __LINE__, "select error");

View File

@ -81,6 +81,12 @@
#error need sys/time.h
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#else
#error need signal.h
#endif
#include "Util.h"
#include "Exception.h"
@ -243,7 +249,8 @@ TcpSocket :: canRead ( unsigned int sec,
unsigned int usec ) throw ( Exception )
{
fd_set fdset;
struct timeval tv;
struct timespec timespec;
sigset_t sigset;
int ret;
if ( !isOpen() ) {
@ -252,10 +259,15 @@ TcpSocket :: canRead ( unsigned int sec,
FD_ZERO( &fdset);
FD_SET( sockfd, &fdset);
tv.tv_sec = sec;
tv.tv_usec = usec;
ret = select( sockfd + 1, &fdset, NULL, NULL, &tv);
timespec.tv_sec = sec;
timespec.tv_nsec = usec * 1000L;
// mask out SIGUSR1, as we're expecting that signal for other reasons
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
ret = pselect( sockfd + 1, &fdset, NULL, NULL, &timespec, &sigset);
if ( ret == -1 ) {
throw Exception( __FILE__, __LINE__, "select error");
@ -305,7 +317,8 @@ TcpSocket :: canWrite ( unsigned int sec,
unsigned int usec ) throw ( Exception )
{
fd_set fdset;
struct timeval tv;
struct timespec timespec;
sigset_t sigset;
int ret;
if ( !isOpen() ) {
@ -314,10 +327,15 @@ TcpSocket :: canWrite ( unsigned int sec,
FD_ZERO( &fdset);
FD_SET( sockfd, &fdset);
tv.tv_sec = sec;
tv.tv_usec = usec;
ret = select( sockfd + 1, NULL, &fdset, NULL, &tv);
timespec.tv_sec = sec;
timespec.tv_nsec = usec * 1000L;
// mask out SIGUSR1, as we're expecting that signal for other reasons
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
ret = pselect( sockfd + 1, NULL, &fdset, NULL, &timespec, &sigset);
if ( ret == -1 ) {
throw Exception( __FILE__, __LINE__, "select error");

View File

@ -258,6 +258,18 @@ class TcpSocket : public Source, public Sink
{
}
/**
* Cut what the sink has been doing so far, and start anew.
* This usually means separating the data sent to the sink up
* until now, and start saving a new chunk of data.
*
* For TcpSocket, this is a no-op.
*/
inline virtual void
cut ( void ) throw ()
{
}
/**
* Close the TcpSocket.
*

View File

@ -65,10 +65,9 @@ static const char fileid[] = "$Id$";
* Initialize the object
*----------------------------------------------------------------------------*/
void
TwoLameLibEncoder :: init ( Sink * sink ) throw ( Exception )
TwoLameLibEncoder :: init ( void ) throw ( Exception )
{
this->twolame_opts = NULL;
this->sink = sink;
if ( getInBitsPerSample() != 16 ) {
throw Exception( __FILE__, __LINE__,
@ -106,7 +105,7 @@ TwoLameLibEncoder :: open ( void )
}
// open the underlying sink
if ( !sink->open() ) {
if ( !getSink()->open() ) {
throw Exception( __FILE__, __LINE__,
"TwoLAME lib opening underlying sink error");
}
@ -239,7 +238,7 @@ TwoLameLibEncoder :: write ( const void * buf,
return 0;
}
unsigned int written = sink->write( mp2Buf, ret);
unsigned int written = getSink()->write( mp2Buf, ret);
delete[] mp2Buf;
// just let go data that could not be written
if ( written < (unsigned int) ret ) {
@ -270,7 +269,7 @@ TwoLameLibEncoder :: flush ( void )
ret = twolame_encode_flush( twolame_opts, mp2Buf, mp2Size );
unsigned int written = sink->write( mp2Buf, ret);
unsigned int written = getSink()->write( mp2Buf, ret);
delete[] mp2Buf;
// just let go data that could not be written
@ -280,7 +279,7 @@ TwoLameLibEncoder :: flush ( void )
ret - written);
}
sink->flush();
getSink()->flush();
}
@ -293,7 +292,7 @@ TwoLameLibEncoder :: close ( void ) throw ( Exception )
if ( isOpen() ) {
flush();
twolame_close( &twolame_opts );
sink->close();
getSink()->close();
}
}

View File

@ -78,11 +78,6 @@ class TwoLameLibEncoder : public AudioEncoder, public virtual Reporter
*/
twolame_options * twolame_opts;
/**
* The Sink to dump mp2 data to
*/
Ref<Sink> sink;
/**
* Initialize the object.
*
@ -90,7 +85,7 @@ class TwoLameLibEncoder : public AudioEncoder, public virtual Reporter
* @exception Exception
*/
void
init ( Sink * sink ) throw ( Exception );
init ( void ) throw ( Exception );
/**
* De-initialize the object.
@ -147,7 +142,8 @@ class TwoLameLibEncoder : public AudioEncoder, public virtual Reporter
unsigned int outChannel = 0 )
throw ( Exception )
: AudioEncoder ( inSampleRate,
: AudioEncoder ( sink,
inSampleRate,
inBitsPerSample,
inChannel,
inBigEndian,
@ -157,7 +153,7 @@ class TwoLameLibEncoder : public AudioEncoder, public virtual Reporter
outSampleRate,
outChannel )
{
init( sink );
init();
}
/**
@ -183,14 +179,15 @@ class TwoLameLibEncoder : public AudioEncoder, public virtual Reporter
unsigned int outChannel = 0 )
throw ( Exception )
: AudioEncoder ( as,
: AudioEncoder ( sink,
as,
outBitrateMode,
outBitrate,
0.0f, // outQuality
outSampleRate,
outChannel )
{
init( sink );
init();
}
/**
@ -203,7 +200,7 @@ class TwoLameLibEncoder : public AudioEncoder, public virtual Reporter
throw ( Exception )
: AudioEncoder( encoder )
{
init( encoder.sink.get() );
init();
}
@ -234,7 +231,7 @@ class TwoLameLibEncoder : public AudioEncoder, public virtual Reporter
if ( this != &encoder ) {
strip();
AudioEncoder::operator=( encoder);
init( encoder.sink.get() );
init();
}
return *this;

View File

@ -62,11 +62,9 @@ static const char fileid[] = "$Id$";
* Initialize the encoder
*----------------------------------------------------------------------------*/
void
VorbisLibEncoder :: init ( CastSink * sink,
unsigned int outMaxBitrate )
VorbisLibEncoder :: init ( unsigned int outMaxBitrate )
throw ( Exception )
{
this->sink = sink;
this->outMaxBitrate = outMaxBitrate;
if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 8 ) {
@ -140,7 +138,7 @@ VorbisLibEncoder :: open ( void )
}
// open the underlying sink
if ( !sink->open() ) {
if ( !getSink()->open() ) {
throw Exception( __FILE__, __LINE__,
"vorbis lib opening underlying sink error");
}
@ -206,11 +204,17 @@ VorbisLibEncoder :: open ( void )
// create an empty vorbis_comment structure
vorbis_comment_init( &vorbisComment);
/* FIXME: removed title metadata when the sink type was changed from
* CastSink to the more generic Sink.
* make sure to add metadata somehow
// Add comment to vorbis headers to show title in players
// stupid cast to (char*) because of stupid vorbis API
if ( sink->getName() ) {
vorbis_comment_add_tag(&vorbisComment, "TITLE", (char*)sink->getName());
if ( getSink()->getName() ) {
vorbis_comment_add_tag(&vorbisComment,
"TITLE",
(char*) getSink()->getName());
}
*/
// create the vorbis stream headers and send them to the underlying sink
ogg_packet header;
@ -231,8 +235,8 @@ VorbisLibEncoder :: open ( void )
ogg_page oggPage;
while ( ogg_stream_flush( &oggStreamState, &oggPage) ) {
sink->write( oggPage.header, oggPage.header_len);
sink->write( oggPage.body, oggPage.body_len);
getSink()->write( oggPage.header, oggPage.header_len);
getSink()->write( oggPage.body, oggPage.body_len);
}
vorbis_comment_clear( &vorbisComment );
@ -346,7 +350,7 @@ VorbisLibEncoder :: flush ( void )
vorbis_analysis_wrote( &vorbisDspState, 0);
vorbisBlocksOut();
sink->flush();
getSink()->flush();
}
@ -370,8 +374,8 @@ VorbisLibEncoder :: vorbisBlocksOut ( void ) throw ( Exception )
while ( ogg_stream_pageout( &oggStreamState, &oggPage) ) {
int written;
written = sink->write( oggPage.header, oggPage.header_len);
written += sink->write( oggPage.body, oggPage.body_len);
written = getSink()->write(oggPage.header, oggPage.header_len);
written += getSink()->write( oggPage.body, oggPage.body_len);
if ( written < oggPage.header_len + oggPage.body_len ) {
// just let go data that could not be written
@ -402,7 +406,7 @@ VorbisLibEncoder :: close ( void ) throw ( Exception )
encoderOpen = false;
sink->close();
getSink()->close();
}
}

View File

@ -104,11 +104,6 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
*/
ogg_stream_state oggStreamState;
/**
* The Sink to dump encoded data to
*/
Ref<CastSink> sink;
/**
* Maximum bitrate of the output in kbits/sec. If 0, don't care.
*/
@ -127,13 +122,11 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
/**
* Initialize the object.
*
* @param sink the sink to send encoded output to
* @param the maximum bit rate
* @exception Exception
*/
void
init ( CastSink * sink,
unsigned int outMaxBitrate ) throw ( Exception );
init ( unsigned int outMaxBitrate ) throw ( Exception );
/**
* De-initialize the object.
@ -204,7 +197,8 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
unsigned int outMaxBitrate = 0 )
throw ( Exception )
: AudioEncoder ( inSampleRate,
: AudioEncoder ( sink,
inSampleRate,
inBitsPerSample,
inChannel,
inBigEndian,
@ -214,7 +208,7 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
outSampleRate,
outChannel )
{
init( sink, outMaxBitrate);
init( outMaxBitrate);
}
/**
@ -245,14 +239,15 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
unsigned int outMaxBitrate = 0 )
throw ( Exception )
: AudioEncoder ( as,
: AudioEncoder ( sink,
as,
outBitrateMode,
outBitrate,
outQuality,
outSampleRate,
outChannel )
{
init( sink, outMaxBitrate);
init( outMaxBitrate);
}
/**
@ -268,7 +263,7 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
if( encoder.isOpen() ) {
throw Exception(__FILE__, __LINE__, "don't copy open encoders");
}
init( encoder.sink.get(), encoder.getOutMaxBitrate() );
init( encoder.getOutMaxBitrate() );
}
/**
@ -302,7 +297,7 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
if ( this != &encoder ) {
strip();
AudioEncoder::operator=( encoder);
init( encoder.sink.get(), encoder.getOutMaxBitrate() );
init( encoder.getOutMaxBitrate() );
}
return *this;

View File

@ -43,6 +43,12 @@
#error needs stdlib.h
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#else
#error needs signal.h
#endif
#include <iostream>
#include <fstream>
@ -54,6 +60,11 @@
/* =================================================== local data structures */
/*------------------------------------------------------------------------------
* The DarkIce object we're running
*----------------------------------------------------------------------------*/
static Ref<DarkIce> darkice;
/* ================================================ local constants & macros */
@ -76,6 +87,12 @@ static const char *DEFAULT_CONFIG_FILE = "/etc/darkice.cfg";
static void
showUsage ( std::ostream & os );
/*------------------------------------------------------------------------------
* Handler for the SIGUSR1 signal
*----------------------------------------------------------------------------*/
static void
sigusr1Handler(int value);
/* ============================================================= module code */
@ -126,9 +143,12 @@ main (
Reporter::setReportVerbosity( verbosity );
Reporter::setReportOutputStream( std::cout );
Config config( configFile);
Ref<DarkIce> di = new DarkIce( config);
res = di->run();
darkice = new DarkIce( config);
signal(SIGUSR1, sigusr1Handler);
res = darkice->run();
} catch ( Exception & e ) {
std::cout << "DarkIce: " << e << std::endl << std::flush;
@ -162,6 +182,16 @@ showUsage ( std::ostream & os )
}
/*------------------------------------------------------------------------------
* Handle the SIGUSR1 signal here
*----------------------------------------------------------------------------*/
static void
sigusr1Handler(int value)
{
darkice->cut();
}
/*------------------------------------------------------------------------------
$Source$