added multiple outputs
added configuration reading added command line processing
This commit is contained in:
parent
7c682a8a12
commit
d9d97e3821
|
@ -73,9 +73,10 @@
|
|||
#include <string>
|
||||
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
|
||||
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
#include "DarkIce.h"
|
||||
|
||||
|
||||
|
@ -107,51 +108,185 @@ static const char fileid[] = "$Id$";
|
|||
|
||||
/* ============================================================= module code */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*----------------------------------------------------------------------------*/
|
||||
DarkIce :: DarkIce ( int argc,
|
||||
char * argv[] ) throw ( Exception )
|
||||
{
|
||||
const char * configFileName = 0;
|
||||
int i;
|
||||
|
||||
while ( (i = getopt( argc, argv, "c:")) != -1 ) {
|
||||
switch ( i ) {
|
||||
case 'c':
|
||||
configFileName = optarg;
|
||||
break;
|
||||
|
||||
default:
|
||||
case ':':
|
||||
case '?':
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"error parsing command line options");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !configFileName ) {
|
||||
throw Exception( __FILE__, __LINE__, "no configuration file specified");
|
||||
}
|
||||
|
||||
cout << "configFileName: " << configFileName << endl;
|
||||
|
||||
ifstream configFile( configFileName);
|
||||
Config config( configFile);
|
||||
|
||||
init( config);
|
||||
|
||||
cout << "no. of outputs: " << noOutputs << endl;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Initialize the object
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
DarkIce :: init ( void ) throw ( Exception )
|
||||
DarkIce :: init ( const Config & config ) throw ( Exception )
|
||||
{
|
||||
/* the pipes */
|
||||
encOutPipe = new PipeSource( "enc.out");
|
||||
encInPipe = new PipeSink( "enc.in");
|
||||
const ConfigSection * cs;
|
||||
const char * str;
|
||||
unsigned int u, v, w;
|
||||
int i;
|
||||
|
||||
// the [general] section
|
||||
if ( !(cs = config.get( "general")) ) {
|
||||
throw Exception( __FILE__, __LINE__, "no section [general] in config");
|
||||
}
|
||||
str = cs->getForSure( "duration", " missing in section [general]");
|
||||
duration = Util::strToL( str);
|
||||
|
||||
|
||||
// the [input] section
|
||||
if ( !(cs = config.get( "input")) ) {
|
||||
throw Exception( __FILE__, __LINE__, "no section [general] in config");
|
||||
}
|
||||
|
||||
if ( !encOutPipe->exists() ) {
|
||||
if ( !encOutPipe->create() ) {
|
||||
throw Exception( __FILE__, __LINE__, "can't create out pipe");
|
||||
}
|
||||
}
|
||||
str = cs->getForSure( "sampleRate", " missing in section [input]");
|
||||
u = Util::strToL( str);
|
||||
|
||||
if ( !encInPipe->exists() ) {
|
||||
if ( !encInPipe->create() ) {
|
||||
throw Exception( __FILE__, __LINE__, "can't create in pipe");
|
||||
}
|
||||
}
|
||||
str = cs->getForSure( "bitsPerSample", " missing in section [input]");
|
||||
v = Util::strToL( str);
|
||||
|
||||
/* encoder related stuff */
|
||||
dsp = new OssDspSource( "/dev/dsp", 22050, 16, 2);
|
||||
encIn = new BufferedSink( encInPipe.get(), 64 * 1024);
|
||||
encConnector = new Connector( dsp.get(), encInPipe.get());
|
||||
encoder = new LameEncoder( "notlame",
|
||||
encInPipe->getFileName(),
|
||||
str = cs->getForSure( "channel", " missing in section [input]");
|
||||
w = Util::strToL( str);
|
||||
|
||||
str = cs->getForSure( "device", " missing in section [input]");
|
||||
|
||||
dsp = new OssDspSource( str, u, v, w);
|
||||
encConnector = new Connector( dsp.get());
|
||||
|
||||
|
||||
// look for lame encoder output streams, sections [lame0], [lame1], etc.
|
||||
char lame[] = "lame ";
|
||||
size_t lameLen = Util::strLen( lame);
|
||||
char * pipeOutExt = ".out";
|
||||
size_t pipeOutExtLen = Util::strLen( pipeOutExt);
|
||||
char * pipeInExt = ".in";
|
||||
size_t pipeInExtLen = Util::strLen( pipeInExt);
|
||||
|
||||
for ( i = 0; i < maxOutput; ++i ) {
|
||||
// ugly hack to change the section name to "lame0", "lame1", etc.
|
||||
lame[lameLen-1] = '0' + i;
|
||||
|
||||
if ( !(cs = config.get( lame)) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
const char * encoder = 0;
|
||||
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;
|
||||
|
||||
encoder = cs->getForSure( "encoder", " missing in section ", lame);
|
||||
str = cs->getForSure( "bitrate", " missing in section ", lame);
|
||||
bitrate = Util::strToL( str);
|
||||
server = cs->getForSure( "server", " missing in section ", lame);
|
||||
str = cs->getForSure( "port", " missing in section ", lame);
|
||||
port = Util::strToL( str);
|
||||
password = cs->getForSure( "password", " missing in section ", lame);
|
||||
mountPoint = cs->getForSure( "mountPoint"," missing in section ",lame);
|
||||
name = cs->getForSure( "name", " missing in section ", lame);
|
||||
description = cs->getForSure("description"," missing in section ",lame);
|
||||
url = cs->getForSure( "url", " missing in section ", lame);
|
||||
genre = cs->getForSure( "genre", " missing in section ", lame);
|
||||
str = cs->getForSure( "public", " missing in section ", lame);
|
||||
isPublic = Util::strEq( str, "yes") ? true : false;
|
||||
|
||||
// generate the pipe names
|
||||
char pipeOutName[lameLen + pipeOutExtLen + 1];
|
||||
char pipeInName[lameLen + pipeInExtLen + 1];
|
||||
|
||||
Util::strCpy( pipeOutName, lame);
|
||||
Util::strCat( pipeOutName, pipeOutExt);
|
||||
Util::strCpy( pipeInName, lame);
|
||||
Util::strCat( pipeInName, pipeInExt);
|
||||
|
||||
// go on and create the things
|
||||
|
||||
// the pipes
|
||||
outputs[i].encOutPipe = new PipeSource( pipeOutName);
|
||||
outputs[i].encInPipe = new PipeSink( pipeInName);
|
||||
|
||||
if ( !outputs[i].encOutPipe->exists() ) {
|
||||
if ( !outputs[i].encOutPipe->create() ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"can't create out pipe ",
|
||||
pipeOutName );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !outputs[i].encInPipe->exists() ) {
|
||||
if ( !outputs[i].encInPipe->create() ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"can't create in pipe",
|
||||
pipeInName );
|
||||
}
|
||||
}
|
||||
|
||||
// encoder related stuff
|
||||
outputs[i].encIn = new BufferedSink( outputs[i].encInPipe.get(),
|
||||
64 * 1024);
|
||||
encConnector->attach( outputs[i].encIn.get());
|
||||
outputs[i].encoder = new LameEncoder( encoder,
|
||||
outputs[i].encInPipe->getFileName(),
|
||||
dsp.get(),
|
||||
encOutPipe->getFileName(),
|
||||
96 );
|
||||
outputs[i].encOutPipe->getFileName(),
|
||||
bitrate );
|
||||
|
||||
|
||||
/* streaming related stuff */
|
||||
socket = new TcpSocket( "susi", 8000);
|
||||
ice = new IceCast( socket.get(),
|
||||
"hackme",
|
||||
"sample",
|
||||
"name",
|
||||
"description",
|
||||
"http://ez.az/",
|
||||
"sajat",
|
||||
128,
|
||||
false );
|
||||
shoutConnector = new Connector( encOutPipe.get(), ice.get());
|
||||
// streaming related stuff
|
||||
outputs[i].socket = new TcpSocket( server, port);
|
||||
outputs[i].ice = new IceCast( outputs[i].socket.get(),
|
||||
password,
|
||||
mountPoint,
|
||||
name,
|
||||
description,
|
||||
url,
|
||||
genre,
|
||||
bitrate,
|
||||
isPublic );
|
||||
outputs[i].shoutConnector = new Connector( outputs[i].encOutPipe.get(),
|
||||
outputs[i].ice.get());
|
||||
}
|
||||
|
||||
noOutputs = i;
|
||||
}
|
||||
|
||||
|
||||
|
@ -162,8 +297,11 @@ bool
|
|||
DarkIce :: encode ( void ) throw ( Exception )
|
||||
{
|
||||
unsigned int len;
|
||||
int i;
|
||||
|
||||
encoder->start();
|
||||
for ( i = 0; i < noOutputs; ++i ) {
|
||||
outputs[i].encoder->start();
|
||||
}
|
||||
|
||||
sleep( 1 );
|
||||
|
||||
|
@ -171,13 +309,21 @@ DarkIce :: encode ( void ) throw ( Exception )
|
|||
throw Exception( __FILE__, __LINE__, "can't open connector");
|
||||
}
|
||||
|
||||
len = encConnector->transfer( 22050 * 2 * 2 * 120, 4096, 1, 0 );
|
||||
len = encConnector->transfer( dsp->getSampleRate() *
|
||||
(dsp->getBitsPerSample() / 8) *
|
||||
dsp->getChannel() *
|
||||
duration,
|
||||
4096,
|
||||
1,
|
||||
0 );
|
||||
|
||||
cout << len << " bytes transfered" << endl;
|
||||
|
||||
encConnector->close();
|
||||
|
||||
encoder->stop();
|
||||
for ( i = 0; i < noOutputs; ++i ) {
|
||||
outputs[i].encoder->stop();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -187,19 +333,29 @@ DarkIce :: encode ( void ) throw ( Exception )
|
|||
* Run the encoder
|
||||
*----------------------------------------------------------------------------*/
|
||||
bool
|
||||
DarkIce :: shout ( void ) throw ( Exception )
|
||||
DarkIce :: shout ( unsigned int ix ) throw ( Exception )
|
||||
{
|
||||
unsigned int len;
|
||||
|
||||
if ( !shoutConnector->open() ) {
|
||||
if ( ix >= noOutputs ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !outputs[ix].shoutConnector->open() ) {
|
||||
throw Exception( __FILE__, __LINE__, "can't open connector");
|
||||
}
|
||||
|
||||
len = shoutConnector->transfer( 128 * 1024 / 8 * 120, 4096, 1, 0 );
|
||||
len = outputs[ix].shoutConnector->transfer (
|
||||
outputs[ix].encoder->getOutBitrate()
|
||||
* (1024 / 8)
|
||||
* duration,
|
||||
4096,
|
||||
1,
|
||||
0 );
|
||||
|
||||
cout << len << " bytes transfered" << endl;
|
||||
|
||||
shoutConnector->close();
|
||||
outputs[ix].shoutConnector->close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -214,32 +370,6 @@ DarkIce :: run ( void ) throw ( Exception )
|
|||
pid_t pid;
|
||||
|
||||
cout << "DarkIce" << endl << endl << flush;
|
||||
/*
|
||||
Config config;
|
||||
const ConfigSection * cs;
|
||||
const char * str;
|
||||
|
||||
config.read( cin);
|
||||
|
||||
cs = config.get( "first");
|
||||
if ( cs ) {
|
||||
str = cs->get( "blahblah");
|
||||
cout << str << endl;
|
||||
str = cs->get( "ejj");
|
||||
cout << str << endl;
|
||||
str = cs->get( "ojj");
|
||||
cout << str << endl;
|
||||
}
|
||||
|
||||
cs = config.get( "second");
|
||||
if ( cs ) {
|
||||
str = cs->get( "blahblah");
|
||||
cout << str << endl;
|
||||
}
|
||||
*/
|
||||
init();
|
||||
|
||||
cout << "init OK" << endl << flush;
|
||||
|
||||
pid = fork();
|
||||
|
||||
|
@ -248,11 +378,14 @@ DarkIce :: run ( void ) throw ( Exception )
|
|||
|
||||
} else if ( pid == 0 ) {
|
||||
// this is the child
|
||||
int i;
|
||||
|
||||
sleep ( 2 );
|
||||
|
||||
cout << "shouting" << endl << flush;
|
||||
shout();
|
||||
for ( i = 0; i < noOutputs; ++i ) {
|
||||
shout( i);
|
||||
}
|
||||
cout << "shouting ends" << endl << flush;
|
||||
|
||||
exit(0);
|
||||
|
@ -280,6 +413,11 @@ DarkIce :: run ( void ) throw ( Exception )
|
|||
$Source$
|
||||
|
||||
$Log$
|
||||
Revision 1.4 2000/11/09 22:09:46 darkeye
|
||||
added multiple outputs
|
||||
added configuration reading
|
||||
added command line processing
|
||||
|
||||
Revision 1.3 2000/11/08 17:29:50 darkeye
|
||||
added configuration file reader
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "PipeSource.h"
|
||||
#include "TcpSocket.h"
|
||||
#include "IceCast.h"
|
||||
#include "Config.h"
|
||||
|
||||
|
||||
/* ================================================================ constants */
|
||||
|
@ -71,20 +72,29 @@ class DarkIce : public virtual Referable
|
|||
{
|
||||
private:
|
||||
|
||||
Ref<OssDspSource> dsp;
|
||||
Ref<PipeSink> encInPipe;
|
||||
Ref<BufferedSink> encIn;
|
||||
Ref<Connector> encConnector;
|
||||
Ref<LameEncoder> encoder;
|
||||
static const unsigned int maxOutput = 8;
|
||||
|
||||
typedef struct {
|
||||
Ref<PipeSink> encInPipe;
|
||||
Ref<BufferedSink> encIn;
|
||||
Ref<LameEncoder> encoder;
|
||||
Ref<PipeSource> encOutPipe;
|
||||
Ref<TcpSocket> socket;
|
||||
Ref<IceCast> ice;
|
||||
Ref<Connector> shoutConnector;
|
||||
} Output;
|
||||
|
||||
Ref<PipeSource> encOutPipe;
|
||||
Ref<TcpSocket> socket;
|
||||
Ref<IceCast> ice;
|
||||
Ref<Connector> shoutConnector;
|
||||
|
||||
unsigned int duration;
|
||||
Ref<OssDspSource> dsp;
|
||||
Ref<Connector> encConnector;
|
||||
|
||||
Output outputs[maxOutput];
|
||||
unsigned int noOutputs;
|
||||
|
||||
|
||||
void
|
||||
init ( void ) throw ( Exception );
|
||||
init ( const Config & config ) throw ( Exception );
|
||||
|
||||
|
||||
bool
|
||||
|
@ -92,7 +102,7 @@ class DarkIce : public virtual Referable
|
|||
|
||||
|
||||
bool
|
||||
shout ( void ) throw ( Exception );
|
||||
shout ( unsigned int ) throw ( Exception );
|
||||
|
||||
|
||||
protected:
|
||||
|
@ -109,11 +119,8 @@ class DarkIce : public virtual Referable
|
|||
}
|
||||
|
||||
|
||||
inline
|
||||
DarkIce ( int argc,
|
||||
char * argv[] ) throw ()
|
||||
{
|
||||
}
|
||||
char * argv[] ) throw ( Exception );
|
||||
|
||||
|
||||
inline virtual
|
||||
|
@ -157,8 +164,13 @@ class DarkIce : public virtual Referable
|
|||
$Source$
|
||||
|
||||
$Log$
|
||||
Revision 1.1 2000/11/05 10:05:50 darkeye
|
||||
Initial revision
|
||||
Revision 1.2 2000/11/09 22:09:46 darkeye
|
||||
added multiple outputs
|
||||
added configuration reading
|
||||
added command line processing
|
||||
|
||||
Revision 1.1.1.1 2000/11/05 10:05:50 darkeye
|
||||
initial version
|
||||
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
|
|
Loading…
Reference in New Issue