diff --git a/darkice/trunk/AUTHORS b/darkice/trunk/AUTHORS index eaa272d..ebaea81 100644 --- a/darkice/trunk/AUTHORS +++ b/darkice/trunk/AUTHORS @@ -28,4 +28,5 @@ with contributions by: Alexander Vlasov Mariusz Mazur dsk + Clyde Stubbs diff --git a/darkice/trunk/ChangeLog b/darkice/trunk/ChangeLog index 7f2d81c..e82fe31 100644 --- a/darkice/trunk/ChangeLog +++ b/darkice/trunk/ChangeLog @@ -1,5 +1,7 @@ DarkIce next release + o added serial ulaw input device support, thanks to + Clyde Stubbs o improvements on reconnecting: added TCP connection keep-alive to TCP sockets added graceful sleep when trying to reconnect diff --git a/darkice/trunk/acinclude.m4 b/darkice/trunk/acinclude.m4 index e7bf604..c0adc6e 100644 --- a/darkice/trunk/acinclude.m4 +++ b/darkice/trunk/acinclude.m4 @@ -12,7 +12,7 @@ dnl contain the full pathname or the empty string dnl PATH is space-separated list of directories. dnl by Florian Bomers dnl----------------------------------------------------------------------------- -AC_DEFUN(LA_SEARCH_FILE,[ +AC_DEFUN([LA_SEARCH_FILE],[ $1= dnl hack: eliminate line feeds in $2 for FILE in $2; do @@ -41,7 +41,7 @@ dnl TODO: assert function call to verify lib dnl dnl by Florian Bomers dnl----------------------------------------------------------------------------- -AC_DEFUN(LA_SEARCH_LIB,[ +AC_DEFUN([LA_SEARCH_LIB],[ dnl look for lib LA_SEARCH_FILE($1, $3, $5 $5/lib64 $5/lib ) dnl look for header. diff --git a/darkice/trunk/configure.in b/darkice/trunk/configure.in index be0f30d..d1c8a6a 100644 --- a/darkice/trunk/configure.in +++ b/darkice/trunk/configure.in @@ -13,7 +13,7 @@ dnl AC_STDC_HEADERS AC_HAVE_HEADERS(errno.h fcntl.h stdio.h stdlib.h string.h unistd.h limits.h) AC_HAVE_HEADERS(signal.h time.h sys/time.h sys/types.h sys/wait.h math.h) AC_HAVE_HEADERS(netdb.h netinet/in.h sys/ioctl.h sys/socket.h sys/stat.h) -AC_HAVE_HEADERS(sched.h pthread.h) +AC_HAVE_HEADERS(sched.h pthread.h termios.h) AC_HAVE_HEADERS(sys/soundcard.h sys/audio.h sys/audioio.h) AC_HEADER_SYS_WAIT() @@ -55,7 +55,7 @@ AC_ARG_WITH(lame-prefix, if test "x${USE_LAME}" = "xyes" ; then AC_MSG_CHECKING( [for lame library at ${CONFIG_LAME_PREFIX}] ) - LA_SEARCH_LIB( LAME_LIB_LOC, LAME_INC_LOC, libmp3lame.a, lame/lame.h, + LA_SEARCH_LIB( LAME_LIB_LOC, LAME_INC_LOC, libmp3lame.a libmp3lame.so, lame/lame.h, ${CONFIG_LAME_PREFIX}) if test "x${LAME_LIB_LOC}" != "x" ; then AC_DEFINE( HAVE_LAME_LIB, 1, [build with lame library] ) @@ -132,7 +132,7 @@ AC_ARG_WITH(faac-prefix, if test "x${USE_FAAC}" = "xyes" ; then AC_MSG_CHECKING( [for faac library at ${CONFIG_FAAC_PREFIX}] ) - LA_SEARCH_LIB( FAAC_LIB_LOC, FAAC_INC_LOC, libfaac.a, faac.h, + LA_SEARCH_LIB( FAAC_LIB_LOC, FAAC_INC_LOC, libfaac.a libfaac.so, faac.h, ${CONFIG_FAAC_PREFIX}) if test "x${FAAC_LIB_LOC}" != "x" ; then AC_DEFINE( HAVE_FAAC_LIB, 1, [build with faac library] ) @@ -166,7 +166,7 @@ AC_ARG_WITH(twolame-prefix, if test "x${USE_TWOLAME}" = "xyes" ; then AC_MSG_CHECKING( [for twolame library at ${CONFIG_TWOLAME_PREFIX}] ) - LA_SEARCH_LIB( TWOLAME_LIB_LOC, TWOLAME_INC_LOC, libtwolame.a, twolame.h, + LA_SEARCH_LIB( TWOLAME_LIB_LOC, TWOLAME_INC_LOC, libtwolame.a libtwolame.so, twolame.h, ${CONFIG_TWOLAME_PREFIX}) if test "x${TWOLAME_LIB_LOC}" != "x" ; then AC_DEFINE( HAVE_TWOLAME_LIB, 1, [build with twolame library] ) diff --git a/darkice/trunk/man/darkice.1 b/darkice/trunk/man/darkice.1 index 5dad2a2..5d4eb19 100644 --- a/darkice/trunk/man/darkice.1 +++ b/darkice/trunk/man/darkice.1 @@ -102,6 +102,7 @@ Developed with contributions by Alexander Vlasov Mariusz Mazur dsk + Clyde Stubbs .SH LINKS Project homepage: diff --git a/darkice/trunk/src/AudioSource.cpp b/darkice/trunk/src/AudioSource.cpp index 95187ad..3b01ef5 100644 --- a/darkice/trunk/src/AudioSource.cpp +++ b/darkice/trunk/src/AudioSource.cpp @@ -66,7 +66,20 @@ AudioSource :: createDspSource( const char * deviceName, throw ( Exception ) { - if ( Util::strEq( deviceName, "/dev", 4) ) { + if ( Util::strEq( deviceName, "/dev/tty", 8) ) { +#if defined( SUPPORT_SERIAL_ULAW ) + Reporter::reportEvent( 1, "Using Serial Ulaw input device:", + deviceName); + return new SerialUlaw( deviceName, + sampleRate, + bitsPerSample, + channel); +#else + throw Exception( __FILE__, __LINE__, + "trying to open Serial ULaw device " + "without support compiled", deviceName); +#endif + } else if ( Util::strEq( deviceName, "/dev", 4) ) { #if defined( SUPPORT_OSS_DSP ) Reporter::reportEvent( 1, "Using OSS DSP input device:", deviceName); return new OssDspSource( deviceName, diff --git a/darkice/trunk/src/AudioSource.h b/darkice/trunk/src/AudioSource.h index 59c4b0b..b8e5a90 100644 --- a/darkice/trunk/src/AudioSource.h +++ b/darkice/trunk/src/AudioSource.h @@ -71,10 +71,15 @@ #define SUPPORT_JACK_DSP 1 #endif +#if defined ( HAVE_TERMIOS_H ) +#define SUPPORT_SERIAL_ULAW 1 +#endif + #if !defined( SUPPORT_ALSA_DSP ) \ && !defined( SUPPORT_OSS_DSP ) \ && !defined( SUPPORT_JACK_DSP ) \ - && !defined( SUPPORT_SOLARIS_DSP ) + && !defined( SUPPORT_SOLARIS_DSP ) \ + && !defined( SUPPORT_SERIAL_ULAW) // there was no DSP audio system found #error No DSP audio input device found on system #endif @@ -295,6 +300,11 @@ class AudioSource : public Source, public virtual Reporter #include "JackDspSource.h" #endif +#if defined ( SUPPORT_SERIAL_ULAW ) +#include "SerialUlaw.h" +#endif + + /* ====================================================== function prototypes */ diff --git a/darkice/trunk/src/Makefile.am b/darkice/trunk/src/Makefile.am index b5db157..6a5a55d 100644 --- a/darkice/trunk/src/Makefile.am +++ b/darkice/trunk/src/Makefile.am @@ -46,6 +46,8 @@ darkice_SOURCES = AudioEncoder.h\ aflibConverterSmallFilter.h\ OssDspSource.cpp\ OssDspSource.h\ + SerialUlaw.cpp\ + SerialUlaw.h\ SolarisDspSource.cpp\ SolarisDspSource.h\ Ref.h\ diff --git a/darkice/trunk/src/SerialUlaw.cpp b/darkice/trunk/src/SerialUlaw.cpp new file mode 100644 index 0000000..da830f1 --- /dev/null +++ b/darkice/trunk/src/SerialUlaw.cpp @@ -0,0 +1,334 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000 Tyrell Corporation. + Copyright (c) 2006 Clyde Stubbs. + + Tyrell DarkIce + + File : SerialUlaw.cpp + Version : $Revision: 1.13 $ + Author : $Author: darkeye $ + Location : $Source: /cvsroot/darkice/darkice/src/SerialUlaw.cpp,v $ + + 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 */ + +#include "SerialUlaw.h" + +#ifdef SUPPORT_SERIAL_ULAW +// only compile this code if there's support for it + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#else +#error need sys/stat.h +#endif + +#ifdef HAVE_FCNTL_H +#include +#else +#error need fcntl.h +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#else +#error need sys/time.h +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#else +#error need sys/ioctl.h +#endif + +#ifdef HAVE_SYS_SOUNDCARD_H +#include +#else +#error need sys/soundcard.h +#endif + +#ifdef HAVE_TERMIOS_H +#include +#else +#error need termios.h +#endif + + +#include "Util.h" +#include "Exception.h" +#include "SerialUlaw.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * Ulaw decode table + *----------------------------------------------------------------------------*/ +static unsigned int ulawdecode[256] = +{ + 0x8284,0x8684,0x8a84,0x8e84,0x9284,0x9684,0x9a84,0x9e84, + 0xa284,0xa684,0xaa84,0xae84,0xb284,0xb684,0xba84,0xbe84, + 0xc184,0xc384,0xc584,0xc784,0xc984,0xcb84,0xcd84,0xcf84, + 0xd184,0xd384,0xd584,0xd784,0xd984,0xdb84,0xdd84,0xdf84, + 0xe104,0xe204,0xe304,0xe404,0xe504,0xe604,0xe704,0xe804, + 0xe904,0xea04,0xeb04,0xec04,0xed04,0xee04,0xef04,0xf004, + 0xf0c4,0xf144,0xf1c4,0xf244,0xf2c4,0xf344,0xf3c4,0xf444, + 0xf4c4,0xf544,0xf5c4,0xf644,0xf6c4,0xf744,0xf7c4,0xf844, + 0xf8a4,0xf8e4,0xf924,0xf964,0xf9a4,0xf9e4,0xfa24,0xfa64, + 0xfaa4,0xfae4,0xfb24,0xfb64,0xfba4,0xfbe4,0xfc24,0xfc64, + 0xfc94,0xfcb4,0xfcd4,0xfcf4,0xfd14,0xfd34,0xfd54,0xfd74, + 0xfd94,0xfdb4,0xfdd4,0xfdf4,0xfe14,0xfe34,0xfe54,0xfe74, + 0xfe8c,0xfe9c,0xfeac,0xfebc,0xfecc,0xfedc,0xfeec,0xfefc, + 0xff0c,0xff1c,0xff2c,0xff3c,0xff4c,0xff5c,0xff6c,0xff7c, + 0xff88,0xff90,0xff98,0xffa0,0xffa8,0xffb0,0xffb8,0xffc0, + 0xffc8,0xffd0,0xffd8,0xffe0,0xffe8,0xfff0,0xfff8,0x0000, + 0x7d7c,0x797c,0x757c,0x717c,0x6d7c,0x697c,0x657c,0x617c, + 0x5d7c,0x597c,0x557c,0x517c,0x4d7c,0x497c,0x457c,0x417c, + 0x3e7c,0x3c7c,0x3a7c,0x387c,0x367c,0x347c,0x327c,0x307c, + 0x2e7c,0x2c7c,0x2a7c,0x287c,0x267c,0x247c,0x227c,0x207c, + 0x1efc,0x1dfc,0x1cfc,0x1bfc,0x1afc,0x19fc,0x18fc,0x17fc, + 0x16fc,0x15fc,0x14fc,0x13fc,0x12fc,0x11fc,0x10fc,0x0ffc, + 0x0f3c,0x0ebc,0x0e3c,0x0dbc,0x0d3c,0x0cbc,0x0c3c,0x0bbc, + 0x0b3c,0x0abc,0x0a3c,0x09bc,0x093c,0x08bc,0x083c,0x07bc, + 0x075c,0x071c,0x06dc,0x069c,0x065c,0x061c,0x05dc,0x059c, + 0x055c,0x051c,0x04dc,0x049c,0x045c,0x041c,0x03dc,0x039c, + 0x036c,0x034c,0x032c,0x030c,0x02ec,0x02cc,0x02ac,0x028c, + 0x026c,0x024c,0x022c,0x020c,0x01ec,0x01cc,0x01ac,0x018c, + 0x0174,0x0164,0x0154,0x0144,0x0134,0x0124,0x0114,0x0104, + 0x00f4,0x00e4,0x00d4,0x00c4,0x00b4,0x00a4,0x0094,0x0084, + 0x0078,0x0070,0x0068,0x0060,0x0058,0x0050,0x0048,0x0040, + 0x0038,0x0030,0x0028,0x0020,0x0018,0x0010,0x0008,0x0000, +}; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Tell if source id big endian + *----------------------------------------------------------------------------*/ +bool +SerialUlaw :: isBigEndian ( void ) const throw () +{ + return false; +} + + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +SerialUlaw :: init ( const char * name ) throw ( Exception ) +{ + fileName = Util::strDup( name); + fileDescriptor = 0; + running = false; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +SerialUlaw :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + delete[] fileName; +} + + +/*------------------------------------------------------------------------------ + * Open the audio source + *----------------------------------------------------------------------------*/ +bool +SerialUlaw :: open ( void ) throw ( Exception ) +{ + struct termios ts; + + if ( isOpen() ) { + return false; + } + + switch ( getBitsPerSample() ) { + case 16: + break; + + default: + return false; + } + + if (getChannel() != 1) { + reportEvent(3, "Only mono input supported for Serial ULaw"); + return false; + } + if (getSampleRate() != 8000) { + reportEvent(3, "Only 8000 Hz sample rate supported for Serial ULaw"); + return false; + } + + if ( (fileDescriptor = ::open( fileName, O_RDONLY)) == -1 ) { + fileDescriptor = 0; + return false; + } + + if(tcgetattr(fileDescriptor, &ts) < 0) { + close(); + throw Exception( __FILE__, __LINE__, "can't get tty settings"); + } + + cfsetispeed(&ts, B115200); + cfmakeraw(&ts); + ts.c_cflag |= CLOCAL; + if(tcsetattr(fileDescriptor, TCSANOW, &ts) < 0) { + close(); + throw Exception( __FILE__, __LINE__, "can't set tty settings"); + } + + tcflush(fileDescriptor, TCIFLUSH); + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check whether read() would return anything + *----------------------------------------------------------------------------*/ +bool +SerialUlaw :: canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + fd_set fdset; + struct timeval tv; + int ret; + + if ( !isOpen() ) { + return false; + } + + FD_ZERO( &fdset); + FD_SET( fileDescriptor, &fdset); + tv.tv_sec = sec; + tv.tv_usec = usec; + + ret = select( fileDescriptor + 1, &fdset, NULL, NULL, &tv); + + if ( ret == -1 ) { + throw Exception( __FILE__, __LINE__, "select error"); + } + + return ret > 0; +} + + +/*------------------------------------------------------------------------------ + * Read from the audio source + *----------------------------------------------------------------------------*/ +unsigned int +SerialUlaw :: read ( void * buf, + unsigned int len ) throw ( Exception ) +{ + ssize_t ret; + unsigned char ubuf[256], * ptr; + int i, plen; + + if ( !isOpen() ) { + return 0; + } + + ret = 0; + ptr = (unsigned char *)buf; + while(len > 1) { + plen = sizeof(ubuf); + if (plen > (int)len/2) { + plen = len/2; + } + plen = ::read( fileDescriptor, ubuf, plen); + if(plen < 0) { + perror("read"); + throw Exception( __FILE__, __LINE__, "read error"); + } + for(i = 0 ; i != plen ; i++) { + *ptr++ = ulawdecode[ubuf[i]] & 0xFF; + *ptr++ = ulawdecode[ubuf[i]] >> 8; + } + len -= plen*2; + ret += plen*2; + } + + running = true; + return ret; +} + + +/*------------------------------------------------------------------------------ + * Close the audio source + *----------------------------------------------------------------------------*/ +void +SerialUlaw :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + ::close( fileDescriptor); + fileDescriptor = 0; + running = false; +} + + +#endif // SUPPORT_SERIAL_ULAW diff --git a/darkice/trunk/src/SerialUlaw.h b/darkice/trunk/src/SerialUlaw.h new file mode 100644 index 0000000..c5f7150 --- /dev/null +++ b/darkice/trunk/src/SerialUlaw.h @@ -0,0 +1,255 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + Copyright (c) 2007 Clyde Stubbs + + Tyrell DarkIce + + File : SerialUlaw.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef SERIAL_ULAW_SOURCE_H +#define SERIAL_ULAW_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Reporter.h" +#include "AudioSource.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An audio input based on /dev/dsp-like raw devices + * + * @author $Author: darkeye $ + * @version $Revision: 1.7 $ + */ +class SerialUlaw : public AudioSource, public virtual Reporter +{ + private: + + /** + * The file name of the OSS DSP device (e.g. /dev/dsp or /dev/dsp0). + */ + char * fileName; + + /** + * The low-level file descriptor of the OSS DSP device. + */ + int fileDescriptor; + + /** + * Indicates wether the low-level OSS DSP device is in a recording + * state. + */ + bool running; + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + SerialUlaw ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Initialize the object + * + * @param name the file name of the OSS DSP device. + * @exception Exception + */ + void + init ( const char * name ) throw ( Exception ); + + /** + * De-iitialize the object + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param name the file name of the OSS DSP device + * (e.g. /dev/dsp or /dev/dsp0). + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channel number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + SerialUlaw ( const char * name, + int sampleRate = 44100, + int bitsPerSample = 16, + int channel = 2 ) + throw ( Exception ) + + : AudioSource( sampleRate, bitsPerSample, channel) + { + init( name); + } + + /** + * Copy Constructor. + * + * @param ods the object to copy. + * @exception Exception + */ + inline + SerialUlaw ( const SerialUlaw & ods ) throw ( Exception ) + : AudioSource( ods ) + { + init( ods.fileName); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~SerialUlaw ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ds the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual SerialUlaw & + operator= ( const SerialUlaw & ds ) throw ( Exception ) + { + if ( this != &ds ) { + strip(); + AudioSource::operator=( ds); + init( ds.fileName); + } + return *this; + } + + /** + * Tell if the data from this source comes in big or little endian. + * + * @return true if the source is big endian, false otherwise + */ + virtual bool + isBigEndian ( void ) const throw (); + + /** + * Open the SerialUlaw. + * This does not put the OSS DSP device into recording mode. + * To start getting samples, call either canRead() or read(). + * + * @return true if opening was successful, false otherwise + * @exception Exception + * + * @see #canRead + * @see #read + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the SerialUlaw is open. + * + * @return true if the SerialUlaw is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return fileDescriptor != 0; + } + + /** + * Check if the SerialUlaw can be read from. + * Blocks until the specified time for data to be available. + * Puts the OSS DSP device into recording mode. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the SerialUlaw is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the SerialUlaw. + * Puts the OSS DSP device into recording mode. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Close the SerialUlaw. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* SERIAL_ULAW_SOURCE_H */