filesounddevice.cxx
来自「MiniSip Client with DomainKeys Authentic」· CXX 代码 · 共 488 行
CXX
488 行
/* Copyright (C) 2004-2006 the Minisip Team This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* Copyright (C) 2004 * * Authors: Erik Eliasson <eliasson@it.kth.se> * Johan Bilien <jobi@via.ecp.fr> * Cesc Santasusana <c e s c DOT s a n t a [AT} g m a i l DOT c o m>*/#include<config.h>#include<libminisip/soundcard/FileSoundDevice.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<errno.h>#include<iostream>#include<stdio.h>#include<signal.h>#include<time.h>#include<libmutil/itoa.h>#include<libmutil/mtime.h>#ifdef WIN32 #include<winsock2.h>#else #include<time.h>#endif#if defined(_MSC_VER) || defined(__MINGW32__)# define USE_WIN32_API#endifint filesleep( unsigned long usec ){#ifdef WIN32#include<winsock2.h> struct timeval tv; tv.tv_sec = 0; tv.tv_usec = (long)usec; return select (0, NULL, NULL, NULL, &tv);#else struct timespec request; request.tv_sec = 0; request.tv_nsec = (long) usec * 1000; return nanosleep( &request, NULL );#endif}FileSoundDevice::FileSoundDevice(string in_file, string out_file, int32_t filetype_ ): SoundDevice("!notused_filesounddevice!"), fileType(filetype_), inFilename(in_file), outFilename(out_file){ this->in_fd=-1; this->out_fd=-1; format=-1; openedPlayback=false; openedRecord=false; nChannelsPlay = 0; nChannelsRecord = 0; samplingRate = 0; sampleSize = 0; fileSoundBlockSleep = 20; //default value lastTimeRead = 0; lastTimeWrite = 0; isFirstTimeOpenWrite = true; this->loopRecord = true;}void FileSoundDevice::setAudioParams( int samplingRate_, int nChannels_ ) { if( fileType == FILESOUND_TYPE_RAW ) { if( samplingRate_ > 0 ) samplingRate = samplingRate_; if( nChannels_ > 0 ) { this->nChannelsRecord = nChannels_; this->nChannelsPlay = nChannels_; } } else { cerr << "FileSoundDevice: filetype not understood" << endl; }}int FileSoundDevice::openRecord(int32_t samplerate_, int nChannels_, int format_){ if( format!= -1 && format_!=format ) {#ifdef DEBUG_OUTPUT cerr << "FileSoundDevice::openRecord - trying to modify the format!" << endl;#endif exit(-1); } else { setFormat( format_ ); setAudioParams( samplerate_, nChannels_ ); } #ifdef DEBUG_OUTPUT printf( "FileSoundDev:record - samplerate = %d, nChannels = %d, sampleSize = %d\n", samplingRate, nChannelsRecord, sampleSize );#endif#ifndef _WIN32_WCE in_fd=::open(inFilename.c_str(), O_RDONLY);#else //win32 wcecompat only takes 3 params ... open the file with mode = permission for everybody ... in_fd=::_open(inFilename.c_str(), O_RDONLY, S_IREAD | S_IWRITE | S_IEXEC);#endif if (in_fd==-1){ printError("openRecord"); exit(-1); //FIX: handle nicer - exception } openedRecord=true; return 0;}int FileSoundDevice::openPlayback(int32_t samplerate_, int nChannels_, int format_){ if( format!= -1 && format_!=format ) {#ifdef DEBUG_OUTPUT cerr << "FileSoundDevice::openRecord - trying to modify the format!" << endl;#endif exit(-1); } else { setFormat( format_ ); setAudioParams( samplerate_, nChannels_ ); } #ifdef DEBUG_OUTPUT printf( "FSD:playback - samplerate = %d, nChannels = %d, sampleSize = %d\n", samplingRate, nChannelsPlay, sampleSize );#endif int openFlags; //if it is the first time we open for writing, create and truncate to zero size //otherwise, append to the file if( isFirstTimeOpenWrite ) { #ifdef _MSC_VER openFlags = _O_WRONLY | _O_CREAT | _O_TRUNC; #else openFlags = O_WRONLY | O_CREAT | O_TRUNC; #endif isFirstTimeOpenWrite = false; } else { #ifdef _MSC_VER openFlags = _O_WRONLY | _O_APPEND; #else openFlags = O_WRONLY | O_APPEND; #endif } #ifdef _MSC_VER out_fd =::_open(outFilename.c_str(), openFlags, _S_IREAD | _S_IWRITE );#else out_fd =::open( outFilename.c_str(), openFlags, S_IWUSR | S_IRUSR);#endif if (out_fd==-1){ printError("openPlayback"); exit(-1); //FIX: handle nicer - exception } openedPlayback=true; return 0;}int FileSoundDevice::closeRecord(){ int ret; openedRecord=false;#ifdef _WIN32_WCE ret = ::_close(in_fd);#else ret = ::close(in_fd);#endif if( ret == -1 ) { printError("openRecord"); } lastTimeRead = 0; return ret;}int FileSoundDevice::closePlayback(){ int ret; openedPlayback=false;#ifdef _WIN32_WCE ret = ::_close(out_fd);#else ret = ::close(out_fd);#endif if( ret == -1 ) { printError("openPlayback"); }// lastTimeWrite = 0; return ret;}//n is in samples! not in bytesint FileSoundDevice::read(byte_t *buffer, uint32_t nSamples){ if (lastTimeRead==0){ lastTimeRead = mtime(); } //loop if needed if( loopRecord ) { int currPos; int fileSize; //Check if we are at the end of the file ... currPos = lseek( in_fd, 0, SEEK_CUR ); fileSize = getFileSize( in_fd ); if( currPos == -1 ) { printError("read-loop"); return -1; } //Check not for the exact end of file, but for when there are not enough //samples to read ... skip the few left and loop ... if( (fileSize - currPos ) < ((int)nSamples * getSampleSize() * getNChannelsRecord() ) ) { if( currPos == -1 ) { printError("read-loop2"); return -1; } currPos = lseek( in_fd, 0, SEEK_SET ); if( currPos == -1 ) { printError("read-loop3"); return -1; } } } SoundDevice::read( buffer, nSamples ); if( fileSoundBlockSleep != 0 ) readSleep(); return nSamples;}int FileSoundDevice::readFromDevice(byte_t *buf, uint32_t nSamples){ int retValue=-1; //select the appropriate way to write to the file ... switch( fileType ) { case FILESOUND_TYPE_RAW: #ifdef _WIN32_WCE retValue = ::_read(in_fd, buf, nSamples * getSampleSize() * getNChannelsRecord() );#else retValue = ::read(in_fd, buf, nSamples * getSampleSize() * getNChannelsRecord() );#endif if( retValue == -1 ) { retValue = -errno; printError( "readFromDevice" ); } else { retValue = retValue / ( getSampleSize() * getNChannelsRecord() ); } break; case FILESOUND_TYPE_WAV: case FILESOUND_TYPE_MP3: cerr << "FileSoundDevice::readFromDevice - filetype not implemented" << endl; break; } return retValue;}int FileSoundDevice::readError( int errcode, byte_t * buffer, uint32_t nSamples ) { bool mustReturn = true; switch( errcode ) { case -EAGAIN: #ifndef _WIN32_WCE case -EINTR: #else case WSAEINTR: #endif mustReturn = false; break; default: mustReturn = true; break; } if( mustReturn ) { return -1; } else { return 0; } }void FileSoundDevice::readSleep( ) { uint64_t currentTime; currentTime = mtime(); //the sleep thingy is deactivated if sleeptime < 0 // (the time in the computer should not go backward, right?!// printf("R: %d ", currentTime - lastTimeRead ); while (currentTime - lastTimeRead < fileSoundBlockSleep){ int32_t ret; int32_t sleep = (int32_t ) (fileSoundBlockSleep - (currentTime-lastTimeRead)); if( sleep < 0 ) sleep = 0;// printf(" [%d] ", sleep); ret = filesleep( sleep * 1000); currentTime = mtime();// printf(" %d ", currentTime - lastTimeRead); }// printf("\n"); lastTimeRead+=fileSoundBlockSleep;}int FileSoundDevice::write( byte_t * buffer, uint32_t nSamples ) { if (lastTimeWrite==0){ lastTimeWrite = mtime(); } SoundDevice::write( buffer, nSamples ); //if SoundDevice::sleepTime is >0, then the device has been opened for //playback in non-blocking mode, thus SoundDevice::write will do the sleeping between //calls (no need for FileSoundDevice::write to block for fileSoundBlockSleep miliseconds). if( fileSoundBlockSleep > 0 && sleepTime == 0) writeSleep(); return nSamples;}//n is in samples!! not in bytesint FileSoundDevice::writeToDevice( byte_t *buf, uint32_t nSamples ){ int retValue = -1; //select the appropriate way to write to the file ... switch( fileType ) { case FILESOUND_TYPE_RAW: //write n samples to the file ... #ifdef _WIN32_WCE retValue = ::_write(out_fd, buf, nSamples * getSampleSize() * getNChannelsPlay() );#else retValue = ::write(out_fd, buf, nSamples * getSampleSize() * getNChannelsPlay() );#endif if( retValue == -1 ) { retValue = -errno; printError( "write" ); } else { retValue = retValue / ( getSampleSize() * getNChannelsPlay() ); } break; case FILESOUND_TYPE_WAV: case FILESOUND_TYPE_MP3: cerr << "FileSoundDevice::write - filetype not implemented" << endl; break; } return retValue;}int FileSoundDevice::writeError( int errcode, byte_t * buffer, uint32_t nSamples ) { bool mustReturn = true; switch( errcode ) { case -EAGAIN: #ifndef _WIN32_WCE case -EINTR: #else case WSAEINTR: #endif mustReturn = false; break; default: mustReturn = true; break; } if( mustReturn ) { return -1; } else { return 0; } }void FileSoundDevice::writeSleep( ) { uint64_t currentTime; currentTime = mtime(); //the sleep thingy is deactivated if sleeptime < 0 // (the time in the computer should not go backward, right?!// printf("W: %d ", currentTime - lastTimeWrite ); while (currentTime - lastTimeWrite < fileSoundBlockSleep ){ int32_t ret; int32_t sleep = (int32_t) (fileSoundBlockSleep - (currentTime-lastTimeWrite)); if( sleep < 0 ) sleep = 0;// printf(" [%d] ", sleep); ret = filesleep( sleep * 1000); currentTime = mtime();// printf(" %d ", currentTime - lastTimeWrite); }// printf("\n"); //lastTimeWrite = currentTime; lastTimeWrite += fileSoundBlockSleep;}void FileSoundDevice::sync(){ cerr << "ERROR: sync unimplemented for file sound device"<< endl;}int FileSoundDevice::getFileSize( int fd ) { int ret; int filesize; int currentPos; currentPos = lseek( fd, 0, SEEK_CUR ); if( currentPos == -1 ) {#ifdef DEBUG_OUTPUT// printError("getFileSize (1)");#endif return -1; } filesize = lseek( fd, 0, SEEK_END ); if( filesize == -1 ) {#ifdef DEBUG_OUTPUT// printError("getFileSize(2)");#endif return -1; } ret = lseek( fd, currentPos, SEEK_SET); if( ret == (currentPos-1) ) {#ifdef DEBUG_OUTPUT// printError("getFileSize(3)");#endif return -1; } return filesize;}void FileSoundDevice::printError( string func ) { string errStr; errStr = "FileSoundDevice::" + func + " - errno = ";//cut the function in wince ... most of these are not defined ... not worth the trouble#ifndef _WIN32_WCE switch( errno ) { case EACCES: errStr + "eaccess"; break; case EEXIST: errStr + "eexist"; break; case EFAULT: errStr + "efault"; break; case EISDIR: errStr + "eisdir"; break; #ifndef USE_WIN32_API case ELOOP: errStr + "eloop"; break; #endif case EMFILE: errStr + "emfile"; break; case ENAMETOOLONG: errStr + "toolong"; break; case ENFILE: errStr + "enfile"; break; case ENODEV: errStr + "enodev"; break; case ENOENT: errStr + "enoent"; break; case ENOMEM: errStr + "enomem"; break; case ENOSPC: errStr + "enospc"; break; case ENOTDIR: errStr + "enotdir"; break; case ENXIO: errStr + "enxio"; break; #ifndef USE_WIN32_API case EOVERFLOW: errStr + "eoverflow"; break; #endif case EROFS: errStr + "erofs"; break; #ifndef USE_WIN32_API case ETXTBSY: errStr + "etxtbsy"; break; #endif default: errStr + "unknown"; }#endif cerr << errStr << " (check man page for explanation)" << endl;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?