#include <typeinfo> #include <iostream> #include <time.h> #include "mpluginAudio.h" #include "../../config.h" #include "../convert.h" #include "../MonitorExceptions.h" #include "../MonitorLogging.h" extern "C" { #include "sox.h" } #ifndef WIN32 typedef short SHORT ; #include <dlfcn.h> #else #include <windows.h> #endif using namespace std ; class MonitorAudioPlugInRecorderSOX : public MonitorAudioPlugIn { public: /** * */ MonitorAudioPlugInRecorderSOX() { m_channelNum=0 ; } virtual ~MonitorAudioPlugInRecorderSOX() { sox_format_quit() ; } virtual bool InitAudioProcessing(class MonitorConfiguration* configPtr, XMLNode config, int channelNum) { std::string logFile="screen" ; std::string logLevel="DEBUG" ; XMLNode parameters ; m_channelNum=channelNum; if (!((parameters=config.getChildNode("parameters"))).isEmpty()) { m_filePath=getNodeText(parameters,"path","./") ; logFile=getNodeText(parameters,"logfile","screen") ; logLevel=getNodeText(parameters,"loglevel","INFO") ; } #ifdef WIN32 if (!(logFile=="screen")) { FILE* pFile = fopen(logFile.c_str(), "a"); Output2FILE::Stream() = pFile; } // TODO: log4cxx FILELog::ReportingLevel() = FILELog::FromString(logLevel); LOG_INFO("logging started"; #endif if (sox_init() != SOX_SUCCESS) { ThrowMonitorException("Error initializing sox library!") ; } ; StartRecording(1,"test",10) ; return true ; } virtual void Show() { LOG_INFO("MonitorAudioPluginRecorder successfully loaded") } virtual void WriteToFile (FILE *pFile,unsigned char buffer[],unsigned int bufferSize) { size_t len=fwrite(buffer, sizeof(unsigned char), bufferSize,pFile); if (len!=bufferSize) { LOG_ERROR("Fehler beim Schreiben: " << len << " statt " << bufferSize) // Fehler beim Schreiben ? } } virtual void ProcessAudio(float *buffer, int length) { SOX_SAMPLE_LOCALS ; const int MAXTEMP=20000 ; int jobID=0 ; int myCount=0 ; static sox_sample_t tempBuf[MAXTEMP] ; //static unsigned char mp3Buffer[2*MAXTEMP] ; unsigned int tempBufCounter=0 ; time_t startTime ; if (length>MAXTEMP) { ThrowMonitorException ("Audiobuffer size exceeds temporary buffer size!") ; } { for (int i=0;i<length;i++) { tempBuf[tempBufCounter++]=SOX_FLOAT_32BIT_TO_SAMPLE(*buffer,myCount) ; buffer++; } for (jobID=0;jobID<MAXAUDIOCLIENTS;jobID++) { sox_format_t * pFormat=(sox_format_t*) getCustomValue(jobID); unsigned long seconds = getInfo(jobID) ; SocketThread* pClient=getClient(jobID) ; startTime=getTime1(jobID) ; //TODO: if ((pFormat) && (pClient)) { // if (sox_write (pFormat,tempBuf,length)==0) { // error ThrowMonitorException("Error while sox encoding") ; } time_t curTime=time(NULL) ; if ( (curTime-startTime)>(time_t) seconds) { StopRecording(jobID) ; } } } } } void StartRecording(int jobID,std::string fname,int Sekunden) { LOG_INFO("Starte Aufnahme ..") // Aufnahmedatei erzeugen LOG_INFO("Starte mit dauer:" << Sekunden) if (fname.size()>0) { // Dateiname wurde vorgegeben } else { fname="kein_datename" ; } sox_format_t * pFormat = new sox_format_t ; sox_signalinfo_t info ; sox_encodinginfo_t encoding ; info.rate=8000 ; info.channels=1 ; info.precision= 32 ; info.length=SOX_IGNORE_LENGTH ; info.mult=0 ; sox_init_encodinginfo(&encoding) ; encoding.encoding = SOX_ENCODING_LPC10 ; encoding.bits_per_sample = 0 ; // TODO ? encoding.compression = 0 ; pFormat =sox_open_write ("test.mp3", // war: lpc &info, &encoding, 0, 0, 0) ; if(pFormat==NULL) { LOG_ERROR("File ist NICHT erstellt") } else { LOG_ERROR("File ist erstellt: "<< fname) } // Aufnahme starten, Daten beim Job hinterlegen updateClient(jobID, (unsigned long) pFormat, 0, Sekunden, fname, time(NULL)) ; addThreadMessage(jobID,std::string("104:" +convertIntToString(m_channelNum)+ ":1:") + convertStringToHex(fname)) ; } void StopRecording(int jobID) { LOG_INFO("Aufnahme beendet") sox_format_t* pFormat=(sox_format_t*) getCustomValue(jobID) ; std::string fname=getInfoText(jobID) ; sox_close(pFormat) ; addThreadMessage(jobID,std::string("104:" +convertIntToString(m_channelNum)+ ":0:") + convertStringToHex(fname)) ; clearClient(jobID) ; delete pFormat ; } virtual std::string DoCommand(std::string command, SocketThread* pClient) { std::string resultString="" ; std::string fname ; int Sekunden=0 ; LOG_INFO("Kommando: " << command) parseCommand(command) ; for (int i=0;i<10;i++) { LOG_INFO("Param " << i << ":" << m_param[i]) } if (m_param[0]=="RECORD") //RECORD:<zeit> { if (m_paramCount>1) { try { Sekunden=convertToInt(m_param[1]) ; LOG_INFO("Sekunden als param:" << m_param[1]) LOG_INFO("Sekunden als int:" << Sekunden) } catch (BadConversion e) { LOG_ERROR("Fehler bei der Datenkonvertierung " << m_param[1]) Sekunden=60 ; } } int jobID=addClient(pClient) ; //< Auftraggeber, fuer callback mit Result LOG_INFO("jobID=" << jobID) // Laeuft mit der jobID schon eine Aufzeichnung ? // Wenn, dann keine neue starten, sondern nur verlaengern long SekundenAlterJob = getInfo(jobID) ; LOG_INFO("Zeitdauer alte Aufnahme:" << SekundenAlterJob) if (SekundenAlterJob>0) { // Nur die Zeit anpassen time_t curTime=time(NULL) ; time_t startTime=getTime1(jobID) ; LOG_DEBUG( "Zeiten curTime+Sekunden:" << curTime+Sekunden ; LOG_DEBUG( "Zeiten startTime+SekundenAlterJob:" << startTime+SekundenAlterJob ; if (curTime+Sekunden>startTime+SekundenAlterJob) { fname=getInfoText(jobID) ; Sekunden=curTime+Sekunden-startTime ; LOG_INFO("Aufnahme wird auf " << Sekunden << "verlaengert ") updateClient(jobID,getCustomValue(jobID),0,Sekunden,getInfoText(jobID),startTime) ; addThreadMessage(jobID,std::string("104:" +convertIntToString(m_channelNum)+ ":2:") + convertStringToHex(fname)) ; } } else { time_t m_startTime=time(NULL) ; struct tm *strTime = localtime(&m_startTime) ; char zeitString[60] ; sprintf(zeitString,"%04d%02d%02d%02d%02d%02d", 1900+strTime->tm_year, 1+strTime->tm_mon, strTime->tm_mday, strTime->tm_hour, strTime->tm_min, strTime->tm_sec) ; LOG_DEBUG( zeitString) if (m_paramCount<2) { m_param[2]="X" ; } fname= m_filePath + std::string(zeitString) + "_" + m_param[2] + "_"+ convertIntToString(jobID) ; cout << fname << endl ; if (useLame==1) { fname+=".mp3"; ; } else { fname+=".raw"; ; } StartRecording(jobID,fname,Sekunden) ; } } ; resultString="OK" ; return (resultString) ; } protected: std::string m_filePath ; int useLame ; int m_channelNum ; }; class MonitorAudioPlugInRecorderFactory : public MonitorAudioPlugInFactory { public: MonitorAudioPlugInRecorderFactory() { } ~MonitorAudioPlugInRecorderFactory() { } virtual MonitorAudioPlugIn * CreatePlugIn() { return new MonitorAudioPlugInRecorderSOX; } }; // // The "C" linkage factory0() function creates the PlugInFunFactory // class for this library // DLL_EXPORT void * factory0( void ) { return new MonitorAudioPlugInRecorderFactory; }