Kwint wrote:
Hi, Jaroslav
In your patch for call recording you've forgotten to include diff for files,
where you add ON_MPRRECORDER_ENABLED and ON_MPRRECORDER_DISABLED messages to
enum and where these messages are posted from.
_______________________________________________
sipxtapi-dev mailing list
[email protected]
List Archive: http://list.sipfoundry.org/archive/sipxtapi-dev/
This one should be ok.
Jaroslav Libak
diff -ru
old/sipXmediaAdapterLib/sipXmediaMediaProcessing/src/CpPhoneMediaInterface.cpp
new/sipXmediaAdapterLib/sipXmediaMediaProcessing/src/CpPhoneMediaInterface.cpp
---
old/sipXmediaAdapterLib/sipXmediaMediaProcessing/src/CpPhoneMediaInterface.cpp
Mon Mar 5 11:57:41 2007
+++
new/sipXmediaAdapterLib/sipXmediaMediaProcessing/src/CpPhoneMediaInterface.cpp
Mon Mar 5 21:28:22 2007
@@ -1207,14 +1207,15 @@
// TODO:: This API is designed to record the audio from a single channel.
// If the connectionId is -1, record all.
- //
- // Also -- not sure of the if the spkr is the correct place to record --
- // this probably doesn't include mic data...
- ///
-
- double duration = 0 ;
+ double duration = 0 ; // this means it will record for very long time
int dtmf = 0 ;
- return mpFlowGraph->record(1, -1, NULL, NULL, szFile) ;
+
+ /* use new call recorder
+ from now on, call recorder records both mic, speaker and local dtmf
+ we don't want raw pcm, but wav pcm, raw pcm should be passed to a
callback
+ meant for recording, for example for conversion to mp3 or other format
*/
+ return mpFlowGraph->record(0, -1, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, szFile, 0, 0, NULL,
MprRecorder::WAV_PCM_16) ;
}
OsStatus CpPhoneMediaInterface::stopRecordChannelAudio(int connectionId)
diff -ru old/sipXmediaLib/include/mp/MpCallFlowGraph.h
new/sipXmediaLib/include/mp/MpCallFlowGraph.h
--- old/sipXmediaLib/include/mp/MpCallFlowGraph.h Mon Mar 5 11:56:12 2007
+++ new/sipXmediaLib/include/mp/MpCallFlowGraph.h Mon Mar 5 21:32:51 2007
@@ -113,6 +113,7 @@
RECORDER_SPKR32K,
RECORDER_ECHO_IN32,
#endif // HIGH_SAMPLERATE_AUDIO ]
+ RECORDER_CALL,
MAX_RECORDERS = 10
};
@@ -170,14 +171,7 @@
OsProtectedEvent* recordEvent = NULL);
- OsStatus record(int timeMS, int silenceLength, const char* micName = NULL,
- const char* echoOutName = NULL, const char* spkrName = NULL,
- const char* mic32Name = NULL, const char* spkr32Name = NULL,
- const char* echoIn8Name = NULL, const char* echoIn32Name =
NULL,
- const char* playName = NULL,
- int toneOptions = 0,
- int repeat = 0, OsNotification* completion = NULL,
- MprRecorder::RecordFileFormat format =
MprRecorder::RAW_PCM_16);
+ OsStatus record(int timeMS, int silenceLength, const char* micName = NULL,
const char* echoOutName = NULL, const char* spkrName = NULL, const char*
mic32Name = NULL, const char* spkr32Name = NULL, const char* echoIn8Name =
NULL, const char* echoIn32Name = NULL, const char* playName = NULL, const
char* callName = NULL, int toneOptions = 0, int repeat = 0,
OsNotification* completion = NULL, MprRecorder::RecordFileFormat format =
MprRecorder::RAW_PCM_16);
OsStatus startRecording(const char* audioFileName, UtlBoolean repeat,
@@ -469,6 +463,9 @@
#endif
MprMixer* mpTFsMicMixer;
MprMixer* mpTFsBridgeMixer;
+ MprMixer* mpCallrecMixer;
+ MprSplitter* mpMicCallrecSplitter;
+ MprSplitter* mpSpeakerCallrecSplitter;
MprSplitter* mpToneFileSplitter;
MprToSpkr* mpToSpkr;
MprToneGen* mpToneGen;
@@ -541,6 +538,20 @@
* @returns <b>TRUE</b> if the message was handled
* @returns <b>FALSE</b> otherwise.
*/
+
+ /// Handle the ON_MPRRECORDER_ENABLED message.
+ UtlBoolean handleOnMprRecorderEnabled(MpFlowGraphMsg& rMsg);
+ /**<
+ * @returns <b>TRUE</b> if the message was handled
+ * @returns <b>FALSE</b> otherwise.
+ */
+
+ /// Handle the ON_MPRRECORDER_ENABLED message.
+ UtlBoolean handleOnMprRecorderDisabled(MpFlowGraphMsg& rMsg);
+ /**<
+ * @returns <b>TRUE</b> if the message was handled
+ * @returns <b>FALSE</b> otherwise.
+ */
#ifdef DEBUG_POSTPONE /* [ */
/// sends a message requesting a delay for race condition detection...
diff -ru old/sipXmediaLib/include/mp/MpFlowGraphMsg.h
new/sipXmediaLib/include/mp/MpFlowGraphMsg.h
--- old/sipXmediaLib/include/mp/MpFlowGraphMsg.h Thu Mar 8 13:22:43 2007
+++ new/sipXmediaLib/include/mp/MpFlowGraphMsg.h Mon Mar 5 17:48:16 2007
@@ -71,7 +71,10 @@
FLOWGRAPH_SET_DTMF_NOTIFY,
- RESOURCE_SPECIFIC_START = 100 ///< start of resource-specific
messages
+ RESOURCE_SPECIFIC_START = 100, ///< start of resource-specific
messages
+
+ ON_MPRRECORDER_ENABLED,
+ ON_MPRRECORDER_DISABLED
} MpFlowGraphMsgType;
/* ============================ CREATORS ================================== */
diff -ru old/sipXmediaLib/src/mp/MpCallFlowGraph.cpp
new/sipXmediaLib/src/mp/MpCallFlowGraph.cpp
--- old/sipXmediaLib/src/mp/MpCallFlowGraph.cpp Mon Mar 5 11:56:40 2007
+++ new/sipXmediaLib/src/mp/MpCallFlowGraph.cpp Mon Mar 5 21:28:36 2007
@@ -165,8 +165,14 @@
samplesPerFrame, samplesPerSec);
mpTFsBridgeMixer = new MprMixer("TFsBridgeMixer", 2,
samplesPerFrame, samplesPerSec);
+ mpCallrecMixer = new MprMixer("CallrecMixer", 2,
+ samplesPerFrame, samplesPerSec);
mpToneFileSplitter = new MprSplitter("ToneFileSplitter", 2,
samplesPerFrame, samplesPerSec);
+ mpMicCallrecSplitter = new MprSplitter("MicCallrecSplitter", 2,
+ samplesPerFrame, samplesPerSec);
+ mpSpeakerCallrecSplitter = new MprSplitter("SpeakerCallrecSplitter", 2,
+ samplesPerFrame, samplesPerSec);
#ifndef DISABLE_LOCAL_AUDIO // [
mpToSpkr = new MprToSpkr("ToSpkr",
samplesPerFrame, samplesPerSec,
@@ -195,7 +201,10 @@
#endif // DISABLE_LOCAL_AUDIO ]
res = addResource(*mpTFsMicMixer); assert(res == OS_SUCCESS);
res = addResource(*mpTFsBridgeMixer); assert(res == OS_SUCCESS);
+ res = addResource(*mpCallrecMixer); assert(res == OS_SUCCESS);
res = addResource(*mpToneFileSplitter); assert(res == OS_SUCCESS);
+ res = addResource(*mpMicCallrecSplitter); assert(res == OS_SUCCESS);
+ res = addResource(*mpSpeakerCallrecSplitter); assert(res == OS_SUCCESS);
#ifndef DISABLE_LOCAL_AUDIO
res = addResource(*mpToSpkr); assert(res == OS_SUCCESS);
#endif
@@ -233,14 +242,29 @@
assert(res == OS_SUCCESS);
#endif
- // connect TFsMicMixer -> Bridge
- res = addLink(*mpTFsMicMixer, 0, *mpBridge, 0);
+ // connect TFsMicMixer -> mpMicCallrecSplitter
+ res = addLink(*mpTFsMicMixer, 0, *mpMicCallrecSplitter, 0);
+ assert(res == OS_SUCCESS);
+
+ // connect mpMicCallrecSplitter -> Bridge
+ res = addLink(*mpMicCallrecSplitter, 0, *mpBridge, 0);
+ assert(res == OS_SUCCESS);
+
+ //////////////////////////////////////////////////////////////////////////
+ // connect Bridge -> TFsBridgeMixer through mpSpeakerCallrecSplitter
+
+ res = addLink(*mpBridge, 0, *mpSpeakerCallrecSplitter, 0);
+ assert(res == OS_SUCCESS);
+
+ res = addLink(*mpSpeakerCallrecSplitter, 0, *mpTFsBridgeMixer, 1);
assert(res == OS_SUCCESS);
//////////////////////////////////////////////////////////////////////////
- // connect Bridge -> TFsBridgeMixer
+ // connect mpSpeakerCallrecSplitter and mpMicCallrecSplitter into
mpCallrecMixer
+ res = addLink(*mpMicCallrecSplitter, 1, *mpCallrecMixer, 0);
+ assert(res == OS_SUCCESS);
- res = addLink(*mpBridge, 0, *mpTFsBridgeMixer, 1);
+ res = addLink(*mpSpeakerCallrecSplitter, 1, *mpCallrecMixer, 1);
assert(res == OS_SUCCESS);
//////////////////////////////////////////////////////////////////////////
@@ -282,6 +306,11 @@
// disable the from file
boolRes = mpFromFile->disable(); assert(boolRes);
+ // disable mpCallrecMixer and splitters, they are enabled when we want to
start recording
+ boolRes = mpCallrecMixer->disable(); assert(boolRes);
+ boolRes = mpMicCallrecSplitter->disable(); assert(boolRes);
+ boolRes = mpSpeakerCallrecSplitter->disable(); assert(boolRes);
+
#ifndef DISABLE_LOCAL_AUDIO // [
// disable the FromMic, EchoCancel, PreProcess and ToSpkr -- we cannot have
focus yet...
boolRes = mpFromMic->disable(); assert(boolRes);
@@ -303,6 +332,12 @@
boolRes = mpTFsBridgeMixer->setWeight(0, 0); assert(boolRes);
boolRes = mpTFsBridgeMixer->setWeight(1, 1); assert(boolRes);
+ // set up weights for callrec mixer as they are zeroed in constructor
+ // input 0 is from mic
+ boolRes = mpCallrecMixer->setWeight(1, 0); assert(boolRes);
+ // input 1 is speaker
+ boolRes = mpCallrecMixer->setWeight(1, 1); assert(boolRes);
+
#ifdef INCLUDE_RTCP /* [ */
// All the Media Resource seemed to have been started successfully.
// Let's now create an RTCP Session so that we may be prepared to
@@ -361,6 +396,14 @@
*mpEchoCancel, 1);
assert(res == OS_SUCCESS);
+ // create Call recorder and connect it to mpCallrecMixer
+ mpRecorders[RECORDER_CALL] =
+ new MprRecorder("RecordCall", samplesPerFrame, samplesPerSec);
+ res = addResource(*(mpRecorders[RECORDER_CALL]));
+ assert(res == OS_SUCCESS);
+ res = addLink(*mpCallrecMixer, 0, *(mpRecorders[RECORDER_CALL]), 0);
+ assert(res == OS_SUCCESS);
+
#ifdef HIGH_SAMPLERATE_AUDIO // [
mpRecorders[RECORDER_ECHO_IN32] =
new MprRecorder("RecordEchoIn32", samplesPerFrame, samplesPerSec);
@@ -479,6 +522,13 @@
res = removeLink(*mpToneFileSplitter, 0); assert(res == OS_SUCCESS);
res = removeLink(*mpToneFileSplitter, 1); assert(res == OS_SUCCESS);
+ // remove links of call recording
+ res = removeLink(*mpCallrecMixer, 0); assert(res == OS_SUCCESS);
+ res = removeLink(*mpMicCallrecSplitter, 0); assert(res == OS_SUCCESS);
+ res = removeLink(*mpMicCallrecSplitter, 1); assert(res == OS_SUCCESS);
+ res = removeLink(*mpSpeakerCallrecSplitter, 0); assert(res == OS_SUCCESS);
+ res = removeLink(*mpSpeakerCallrecSplitter, 1); assert(res == OS_SUCCESS);
+
// now remove (and destroy) the resources
#ifndef DISABLE_LOCAL_AUDIO
res = removeResource(*mpFromMic);
@@ -523,6 +573,19 @@
assert(res == OS_SUCCESS);
delete mpFromFile;
+ // kill call recording resources
+ res = removeResource(*mpMicCallrecSplitter);
+ assert(res == OS_SUCCESS);
+ delete mpMicCallrecSplitter;
+
+ res = removeResource(*mpSpeakerCallrecSplitter);
+ assert(res == OS_SUCCESS);
+ delete mpSpeakerCallrecSplitter;
+
+ res = removeResource(*mpCallrecMixer);
+ assert(res == OS_SUCCESS);
+ delete mpCallrecMixer;
+
for (i=0; i<MAX_RECORDERS; i++) {
if (NULL != mpRecorders[i]) {
res = removeResource(*mpRecorders[i]);
@@ -850,7 +913,7 @@
res = record(ms, 999999, created_micNamePtr, created_echoOutNamePtr,
created_spkrNamePtr, created_mic32NamePtr, created_spkr32NamePtr,
created_echoIn8NamePtr, created_echoIn32NamePtr,
- playFilename, 0, 0, NULL);
+ playFilename, NULL, 0, 0, NULL);
playIndex++;
strcpy(saved_playFilename,playFilename);
@@ -890,7 +953,7 @@
}
return record(ms, silenceLength, NULL, NULL, fileName,
- NULL, NULL, NULL, NULL, NULL, 0, 0, recordEvent, format);
+ NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, recordEvent,
format);
}
@@ -910,7 +973,7 @@
OsTime maxEventTime(timeoutSecs, 0);
record(ms, silenceLength, fileName, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, 0, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, 0, 0,
NULL, MprRecorder::WAV_PCM_16);
// Wait until the call sets the number of connections
@@ -960,7 +1023,7 @@
record(ms, silenceLength, NULL, NULL, fileName,
- NULL, NULL, NULL, NULL, NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, 0,
0, recordEvent,format);
if (dtmfTerm)
@@ -1004,55 +1067,54 @@
return ret;
}
-OsStatus MpCallFlowGraph::record(int ms, int silenceLength, const char*
micName,
- const char* echoOutName, const char* spkrName,
- const char* mic32Name, const char* spkr32Name,
- const char* echoIn8Name, const char* echoIn32Name,
- const char* playName, int toneOptions,
- int repeat, OsNotification* completion,
- MprRecorder::RecordFileFormat format)
+OsStatus MpCallFlowGraph::record(int timeMS, int silenceLength, const char*
micName /*= NULL*/, const char* echoOutName /*= NULL*/, const char* spkrName
/*= NULL*/, const char* mic32Name /*= NULL*/, const char* spkr32Name /*=
NULL*/, const char* echoIn8Name /*= NULL*/, const char* echoIn32Name /*=
NULL*/, const char* playName /*= NULL*/, const char* callName /*= NULL*/,
int toneOptions /*= 0*/, int repeat /*= 0*/, OsNotification* completion /*=
NULL*/, MprRecorder::RecordFileFormat format /*= MprRecorder::RAW_PCM_16*/)
{
if (NULL == this) {
MpMediaTask* pMT = MpMediaTask::getMediaTask(0);
MpCallFlowGraph* pIF = (MpCallFlowGraph*) pMT->getFocus();
if (NULL != pIF) {
- return pIF-> record(ms, silenceLength, micName, echoOutName, spkrName,
+ return pIF-> record(timeMS, silenceLength, micName, echoOutName,
spkrName,
mic32Name, spkr32Name, echoIn8Name, echoIn32Name,
- playName, toneOptions, repeat, completion);
+ playName, callName, toneOptions, repeat, completion);
}
return OS_INVALID;
}
if (NULL != micName) {
setupRecorder(RECORDER_MIC, micName,
- ms, silenceLength, completion, format);
+ timeMS, silenceLength, completion, format);
}
if (NULL != echoOutName) {
setupRecorder(RECORDER_ECHO_OUT, echoOutName,
- ms, silenceLength, completion, format);
+ timeMS, silenceLength, completion, format);
}
if (NULL != spkrName) {
setupRecorder(RECORDER_SPKR, spkrName,
- ms, silenceLength, completion, format);
+ timeMS, silenceLength, completion, format);
}
if (NULL != echoIn8Name) {
setupRecorder(RECORDER_ECHO_IN8, echoIn8Name,
- ms, silenceLength, completion, format);
+ timeMS, silenceLength, completion, format);
}
#ifdef HIGH_SAMPLERATE_AUDIO // [
if (NULL != mic32Name) {
setupRecorder(RECORDER_MIC32K, mic32Name,
- ms, silenceLength, completion, format);
+ timeMS, silenceLength, completion, format);
}
if (NULL != spkr32Name) {
setupRecorder(RECORDER_SPKR32K,spkr32Name,
- ms, silenceLength, completion, format);
+ timeMS, silenceLength, completion, format);
}
if (NULL != echoIn32Name) {
setupRecorder(RECORDER_ECHO_IN32,
- echoIn32Name, ms, silenceLength, completion, format);
+ echoIn32Name, timeMS, silenceLength, completion, format);
}
#endif // HIGH_SAMPLERATE_AUDIO ]
+ // set up call recorder
+ if (NULL != callName) {
+ setupRecorder(RECORDER_CALL, callName,
+ timeMS, silenceLength, completion, format);
+ }
return startRecording(playName, repeat, toneOptions, completion);
}
@@ -1101,6 +1163,12 @@
res = mpRecorders[which]->setup(file, format, timeMS, silenceLength,
(OsEvent*)event);
}
+ else
+ {
+ OsSysLog::add(FAC_AUDIO, PRI_ERR,
+ "setupRecorder failed to open file %s, error code is %i",
+ audioFileName, errno);
+ }
return (file != -1);
}
@@ -1727,6 +1795,12 @@
case MpFlowGraphMsg::FLOWGRAPH_SET_DTMF_NOTIFY:
retCode = handleSetDtmfNotify(*pMsg);
break;
+ case MpFlowGraphMsg::ON_MPRRECORDER_ENABLED:
+ retCode = handleOnMprRecorderEnabled(*pMsg);
+ break;
+ case MpFlowGraphMsg::ON_MPRRECORDER_DISABLED:
+ retCode = handleOnMprRecorderDisabled(*pMsg);
+ break;
default:
retCode = MpFlowGraphBase::handleMessage(*pMsg);
break;
@@ -2071,6 +2145,61 @@
mpFromStream->destroy(handle) ;
return TRUE ;
+}
+
+UtlBoolean MpCallFlowGraph::handleOnMprRecorderEnabled(MpFlowGraphMsg& rMsg)
+{
+ UtlBoolean boolRes;
+ int status = rMsg.getInt1();
+ MprRecorder* pRecorder = (MprRecorder*) rMsg.getPtr1() ;
+
+ // if this call recorder, also enable required resources
+ if (pRecorder && pRecorder == mpRecorders[RECORDER_CALL])
+ {
+ boolRes = mpCallrecMixer->enable();
+ assert(boolRes);
+
+ boolRes = mpMicCallrecSplitter->enable();
+ assert(boolRes);
+
+ boolRes = mpSpeakerCallrecSplitter->enable();
+ assert(boolRes);
+ }
+
+ return TRUE;
+}
+
+UtlBoolean MpCallFlowGraph::handleOnMprRecorderDisabled(MpFlowGraphMsg& rMsg)
+{
+ UtlBoolean boolRes;
+ int status = rMsg.getInt1();
+ MprRecorder* pRecorder = (MprRecorder*) rMsg.getPtr1() ;
+
+ if (pRecorder && pRecorder == mpRecorders[RECORDER_CALL])
+ {
+ // also disable mpCallrecMixer and splitters
+
+ /* checks just in case this gets called when
+ the resources have already been deleted
+ */
+ if (mpCallrecMixer)
+ {
+ boolRes = mpCallrecMixer->disable();
+ assert(boolRes);
+ }
+ if (mpMicCallrecSplitter)
+ {
+ boolRes = mpMicCallrecSplitter->disable();
+ assert(boolRes);
+ }
+ if (mpSpeakerCallrecSplitter)
+ {
+ boolRes = mpSpeakerCallrecSplitter->disable();
+ assert(boolRes);
+ }
+ }
+
+ return TRUE;
}
/* ============================ FUNCTIONS ================================= */
diff -ru old/sipXmediaLib/src/mp/MprRecorder.cpp
new/sipXmediaLib/src/mp/MprRecorder.cpp
--- old/sipXmediaLib/src/mp/MprRecorder.cpp Thu Mar 8 13:17:20 2007
+++ new/sipXmediaLib/src/mp/MprRecorder.cpp Mon Mar 5 17:52:13 2007
@@ -122,7 +122,19 @@
if (mFileDescriptor > -1) {
mStatus = RECORDING;
OsSysLog::add(FAC_MP, PRI_DEBUG, "MprRecorder::enable\n");
- return MpResource::enable();
+ UtlBoolean res = MpResource::enable();
+
+ if (res && mpFlowGraph)
+ {
+ /* resource is enabled, we started recording, inform flowgraph
+ so it can send media event to sipxtapi and enable some resources
+ if this is call recorder */
+ MpFlowGraphMsg msg(MpFlowGraphMsg::ON_MPRRECORDER_ENABLED,
+ NULL, (void*) this, NULL, mStatus);
+ postMessage(msg);
+ }
+
+ return res;
} else {
OsSysLog::add(FAC_MP, PRI_DEBUG, "MprRecorder::enable (No file
designated!)\n");
}
@@ -171,6 +183,16 @@
mFileDescriptor = -1;
}
res = (MpResource::disable() && (mFileDescriptor == -1));
+ }
+
+ if (res && mpFlowGraph)
+ {
+ /* resource is disabled, we stopped started recording, inform flowgraph
+ so it can send media event to sipxtapi and disable some resources
+ if this is call recorder */
+ MpFlowGraphMsg msg(MpFlowGraphMsg::ON_MPRRECORDER_DISABLED,
+ NULL, (void*) this, NULL, mStatus);
+ postMessage(msg);
}
return res;
_______________________________________________
sipxtapi-dev mailing list
[email protected]
List Archive: http://list.sipfoundry.org/archive/sipxtapi-dev/