📄 tapisend.cpp
字号:
break;
}
//
// the sample was submitted successfully. update count
//
nSampleCount++;
if (nSampleCount == 300)
{
LogError("ReadFileIntoTerminal: sleeping 10 seconds");
Sleep(30000);
LogError("ReadFileIntoTerminal: woke up");
}
//
// keep the sample we have just submitted. on exit, we will wait
// for it to be processed by mst
//
SampleQ.push_back(pStreamSample);
} // file reading/sample-filling loop
LogMessage("ReadFileIntoTerminal: processed %lu samples", nSampleCount);
//
// walk through the list of all the samples we have submitted and wait for
// each sample to be done
//
while (!SampleQ.empty())
{
//
// get and remove a sample from the queue
//
IStreamSample *pStreamSample = SampleQ.front();
SampleQ.pop_front();
//
// wait for the Media Streaming Terminal to finish
// processing the sample
//
pStreamSample->CompletionStatus(COMPSTAT_WAIT, INFINITE);
//
// ignore the error code -- release the sample in any case
//
pStreamSample->Release();
pStreamSample = NULL;
}
LogMessage("ReadFileIntoTerminal: released all submitted samples");
//
// tell media streaming terminal's stream that there is no more data
//
pTerminalMediaStream->SendEndOfStream(0);
//
// ignore the error code
//
pTerminalMediaStream->Release();
pTerminalMediaStream = NULL;
//
// if we disconnect the call right away, the call may be dropped before
// receiver gets all the samples. An application should wait for
// STREAM_INACTIVE media event before disconnecting the call.
//
// Since, for simplicity, we are not processing events in this sample,
// wait several seconds to give the receiver a little time to complete
// processing.
//
LogMessage("ReadFileIntoTerminal: Sleeping to give the receiver time "
"to process everything we have sent.");
Sleep(7500);
LogMessage("ReadFileIntoTerminal: completed");
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// CreateAndSelectTerminal
//
// creates a media streaming terminal for capture, sets requested format,
// sets allocator properties, and selects the terminal on the call's first
// outgoing audio stream.
//
// returns S_OK and terminal if success
// error if failure
//
///////////////////////////////////////////////////////////////////////////////
HRESULT CreateAndSelectTerminal(IN ITBasicCallControl *pCall,
IN WAVEFORMATEX *pWaveFormat,
OUT ITTerminal **ppTerminal)
{
HRESULT hr = E_FAIL;
//
// don't return garbage
//
*ppTerminal = NULL;
//
// find an outgoing audio stream on the call
//
ITStream *pStream = NULL;
hr = FindAudioStream(pCall, &pStream);
if (FAILED(hr))
{
LogError("CreateAndSelectTerminal: failed to find an outgoing audio stream");
return hr;
}
//
// create media streaming terminal
//
ITTerminal *pTerminal = NULL;
pTerminal = CreateCaptureMediaStreamingTerminal(pCall);
if (NULL == pTerminal)
{
LogError("CreateAndSelectTerminal: Failed to create media streaming terminal");
pStream->Release();
pStream = NULL;
return hr;
}
//
// tell media streaming terminal format of the data
// we are going to send. If the terminal cannot handle this format
// return an error
//
hr = SetTerminalFormat(pTerminal, pWaveFormat);
if (FAILED(hr))
{
LogMessage("CreateAndSelectTerminal: "
"terminal does not support requested format");
pStream->Release();
pStream = NULL;
pTerminal->Release();
pTerminal = NULL;
return hr;
}
//
// set allocator properties.
//
// calling ITAllocatorProperties::SetAllocatorProperties with the
// properties that are not optimal for the MSP in use can result
// in loss of sound quality.
//
// So make sure that you only call this function if you know you
// need it.
//
// Do not use ITAllocatorProperties::SetAllocatorProperties to set
// the size of the buffer you want to get when you fill samples,
// ITAllocatorProperties::SetBufferSize will accomplish that without
// affecting terminal's allocator properties.
//
// hr = SetAllocatorProperties(pTerminal);
if (FAILED(hr))
{
//
// not fatal -- we are still likely to successfully stream data
//
LogMessage("CreateAndSelectTerminal: "
"failed to set allocator properties. continuing.");
}
//
// select the terminal on the stream
//
hr = pStream->SelectTerminal(pTerminal);
//
// don't need the stream anymore
//
pStream->Release();
pStream = NULL;
if (FAILED(hr))
{
LogError("CreateAndSelectTerminal: Failed to select terminal on the stream");
pTerminal->Release();
pTerminal = NULL;
}
//
// if everything went smoothly pTerminal has a pointer to configured
// and selected terminal. otherwise pTerminal is null and all resources
// have been released
//
*ppTerminal = pTerminal;
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// StreamFile
//
// use TAPI to connect to the remote machine to stream file
//
///////////////////////////////////////////////////////////////////////////////
HRESULT StreamFile(IN char *szFileName,
IN char *szAddressString,
IN char *szAddressType)
{
HRESULT hr = E_FAIL;
LogMessage("StreamFile: file [%s] address [%s] address type [%s]",
szFileName, szAddressString, szAddressType);
//
// check if the file is valid
//
if (!IsValidAudioFile(szFileName))
{
LogError("StreamFile: file not valid [%s]", szFileName);
return E_FAIL;
}
//
// initialize COM libraries -- used by TAPI
//
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if ( FAILED(hr))
{
LogError("StreamFile: Failed to CoInitialize");
return hr;
}
//
// create and initialize TAPI
//
hr = InitializeTAPI();
if (SUCCEEDED(hr))
{
//
// try to make a call
//
ITBasicCallControl *pCall = NULL;
hr = Call(szAddressString, szAddressType, &pCall);
if (SUCCEEDED(hr))
{
//
// construct the file reader object
// to be used to read file's data
//
// note: If you want to play more than one file in one call, reuse
// the same terminal for the duration of the call. Under
// Windows 2000, all data submitted via the Media Streaming Terminal
// during the call must have the same format. Changing a Media
// Streaming Terminal's format after it is initially configured will
// always return an error code, regardless of the OS version.
// Unselecting a Media Streaming Terminal and creating and selecting
// a new terminal on the same stream from the same call with a
// different format is not supported on Windows 2000. This may,
// however, be supported on other versions of Windows. For the latest
// information on which versions of Windows support this, please
// refer to the latest Platform SDK documentation.
//
CAVIFileReader FileReader;
hr = FileReader.Initialize(szFileName);
//
// get the file's format. remember to deallocate when done.
//
WAVEFORMATEX *pWaveFormat = NULL;
if (SUCCEEDED(hr) &&
SUCCEEDED(hr = FileReader.GetFormat(&pWaveFormat)))
{
//
// create and configure a media streaming terminal and select it on this call
//
//
ITTerminal *pPlaybackTerminal = NULL;
hr = CreateAndSelectTerminal(pCall, pWaveFormat, &pPlaybackTerminal);
if (SUCCEEDED(hr))
{
//
// use the terminal to send the file
//
hr = ReadFileIntoTerminal(&FileReader, pPlaybackTerminal);
if (FAILED(hr))
{
LogError("StreamFile: failed to ReadFileIntoTerminal");
}
else
{
LogError("StreamFile: succeeded");
}
//
// release the terminal, we no longer need it
//
pPlaybackTerminal->Release();
pPlaybackTerminal = NULL;
}
else
{
LogError("StreamFile: failed to create and select terminal");
}
//
// no longer need wave format. free memory.
//
FreeMemory(pWaveFormat);
pWaveFormat = NULL;
} // got file format
else
{
LogError("StreamFile: failed to get file's format");
}
//
// there is not much we can do if disconnect fails,
// so ignore its return code
//
pCall->Disconnect(DC_NORMAL);
pCall->Release();
pCall = NULL;
} // call connected
else
{
LogError("StreamFile: failed to connect to %s", szAddressString);
}
//
// tapi has been initialized. shutdown now.
//
ShutdownTAPI();
} // initialized tapi
else
{
LogError("StreamFile: Failed to initialize TAPI");
}
CoUninitialize();
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// HelpScreen
//
// this function displays usage information
//
///////////////////////////////////////////////////////////////////////////////
void HelpScreen()
{
printf("Usage:\n\n"
" TAPISend filename address addresstype\n\n"
" where addresstype is [ ");
for (int i = 0; i < g_nNumberOfAddressTypes - 1; ++i)
{
printf("%s | ", g_szAddressTypes[i]);
}
printf("%s ]\n", g_szAddressTypes[i]);
}
///////////////////////////////////////////////////////////////////////////////
//
// CtrlHandler
//
// handler for ctrl+break, close, logoff and shutdown.
//
// sets g_bExitRequested flag signaling shutdown. this ensures graceful exit
//
///////////////////////////////////////////////////////////////////////////////
BOOL CtrlHandler(DWORD nEventType)
{
//
// are we in the middle of shutting down?
//
if (TRUE == g_bExitRequested)
{
LogMessage("CtrlHandler: shutdown is already in progress");
return TRUE;
}
//
// any exit event (close, ctrl+break/C, logoff, shutdown)
// is a signal for the application to exit.
//
switch (nEventType)
{
case CTRL_C_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
LogMessage("CtrlHandler: Initiating shutdown.");
//
// signal shutdown
//
g_bExitRequested = TRUE;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//
// main
//
// usage: TAPISend filename address addresstype
//
// returns 0 if success, 1 if failure
//
///////////////////////////////////////////////////////////////////////////////
int __cdecl main(int argc, char* argv[])
{
LogMessage("main: started");
//
// validate arguments
//
if (argc != 4)
{
HelpScreen();
LogMessage("main: invalid arguments, exiting.");
return 1;
}
//
// we want to handle ctrl+c and ctrl+break events so we can cleanup on exit
// proceed even in case of failure
//
SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE);
//
// open the file, connect to the remote machine and stream the file over
//
HRESULT hr = StreamFile(argv[1], argv[2], argv[3]);
//
// exiting... we no longer want to handle ctrl+c and ctrl+break
//
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, FALSE);
//
// was file streaming successful?
//
if (FAILED(hr))
{
LogError("main: Failed to stream file");
return 1;
}
LogMessage("main: completed");
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -