/*------------------------------------------------------------------------------ Copyright (c) 2000 Tyrell Corporation. All rights reserved. Tyrell DarkIce File : DarkIce.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_STDLIB_H #include #else #error need stdlib.h #endif #ifdef HAVE_UNISTD_H #include #else #error need unistd.h #endif #ifdef HAVE_SYS_TYPES_H #include #else #error need sys/types.h #endif #ifdef HAVE_SYS_WAIT_H #include #else #error need sys/wait.h #endif #ifdef HAVE_ERRNO_H #include #else #error need errno.h #endif #ifdef HAVE_SCHED_H #include #else #error need sched.h #endif #include "Util.h" #include "IceCast.h" #include "IceCast2.h" #include "ShoutCast.h" #include "FileCast.h" #include "MultiThreadedConnector.h" #include "DarkIce.h" #ifdef HAVE_LAME_LIB #include "LameLibEncoder.h" #endif #ifdef HAVE_VORBIS_LIB #include "VorbisLibEncoder.h" #endif /* =================================================== local data structures */ /* ================================================ local constants & macros */ /*------------------------------------------------------------------------------ * File identity *----------------------------------------------------------------------------*/ static const char fileid[] = "$Id$"; /*------------------------------------------------------------------------------ * Make sure wait-related stuff is what we expect *----------------------------------------------------------------------------*/ #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif /* =============================================== local function prototypes */ /* ============================================================= module code */ /*------------------------------------------------------------------------------ * Initialize the object *----------------------------------------------------------------------------*/ void DarkIce :: init ( const Config & config ) throw ( Exception ) { unsigned int bufferSecs; const ConfigSection * cs; const char * str; unsigned int sampleRate; unsigned int bitsPerSample; unsigned int channel; const char * device; // 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); str = cs->getForSure( "bufferSecs", " missing in section [general]"); bufferSecs = Util::strToL( str); // the [input] section if ( !(cs = config.get( "input")) ) { throw Exception( __FILE__, __LINE__, "no section [general] in config"); } str = cs->getForSure( "sampleRate", " missing in section [input]"); sampleRate = Util::strToL( str); str = cs->getForSure( "bitsPerSample", " missing in section [input]"); bitsPerSample = Util::strToL( str); str = cs->getForSure( "channel", " missing in section [input]"); channel = Util::strToL( str); device = cs->getForSure( "device", " missing in section [input]"); dsp = AudioSource::createDspSource( device, sampleRate, bitsPerSample, channel ); encConnector = new MultiThreadedConnector( dsp.get()); noAudioOuts = 0; configIceCast( config, bufferSecs); configIceCast2( config, bufferSecs); configShoutCast( config, bufferSecs); configFileCast( config); } /*------------------------------------------------------------------------------ * Look for the IceCast stream outputs in the config file *----------------------------------------------------------------------------*/ void DarkIce :: configIceCast ( const Config & config, unsigned int bufferSecs ) throw ( Exception ) { // look for IceCast encoder output streams, // sections [icecast-0], [icecast-1], ... char stream[] = "icecast- "; size_t streamLen = Util::strLen( stream); unsigned int u; for ( u = noAudioOuts; u < maxOutput; ++u ) { const ConfigSection * cs; // ugly hack to change the section name to "stream0", "stream1", etc. stream[streamLen-1] = '0' + (u - noAudioOuts); if ( !(cs = config.get( stream)) ) { break; } #ifndef HAVE_LAME_LIB throw Exception( __FILE__, __LINE__, "DarkIce not compiled with lame support, " "thus can't connect to IceCast 1.x, stream: ", stream); #else const char * str; unsigned int sampleRate = 0; unsigned int channel = 0; AudioEncoder::BitrateMode bitrateMode; unsigned int bitrate = 0; double quality = 0.0; const char * server = 0; unsigned int port = 0; const char * password = 0; const char * mountPoint = 0; const char * remoteDumpFile = 0; const char * name = 0; const char * description = 0; const char * url = 0; const char * genre = 0; bool isPublic = false; int lowpass = 0; int highpass = 0; const char * localDumpName = 0; FileSink * localDumpFile = 0; bool fileAddDate = false; str = cs->get( "sampleRate"); sampleRate = str ? Util::strToL( str) : dsp->getSampleRate(); str = cs->get( "channel"); channel = str ? Util::strToL( str) : dsp->getChannel(); str = cs->get( "bitrate"); bitrate = str ? Util::strToL( str) : 0; str = cs->get( "quality"); quality = str ? Util::strToD( str) : 0.0; str = cs->getForSure( "bitrateMode", " not specified in section ", stream); if ( Util::strEq( str, "cbr") ) { bitrateMode = AudioEncoder::cbr; if ( bitrate == 0 ) { throw Exception( __FILE__, __LINE__, "bitrate not specified for CBR encoding"); } if ( quality == 0 ) { throw Exception( __FILE__, __LINE__, "quality not specified for CBR encoding"); } } else if ( Util::strEq( str, "abr") ) { bitrateMode = AudioEncoder::abr; if ( bitrate == 0 ) { throw Exception( __FILE__, __LINE__, "bitrate not specified for ABR encoding"); } } else if ( Util::strEq( str, "vbr") ) { bitrateMode = AudioEncoder::vbr; if ( quality == 0 ) { throw Exception( __FILE__, __LINE__, "quality not specified for VBR encoding"); } } else { throw Exception( __FILE__, __LINE__, "invalid bitrate mode: ", 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); remoteDumpFile = cs->get( "remoteDumpFile"); 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; str = cs->get( "lowpass"); lowpass = str ? Util::strToL( str) : 0; str = cs->get( "highpass"); highpass = str ? Util::strToL( str) : 0; str = cs->get("fileAddDate"); fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false; localDumpName = cs->get( "localDumpFile"); // go on and create the things // check for and create the local dump file if needed if ( localDumpName != 0 ) { if ( fileAddDate ) { localDumpName = Util::fileAddDate(localDumpName); } localDumpFile = new FileSink( localDumpName); if ( !localDumpFile->exists() ) { if ( !localDumpFile->create() ) { reportEvent( 1, "can't create local dump file", localDumpName); localDumpFile = 0; } } if ( fileAddDate ) { delete[] localDumpFile; } } // streaming related stuff 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, localDumpFile, bufferSecs ); audioOuts[u].encoder = new LameLibEncoder( audioOuts[u].server.get(), dsp.get(), bitrateMode, bitrate, quality, sampleRate, channel, lowpass, highpass ); encConnector->attach( audioOuts[u].encoder.get()); #endif // HAVE_LAME_LIB } 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 = noAudioOuts; u < maxOutput; ++u ) { const ConfigSection * cs; // ugly hack to change the section name to "stream0", "stream1", etc. stream[streamLen-1] = '0' + (u - noAudioOuts); if ( !(cs = config.get( stream)) ) { break; } const char * str; IceCast2::StreamFormat format; unsigned int sampleRate = 0; unsigned int channel = 0; AudioEncoder::BitrateMode bitrateMode; unsigned int bitrate = 0; unsigned int maxBitrate = 0; double quality = 0.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; const char * localDumpName = 0; FileSink * localDumpFile = 0; bool fileAddDate = false; str = cs->getForSure( "format", " missing in section ", stream); if ( Util::strEq( str, "vorbis") ) { format = IceCast2::oggVorbis; } else if ( Util::strEq( str, "mp3") ) { format = IceCast2::mp3; } else { throw Exception( __FILE__, __LINE__, "unsupported stream format: ", str); } str = cs->get( "sampleRate"); sampleRate = str ? Util::strToL( str) : dsp->getSampleRate(); str = cs->get( "channel"); channel = str ? Util::strToL( str) : dsp->getChannel(); // determine fixed bitrate or variable bitrate quality str = cs->get( "bitrate"); bitrate = str ? Util::strToL( str) : 0; str = cs->get( "maxBitrate"); maxBitrate = str ? Util::strToL( str) : 0; str = cs->get( "quality"); quality = str ? Util::strToD( str) : 0.0; str = cs->getForSure( "bitrateMode", " not specified in section ", stream); if ( Util::strEq( str, "cbr") ) { bitrateMode = AudioEncoder::cbr; if ( bitrate == 0 ) { throw Exception( __FILE__, __LINE__, "bitrate not specified for CBR encoding"); } } else if ( Util::strEq( str, "abr") ) { bitrateMode = AudioEncoder::abr; if ( bitrate == 0 ) { throw Exception( __FILE__, __LINE__, "bitrate not specified for ABR encoding"); } } else if ( Util::strEq( str, "vbr") ) { bitrateMode = AudioEncoder::vbr; if ( quality == 0 ) { throw Exception( __FILE__, __LINE__, "quality not specified for VBR encoding"); } } else { throw Exception( __FILE__, __LINE__, "invalid bitrate mode: ", 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; str = cs->get( "fileAddDate"); fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false; localDumpName = cs->get( "localDumpFile"); // go on and create the things // check for and create the local dump file if needed if ( localDumpName != 0 ) { if ( fileAddDate ) { localDumpName = Util::fileAddDate(localDumpName); } localDumpFile = new FileSink( localDumpName); if ( !localDumpFile->exists() ) { if ( !localDumpFile->create() ) { reportEvent( 1, "can't create local dump file", localDumpName); localDumpFile = 0; } } if ( fileAddDate ) { delete[] localDumpName; } } // streaming related stuff audioOuts[u].socket = new TcpSocket( server, port); audioOuts[u].server = new IceCast2( audioOuts[u].socket.get(), password, mountPoint, format, bitrate, name, description, url, genre, isPublic, localDumpFile, bufferSecs ); switch ( format ) { case IceCast2::mp3: #ifndef HAVE_LAME_LIB throw Exception( __FILE__, __LINE__, "DarkIce not compiled with lame support, " "thus can't create mp3 stream: ", stream); #else audioOuts[u].encoder = new LameLibEncoder( audioOuts[u].server.get(), dsp.get(), bitrateMode, bitrate, quality, sampleRate, channel ); #endif // HAVE_LAME_LIB break; case IceCast2::oggVorbis: #ifndef HAVE_VORBIS_LIB throw Exception( __FILE__, __LINE__, "DarkIce not compiled with Ogg Vorbis support, " "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); #endif // HAVE_VORBIS_LIB break; default: throw Exception( __FILE__, __LINE__, "Illegal stream format: ", format); } encConnector->attach( audioOuts[u].encoder.get()); } noAudioOuts += u; } /*------------------------------------------------------------------------------ * Look for the ShoutCast stream outputs in the config file *----------------------------------------------------------------------------*/ void DarkIce :: configShoutCast ( const Config & config, unsigned int bufferSecs ) throw ( Exception ) { // look for Shoutcast encoder output streams, // sections [shoutcast-0], [shoutcast-1], ... char stream[] = "shoutcast- "; size_t streamLen = Util::strLen( stream); unsigned int u; for ( u = noAudioOuts; u < maxOutput; ++u ) { const ConfigSection * cs; // ugly hack to change the section name to "stream0", "stream1", etc. stream[streamLen-1] = '0' + (u - noAudioOuts); if ( !(cs = config.get( stream)) ) { break; } #ifndef HAVE_LAME_LIB throw Exception( __FILE__, __LINE__, "DarkIce not compiled with lame support, " "thus can't connect to ShoutCast, stream: ", stream); #else const char * str; unsigned int sampleRate = 0; unsigned int channel = 0; AudioEncoder::BitrateMode bitrateMode; unsigned int bitrate = 0; double quality = 0.0; const char * server = 0; unsigned int port = 0; const char * password = 0; const char * name = 0; const char * url = 0; const char * genre = 0; bool isPublic = false; int lowpass = 0; int highpass = 0; const char * irc = 0; const char * aim = 0; const char * icq = 0; const char * localDumpName = 0; FileSink * localDumpFile = 0; bool fileAddDate = false; str = cs->get( "sampleRate"); sampleRate = str ? Util::strToL( str) : dsp->getSampleRate(); str = cs->get( "channel"); channel = str ? Util::strToL( str) : dsp->getChannel(); str = cs->get( "bitrate"); bitrate = str ? Util::strToL( str) : 0; str = cs->get( "quality"); quality = str ? Util::strToD( str) : 0.0; str = cs->getForSure( "bitrateMode", " not specified in section ", stream); if ( Util::strEq( str, "cbr") ) { bitrateMode = AudioEncoder::cbr; if ( bitrate == 0 ) { throw Exception( __FILE__, __LINE__, "bitrate not specified for CBR encoding"); } if ( quality == 0 ) { throw Exception( __FILE__, __LINE__, "quality not specified for CBR encoding"); } } else if ( Util::strEq( str, "abr") ) { bitrateMode = AudioEncoder::abr; if ( bitrate == 0 ) { throw Exception( __FILE__, __LINE__, "bitrate not specified for ABR encoding"); } } else if ( Util::strEq( str, "vbr") ) { bitrateMode = AudioEncoder::vbr; if ( quality == 0 ) { throw Exception( __FILE__, __LINE__, "quality not specified for VBR encoding"); } } else { throw Exception( __FILE__, __LINE__, "invalid bitrate mode: ", str); } server = cs->getForSure( "server", " missing in section ", stream); str = cs->getForSure( "port", " missing in section ", stream); port = Util::strToL( str); password = cs->getForSure("password"," missing in section ",stream); name = cs->get( "name"); url = cs->get( "url"); genre = cs->get( "genre"); str = cs->get( "public"); isPublic = str ? (Util::strEq( str, "yes") ? true : false) : false; str = cs->get( "lowpass"); lowpass = str ? Util::strToL( str) : 0; str = cs->get( "highpass"); highpass = str ? Util::strToL( str) : 0; irc = cs->get( "irc"); aim = cs->get( "aim"); icq = cs->get( "icq"); str = cs->get("fileAddDate"); fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false; localDumpName = cs->get( "localDumpFile"); // go on and create the things // check for and create the local dump file if needed if ( localDumpName != 0 ) { if ( fileAddDate ) { localDumpName = Util::fileAddDate(localDumpName); } localDumpFile = new FileSink( localDumpName); if ( !localDumpFile->exists() ) { if ( !localDumpFile->create() ) { reportEvent( 1, "can't create local dump file", localDumpName); localDumpFile = 0; } } if ( fileAddDate ) { delete[] localDumpFile; } } // streaming related stuff 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, localDumpFile, bufferSecs ); audioOuts[u].encoder = new LameLibEncoder( audioOuts[u].server.get(), dsp.get(), bitrateMode, bitrate, quality, sampleRate, channel, lowpass, highpass ); encConnector->attach( audioOuts[u].encoder.get()); #endif // HAVE_LAME_LIB } noAudioOuts += u; } /*------------------------------------------------------------------------------ * Look for the FileCast stream outputs in the config file *----------------------------------------------------------------------------*/ void DarkIce :: configFileCast ( const Config & config ) throw ( Exception ) { // look for FileCast encoder output streams, // sections [file-0], [file-1], ... char stream[] = "file- "; size_t streamLen = Util::strLen( stream); unsigned int u; for ( u = noAudioOuts; u < maxOutput; ++u ) { const ConfigSection * cs; // ugly hack to change the section name to "stream0", "stream1", etc. stream[streamLen-1] = '0' + (u - noAudioOuts); if ( !(cs = config.get( stream)) ) { break; } const char * str; const char * format = 0; AudioEncoder::BitrateMode bitrateMode; unsigned int bitrate = 0; double quality = 0.0; const char * targetFileName = 0; unsigned int sampleRate = 0; int lowpass = 0; int highpass = 0; format = cs->getForSure( "format", " missing in section ", stream); if ( !Util::strEq( format, "vorbis") && !Util::strEq( format, "mp3") ) { throw Exception( __FILE__, __LINE__, "unsupported stream format: ", format); } str = cs->getForSure("bitrate", " missing in section ", stream); bitrate = Util::strToL( str); targetFileName = cs->getForSure( "fileName", " missing in section ", stream); str = cs->get( "sampleRate"); sampleRate = str ? Util::strToL( str) : dsp->getSampleRate(); str = cs->get( "bitrate"); bitrate = str ? Util::strToL( str) : 0; str = cs->get( "quality"); quality = str ? Util::strToD( str) : 0.0; str = cs->getForSure( "bitrateMode", " not specified in section ", stream); if ( Util::strEq( str, "cbr") ) { bitrateMode = AudioEncoder::cbr; if ( bitrate == 0 ) { throw Exception( __FILE__, __LINE__, "bitrate not specified for CBR encoding"); } if ( quality == 0 ) { throw Exception( __FILE__, __LINE__, "quality not specified for CBR encoding"); } } else if ( Util::strEq( str, "abr") ) { bitrateMode = AudioEncoder::abr; if ( bitrate == 0 ) { throw Exception( __FILE__, __LINE__, "bitrate not specified for ABR encoding"); } } else if ( Util::strEq( str, "vbr") ) { bitrateMode = AudioEncoder::vbr; if ( quality == 0 ) { throw Exception( __FILE__, __LINE__, "quality not specified for VBR encoding"); } } else { throw Exception( __FILE__, __LINE__, "invalid bitrate mode: ", str); } str = cs->get( "lowpass"); lowpass = str ? Util::strToL( str) : 0; str = cs->get( "highpass"); highpass = str ? Util::strToL( str) : 0; // go on and create the things // the underlying file FileSink * targetFile = new FileSink( targetFileName); if ( !targetFile->exists() ) { if ( !targetFile->create() ) { throw Exception( __FILE__, __LINE__, "can't create output file", targetFileName); } } // streaming related stuff audioOuts[u].socket = 0; audioOuts[u].server = new FileCast( targetFile ); if ( Util::strEq( format, "mp3") ) { #ifndef HAVE_LAME_LIB throw Exception( __FILE__, __LINE__, "DarkIce not compiled with lame support, " "thus can't create mp3 stream: ", stream); #else audioOuts[u].encoder = new LameLibEncoder( audioOuts[u].server.get(), dsp.get(), bitrateMode, bitrate, quality, sampleRate, dsp->getChannel(), lowpass, highpass ); #endif // HAVE_LAME_LIB } else if ( Util::strEq( format, "vorbis") ) { #ifndef HAVE_VORBIS_LIB throw Exception( __FILE__, __LINE__, "DarkIce not compiled with Ogg Vorbis support, " "thus can't Ogg Vorbis stream: ", stream); #else audioOuts[u].encoder = new VorbisLibEncoder( audioOuts[u].server.get(), dsp.get(), bitrateMode, bitrate, quality, dsp->getSampleRate(), dsp->getChannel() ); #endif // HAVE_VORBIS_LIB } else { throw Exception( __FILE__, __LINE__, "Illegal stream format: ", format); } encConnector->attach( audioOuts[u].encoder.get()); } noAudioOuts += u; } /*------------------------------------------------------------------------------ * Set POSIX real-time scheduling, if super-user *----------------------------------------------------------------------------*/ void DarkIce :: setRealTimeScheduling ( void ) throw ( Exception ) { // don't include the following on OpenBSD / NetBSD, as the scheduling // functions are not implemented. #if !defined( __OpenBSD__ ) && !defined( __NetBSD__ ) uid_t euid; euid = geteuid(); if ( euid == 0 ) { int high_priority; struct sched_param param; /* store the old scheduling parameters */ if ( (origSchedPolicy = sched_getscheduler(0)) == -1 ) { throw Exception( __FILE__, __LINE__, "sched_getscheduler", errno); } if ( sched_getparam( 0, ¶m) == -1 ) { throw Exception( __FILE__, __LINE__, "sched_getparam", errno); } origSchedPriority = param.sched_priority; /* set SCHED_FIFO with max - 1 priority */ if ( (high_priority = sched_get_priority_max(SCHED_FIFO)) == -1 ) { throw Exception(__FILE__,__LINE__,"sched_get_priority_max",errno); } reportEvent( 8, "scheduler high priority", high_priority); param.sched_priority = high_priority - 1; if ( sched_setscheduler( 0, SCHED_FIFO, ¶m) == -1 ) { throw Exception( __FILE__, __LINE__, "sched_setscheduler", errno); } /* ask the new priortiy and report it */ if ( sched_getparam( 0, ¶m) == -1 ) { throw Exception( __FILE__, __LINE__, "sched_getparam", errno); } reportEvent( 1, "Using POSIX real-time scheduling, priority", param.sched_priority ); } else { reportEvent( 1, "Not running as super-user, unable to use POSIX real-time scheduling" ); reportEvent( 1, "It is recommended that you run this program as super-user"); } #else reportEvent( 1, "POSIX scheduling not supported on OpenBSD / NetBSD, " "this may cause recording skips"); #endif // !__OpenBSD__ && !__NetBSD__ } /*------------------------------------------------------------------------------ * Set the original scheduling of the process, the one prior to the * setRealTimeScheduling call. * WARNING: make sure you don't call this before setRealTimeScheduling!! *----------------------------------------------------------------------------*/ void DarkIce :: setOriginalScheduling ( void ) throw ( Exception ) { // don't include the following on OpenBSD / NetBSD, as the scheduling // functions are not implemented. #if !defined( __OpenBSD__ ) && !defined( __NetBSD__ ) uid_t euid; euid = geteuid(); if ( euid == 0 ) { struct sched_param param; if ( sched_getparam( 0, ¶m) == -1 ) { throw Exception( __FILE__, __LINE__, "sched_getparam", errno); } param.sched_priority = origSchedPriority; if ( sched_setscheduler( 0, origSchedPolicy, ¶m) == -1 ) { throw Exception( __FILE__, __LINE__, "sched_setscheduler", errno); } reportEvent( 5, "reverted to original scheduling"); } #endif // !__OpenBSD__ && !__NetBSD__ } /*------------------------------------------------------------------------------ * Run the encoder *----------------------------------------------------------------------------*/ bool DarkIce :: encode ( void ) throw ( Exception ) { unsigned int len; unsigned long bytes; if ( !encConnector->open() ) { throw Exception( __FILE__, __LINE__, "can't open connector"); } bytes = dsp->getSampleRate() * (dsp->getBitsPerSample() / 8UL) * dsp->getChannel() * duration; len = encConnector->transfer( bytes, 4096, 1, 0 ); reportEvent( 1, len, "bytes transfered to the encoders"); encConnector->close(); return true; } /*------------------------------------------------------------------------------ * Run *----------------------------------------------------------------------------*/ int DarkIce :: run ( void ) throw ( Exception ) { reportEvent( 3, "encoding"); setRealTimeScheduling(); encode(); setOriginalScheduling(); reportEvent( 3, "encoding ends"); return 0; } /*------------------------------------------------------------------------------ $Source$ $Log$ Revision 1.40 2004/02/23 19:12:51 darkeye ported to NetBSD Revision 1.39 2004/02/19 06:47:06 darkeye finalized OpenBSD port Revision 1.38 2004/02/18 21:08:11 darkeye ported to OpenBSD (real-time scheduling not yet supported) Revision 1.37 2004/02/15 12:14:38 darkeye added patch to allow mp3 stream downsampling to mono for icecast2 as well Revision 1.36 2004/02/15 12:06:30 darkeye added ALSA support, thanks to Christian Forster Revision 1.35 2003/02/09 13:15:57 darkeye added feature for setting the TITLE comment field for vorbis streams Revision 1.34 2003/02/09 12:57:36 darkeye cosmetic changes to the fileAddDate option Revision 1.33 2002/11/20 16:52:05 wandereq added fileAddDate function Revision 1.32 2002/10/19 12:24:55 darkeye anged internals so that now each encoding/server connection is a separate thread Revision 1.31 2002/08/20 19:35:37 darkeye added possibility to specify maximum bitrate for Ogg Vorbis streams Revision 1.30 2002/08/20 18:37:49 darkeye added mp3 streaming possibility for icecast2 Revision 1.29 2002/08/03 12:41:18 darkeye added possibility to stream in mono when recording in stereo Revision 1.28 2002/07/20 10:59:00 darkeye added support for Ogg Vorbis 1.0, removed support for rc2 Revision 1.27 2002/04/13 11:26:00 darkeye added cbr, abr and vbr setting feature with encoding quality Revision 1.26 2002/03/28 16:43:11 darkeye enabled resampling and variable bitrates for vorbis (icecast2) streams Revision 1.25 2002/02/28 09:49:25 darkeye added possibility to save the encoded stream to a local file only (no streaming server needed) Revision 1.24 2002/02/20 11:54:11 darkeye added local dump file possibility Revision 1.23 2002/02/20 10:35:35 darkeye updated to work with Ogg Vorbis libs rc3 and current IceCast2 cvs Revision 1.22 2001/10/20 10:56:45 darkeye added possibility to disable highpass and lowpass filters for lame Revision 1.21 2001/10/19 12:39:42 darkeye created configure options to compile with or without lame / Ogg Vorbis Revision 1.20 2001/10/19 09:03:39 darkeye added support for resampling mp3 streams 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 Revision 1.17 2001/09/09 11:27:31 darkeye added support for ShoutCast servers Revision 1.16 2001/09/05 20:11:15 darkeye removed dependency on locally stored SGI STL header files now compiler-supplied C++ library STL header files are used compiles under GNU C++ 3 hash_map (an SGI extension to STL) replaced with map std:: namespace prefix added to all STL class references Revision 1.15 2001/08/30 17:25:56 darkeye renamed configure.h to config.h Revision 1.14 2001/08/29 21:08:30 darkeye made some description options in the darkice config file optional Revision 1.13 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.12 2000/12/20 12:36:47 darkeye added POSIX real-time scheduling Revision 1.11 2000/11/18 11:13:27 darkeye removed direct reference to cout, except from main.cpp all class use the Reporter interface to report events Revision 1.10 2000/11/17 15:50:48 darkeye added -Wall flag to compiler and eleminated new warnings Revision 1.9 2000/11/15 18:37:37 darkeye changed the transferable number of bytes to unsigned long Revision 1.8 2000/11/15 18:08:43 darkeye added multiple verbosity-level event reporting and verbosity command line option Revision 1.7 2000/11/13 19:38:55 darkeye moved command line parameter parsing from DarkIce.cpp to main.cpp Revision 1.6 2000/11/13 18:46:50 darkeye added kdoc-style documentation comments Revision 1.5 2000/11/10 20:16:21 darkeye first real tests with multiple streaming 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 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:49 darkeye initial version ------------------------------------------------------------------------------*/