Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1084 lines
22 KiB

  1. #include "precomp.h"
  2. #include <nmdsprv.h>
  3. #include "mixer.h"
  4. #include "dscstream.h"
  5. #include "agc.h"
  6. // static member initialization
  7. BOOL DSC_Manager::s_bInitialized = FALSE;
  8. DSC_CAPTURE_INFO DSC_Manager::s_aDSC[MAX_NUMBER_DSCAPTURE_DEVICES];
  9. int DSC_Manager::s_nCaptureDevices = 0;
  10. HINSTANCE DSC_Manager::s_hDSCLib = NULL;
  11. DS_CAP_CREATE DSC_Manager::s_pDSCapCreate = NULL;
  12. DS_CAP_ENUM DSC_Manager::s_pDSCapEnum = NULL;
  13. // static
  14. HRESULT DSC_Manager::Initialize()
  15. {
  16. if (s_bInitialized)
  17. {
  18. return S_OK;
  19. }
  20. // failsafe way to to turn DSC off, without turning
  21. // DirectSound support off. Otherwise, the UI setting
  22. // to disable DS will also disable DSC.
  23. {
  24. BOOL bDisable;
  25. RegEntry re(DISABLE_DSC_REGKEY, HKEY_LOCAL_MACHINE, FALSE,0);
  26. bDisable = re.GetNumber(DISABLE_DSC_REGVALUE, FALSE);
  27. if (bDisable)
  28. {
  29. return E_FAIL;
  30. }
  31. }
  32. // initialize the array of structure descriptions
  33. s_hDSCLib = LoadLibrary(DSOUND_DLL);
  34. if (s_hDSCLib == NULL)
  35. return E_FAIL;
  36. s_pDSCapCreate = (DS_CAP_CREATE)GetProcAddress(s_hDSCLib, "DirectSoundCaptureCreate");
  37. s_pDSCapEnum = (DS_CAP_ENUM)GetProcAddress(s_hDSCLib, "DirectSoundCaptureEnumerateA");
  38. if ((s_pDSCapCreate) && (s_pDSCapEnum))
  39. {
  40. // enumerate!
  41. s_pDSCapEnum(DSC_Manager::DSEnumCallback, 0);
  42. if (s_nCaptureDevices != 0)
  43. {
  44. s_bInitialized = TRUE;
  45. return S_OK; // success
  46. }
  47. }
  48. FreeLibrary(s_hDSCLib);
  49. s_hDSCLib = NULL;
  50. return E_FAIL;
  51. }
  52. // static
  53. BOOL CALLBACK DSC_Manager::DSEnumCallback(LPGUID lpGuid, LPCSTR lpcstrDescription,
  54. LPCSTR lpcstrModule, LPVOID lpContext)
  55. {
  56. if (lpGuid == NULL)
  57. {
  58. s_aDSC[s_nCaptureDevices].guid = GUID_NULL;
  59. }
  60. else
  61. {
  62. s_aDSC[s_nCaptureDevices].guid = *lpGuid;
  63. }
  64. lstrcpyn(s_aDSC[s_nCaptureDevices].szDescription, lpcstrDescription, MAX_DSC_DESCRIPTION_STRING);
  65. s_aDSC[s_nCaptureDevices].uWaveId = WAVE_MAPPER;
  66. s_nCaptureDevices++;
  67. return TRUE;
  68. }
  69. // static
  70. HRESULT DSC_Manager::CreateInstance(GUID *pGuid, IDirectSoundCapture **pDSC)
  71. {
  72. HRESULT hr;
  73. if FAILED(Initialize())
  74. {
  75. return E_FAIL;
  76. }
  77. if (*pGuid == GUID_NULL)
  78. pGuid = NULL;
  79. hr = s_pDSCapCreate(pGuid, pDSC, NULL);
  80. return hr;
  81. }
  82. // static
  83. HRESULT DSC_Manager::MapWaveIdToGuid(UINT uWaveID, GUID *pGuid)
  84. {
  85. HRESULT hr;
  86. WAVEINCAPS waveInCaps;
  87. UINT uNumWaveDevs;
  88. GUID guid = GUID_NULL;
  89. int nIndex;
  90. MMRESULT mmr;
  91. HWAVEIN hWaveIn;
  92. WAVEFORMATEX waveFormat = {WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16, 0};
  93. IDirectSoundCapture *pDSC=NULL;
  94. *pGuid = GUID_NULL;
  95. if (FAILED( Initialize() ))
  96. {
  97. return E_FAIL;
  98. }
  99. // only one wave device, take the easy way out
  100. uNumWaveDevs = waveInGetNumDevs();
  101. if ((uNumWaveDevs <= 1) || (uWaveID == WAVE_MAPPER))
  102. {
  103. return S_OK;
  104. }
  105. // more than one wavein device
  106. mmr = waveInGetDevCaps(uWaveID, &waveInCaps, sizeof(WAVEINCAPS));
  107. if (mmr == MMSYSERR_NOERROR)
  108. {
  109. hr = DsprvGetWaveDeviceMapping(waveInCaps.szPname, TRUE, &guid);
  110. if (SUCCEEDED(hr))
  111. {
  112. *pGuid = guid;
  113. return S_OK;
  114. }
  115. }
  116. // scan through the DSC list to see if we've mapped this device
  117. // previously
  118. for (nIndex = 0; nIndex < s_nCaptureDevices; nIndex++)
  119. {
  120. if (s_aDSC[nIndex].uWaveId == uWaveID)
  121. {
  122. *pGuid = s_aDSC[nIndex].guid;
  123. return S_OK;
  124. }
  125. }
  126. // hack approach to mapping the device to a guid
  127. mmr = waveInOpen(&hWaveIn, uWaveID, &waveFormat, 0,0,0);
  128. if (mmr != MMSYSERR_NOERROR)
  129. {
  130. return S_FALSE;
  131. }
  132. // find all the DSC devices that fail to open
  133. for (nIndex = 0; nIndex < s_nCaptureDevices; nIndex++)
  134. {
  135. s_aDSC[nIndex].bAllocated = FALSE;
  136. hr = CreateInstance(&(s_aDSC[nIndex].guid), &pDSC);
  137. if (FAILED(hr))
  138. {
  139. s_aDSC[nIndex].bAllocated = TRUE;
  140. }
  141. else
  142. {
  143. pDSC->Release();
  144. pDSC=NULL;
  145. }
  146. }
  147. waveInClose(hWaveIn);
  148. // scan through the list of allocated devices and
  149. // see which one opens
  150. for (nIndex = 0; nIndex < s_nCaptureDevices; nIndex++)
  151. {
  152. if (s_aDSC[nIndex].bAllocated)
  153. {
  154. hr = CreateInstance(&(s_aDSC[nIndex].guid), &pDSC);
  155. if (SUCCEEDED(hr))
  156. {
  157. // we have a winner
  158. pDSC->Release();
  159. pDSC = NULL;
  160. *pGuid = s_aDSC[nIndex].guid;
  161. s_aDSC[nIndex].uWaveId = uWaveID;
  162. return S_OK;
  163. }
  164. }
  165. }
  166. // if we got to this point, it means we failed to map a device
  167. // just use GUID_NULL and return an error
  168. return S_FALSE;
  169. }
  170. SendDSCStream::SendDSCStream() :
  171. SendMediaStream(),
  172. m_pAudioFilter(NULL),
  173. m_lRefCount(0),
  174. m_pDSC(NULL),
  175. m_pDSCBuffer(NULL),
  176. m_hEvent(NULL),
  177. m_dwSamplesPerFrame(0),
  178. m_dwNumFrames(0),
  179. m_dwFrameSize(0),
  180. m_dwDSCBufferSize(0),
  181. m_dwSilenceTime(0),
  182. m_dwFrameTimeMS(0),
  183. m_bFullDuplex(TRUE),
  184. m_bJammed(FALSE),
  185. m_bCanSignalOpen(TRUE),
  186. m_bCanSignalFail(TRUE),
  187. m_nFailCount(0),
  188. m_agc(NULL),
  189. m_bAutoMix(FALSE),
  190. m_pDTMF(NULL)
  191. {
  192. return;
  193. };
  194. HRESULT SendDSCStream::Initialize(DataPump *pDP)
  195. {
  196. HRESULT hr;
  197. m_pDP = pDP;
  198. hr = DSC_Manager::Initialize();
  199. if (FAILED(hr))
  200. {
  201. return hr;
  202. }
  203. m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  204. if (m_hEvent == NULL)
  205. {
  206. return DPR_CANT_CREATE_EVENT;
  207. }
  208. DBG_SAVE_FILE_LINE
  209. m_pAudioFilter = new AcmFilter();
  210. if (!m_pAudioFilter)
  211. {
  212. return DPR_OUT_OF_MEMORY;
  213. }
  214. DBG_SAVE_FILE_LINE
  215. m_pDTMF = new DTMFQueue;
  216. if (!m_pDTMF)
  217. {
  218. return DPR_OUT_OF_MEMORY;
  219. }
  220. m_DPFlags = DP_FLAG_ACM|DP_FLAG_MMSYSTEM|DP_FLAG_DIRECTSOUND|DP_FLAG_SEND;
  221. m_SendTimestamp = m_SavedTickCount = timeGetTime();
  222. m_dwDstSize = 0;
  223. m_fSending = FALSE;
  224. m_hCapturingThread = NULL;
  225. m_CaptureThId = 0;
  226. m_ThreadFlags = 0;
  227. m_pRTPSend = NULL;
  228. m_RTPPayload = 0;
  229. m_CaptureDevice = -1;
  230. m_pRTPSend = NULL;
  231. ZeroMemory(m_aPackets, sizeof(m_aPackets));
  232. ZeroMemory(&m_mmioSrc, sizeof(m_mmioSrc));
  233. m_DPFlags = DP_FLAG_ACM | DP_FLAG_MMSYSTEM | DP_FLAG_AUTO_SILENCE_DETECT;
  234. m_DPFlags = (m_DPFlags & DP_MASK_PLATFORM) | DPFLAG_ENABLE_SEND;
  235. m_DPFlags |= DPFLAG_INITIALIZED;
  236. return S_OK;
  237. }
  238. SendDSCStream::~SendDSCStream()
  239. {
  240. if (m_DPFlags & DPFLAG_INITIALIZED)
  241. {
  242. if (m_DPFlags & DPFLAG_CONFIGURED_SEND)
  243. {
  244. UnConfigure();
  245. }
  246. if (m_pRTPSend)
  247. {
  248. m_pRTPSend->Release();
  249. m_pRTPSend = NULL;
  250. }
  251. if (m_pDTMF)
  252. {
  253. delete m_pDTMF;
  254. m_pDTMF = NULL;
  255. }
  256. if (m_pAudioFilter)
  257. {
  258. delete m_pAudioFilter;
  259. }
  260. if (m_hEvent)
  261. {
  262. CloseHandle(m_hEvent);
  263. }
  264. m_pDP->RemoveMediaChannel(MCF_SEND|MCF_AUDIO, (IMediaChannel*)(SendMediaStream*)this);
  265. m_DPFlags &= ~DPFLAG_INITIALIZED;
  266. }
  267. }
  268. HRESULT STDMETHODCALLTYPE SendDSCStream::Configure(
  269. BYTE *pFormat,
  270. UINT cbFormat,
  271. BYTE *pChannelParams,
  272. UINT cbParams,
  273. IUnknown *pUnknown)
  274. {
  275. AUDIO_CHANNEL_PARAMETERS audChannelParams;
  276. WAVEFORMATEX *pwfSend;
  277. MMRESULT mmr;
  278. MEDIAPACKETINIT mpi;
  279. DWORD dwSourceSize;
  280. int nIndex;
  281. HRESULT hr;
  282. FX_ENTRY ("SendDSCStream::Configure");
  283. // basic parameter checking
  284. if (! (m_DPFlags & DPFLAG_INITIALIZED))
  285. {
  286. return DPR_OUT_OF_MEMORY;
  287. }
  288. // Not a good idea to change anything while in mid-stream
  289. if (m_DPFlags & DPFLAG_STARTED_SEND)
  290. {
  291. return DPR_IO_PENDING; // anything better to return
  292. }
  293. if (m_DPFlags & DPFLAG_CONFIGURED_SEND)
  294. {
  295. DEBUGMSG(ZONE_DP, ("Stream Re-Configuration - calling UnConfigure"));
  296. UnConfigure();
  297. }
  298. if ((NULL == pFormat) || (NULL == pChannelParams) ||
  299. (cbParams < sizeof(AUDIO_CHANNEL_PARAMETERS)) ||
  300. (cbFormat < sizeof(WAVEFORMATEX)))
  301. {
  302. return DPR_INVALID_PARAMETER;
  303. }
  304. audChannelParams = *(AUDIO_CHANNEL_PARAMETERS *)pChannelParams;
  305. pwfSend = (WAVEFORMATEX *)pFormat;
  306. m_wfCompressed = *pwfSend;
  307. m_wfCompressed.cbSize = 0;
  308. // initialize the ACM filter
  309. mmr = AcmFilter::SuggestDecodeFormat(pwfSend, &m_wfPCM);
  310. if (mmr != MMSYSERR_NOERROR)
  311. {
  312. return DPR_INVALID_PARAMETER;
  313. }
  314. mmr = m_pAudioFilter->Open(&m_wfPCM, pwfSend);
  315. if (mmr != 0)
  316. {
  317. DEBUGMSG (ZONE_DP, ("%s: AcmFilter->Open failed, mmr=%d\r\n", _fx_, mmr));
  318. return DPR_CANT_OPEN_CODEC;
  319. }
  320. m_dwSamplesPerFrame = audChannelParams.ns_params.wFrameSize * audChannelParams.ns_params.wFramesPerPkt;
  321. m_dwFrameTimeMS = (m_dwSamplesPerFrame * 1000) / m_wfPCM.nSamplesPerSec;
  322. ASSERT(m_dwFrameTimeMS > 0);
  323. if (m_dwFrameTimeMS <= 0)
  324. {
  325. m_pAudioFilter->Close();
  326. return DPR_INVALID_PARAMETER;
  327. }
  328. m_dwNumFrames = 1000 / m_dwFrameTimeMS;
  329. if (m_dwNumFrames < MIN_NUM_DSC_SEGMENTS)
  330. {
  331. m_dwNumFrames = MIN_NUM_DSC_SEGMENTS;
  332. }
  333. m_dwFrameSize = m_dwSamplesPerFrame * m_wfPCM.nBlockAlign;
  334. m_pAudioFilter->SuggestDstSize(m_dwFrameSize, &m_dwDstSize);
  335. m_dwDSCBufferSize = m_dwFrameSize * m_dwNumFrames;
  336. // create the packets
  337. ZeroMemory(&mpi, sizeof(mpi));
  338. mpi.dwFlags = DP_FLAG_SEND | DP_FLAG_ACM | DP_FLAG_MMSYSTEM;
  339. mpi.cbOffsetNetData = sizeof(RTP_HDR);
  340. mpi.cbSizeNetData = m_dwDstSize;
  341. mpi.cbSizeDevData = m_dwFrameSize;
  342. mpi.cbSizeRawData = m_dwFrameSize;
  343. mpi.pDevFmt = &m_wfPCM;
  344. mpi.pStrmConvSrcFmt = &m_wfPCM;
  345. mpi.payload = audChannelParams.RTP_Payload;
  346. mpi.pStrmConvDstFmt = &m_wfCompressed;
  347. hr = CreateAudioPackets(&mpi);
  348. if (FAILED(hr))
  349. {
  350. m_pAudioFilter->Close();
  351. return hr;
  352. }
  353. AudioFile::OpenSourceFile(&m_mmioSrc, &m_wfPCM);
  354. m_pDTMF->Initialize(&m_wfPCM);
  355. m_pDTMF->ClearQueue();
  356. // Initialize RSVP structures
  357. InitAudioFlowspec(&m_flowspec, pwfSend, m_dwDstSize);
  358. // Initialize QOS structures
  359. if (m_pDP->m_pIQoS)
  360. {
  361. // Initialize our requests. One for CPU usage, one for bandwidth usage.
  362. m_aRRq.cResourceRequests = 2;
  363. m_aRRq.aResourceRequest[0].resourceID = RESOURCE_OUTGOING_BANDWIDTH;
  364. if (m_dwFrameTimeMS)
  365. {
  366. m_aRRq.aResourceRequest[0].nUnitsMin = (DWORD)(m_dwDstSize + sizeof(RTP_HDR) + IP_HEADER_SIZE + UDP_HEADER_SIZE) * 8000 / m_dwFrameTimeMS;
  367. }
  368. else
  369. {
  370. m_aRRq.aResourceRequest[0].nUnitsMin = 0;
  371. }
  372. m_aRRq.aResourceRequest[1].resourceID = RESOURCE_CPU_CYCLES;
  373. m_aRRq.aResourceRequest[1].nUnitsMin = 800;
  374. // BUGBUG. This is, in theory the correct calculation, but until we do more investigation, go with a known value
  375. // m_aRRq.aResourceRequest[1].nUnitsMin = (audDetails.wCPUUtilizationEncode+audDetails.wCPUUtilizationDecode)*10;
  376. // Initialize QoS structure
  377. ZeroMemory(&m_Stats, sizeof(m_Stats));
  378. // Initialize oldest QoS callback timestamp
  379. // Register with the QoS module. Even if this call fails, that's Ok, we'll do without the QoS support
  380. // The Callback is defined in SendAudioStream
  381. m_pDP->m_pIQoS->RequestResources((GUID *)&MEDIA_TYPE_H323AUDIO, (LPRESOURCEREQUESTLIST)&m_aRRq, SendAudioStream::QosNotifyAudioCB, (DWORD_PTR)this);
  382. }
  383. // Initialize Statview constats
  384. UPDATE_REPORT_ENTRY(g_prptCallParameters, pwfSend->wFormatTag, REP_SEND_AUDIO_FORMAT);
  385. UPDATE_REPORT_ENTRY(g_prptCallParameters, pwfSend->nSamplesPerSec, REP_SEND_AUDIO_SAMPLING);
  386. UPDATE_REPORT_ENTRY(g_prptCallParameters, pwfSend->nAvgBytesPerSec * 8, REP_SEND_AUDIO_BITRATE);
  387. RETAILMSG(("NAC: Audio Send Format: %s", (pwfSend->wFormatTag == 66) ? "G723.1" : (pwfSend->wFormatTag == 112) ? "LHCELP" : (pwfSend->wFormatTag == 113) ? "LHSB08" : (pwfSend->wFormatTag == 114) ? "LHSB12" : (pwfSend->wFormatTag == 115) ? "LHSB16" : (pwfSend->wFormatTag == 6) ? "MSALAW" : (pwfSend->wFormatTag == 7) ? "MSULAW" : (pwfSend->wFormatTag == 130) ? "MSRT24" : "??????"));
  388. RETAILMSG(("NAC: Audio Send Sampling Rate (Hz): %ld", pwfSend->nSamplesPerSec));
  389. RETAILMSG(("NAC: Audio Send Bitrate (w/o network overhead - bps): %ld", pwfSend->nAvgBytesPerSec*8));
  390. UPDATE_REPORT_ENTRY(g_prptCallParameters, m_dwSamplesPerFrame, REP_SEND_AUDIO_PACKET);
  391. RETAILMSG(("NAC: Audio Send Packetization (ms/packet): %ld", pwfSend->nSamplesPerSec ? m_dwSamplesPerFrame * 1000UL / pwfSend->nSamplesPerSec : 0));
  392. INIT_COUNTER_MAX(g_pctrAudioSendBytes, (pwfSend->nAvgBytesPerSec + pwfSend->nSamplesPerSec * (sizeof(RTP_HDR) + IP_HEADER_SIZE + UDP_HEADER_SIZE) / m_dwSamplesPerFrame) << 3);
  393. m_DPFlags |= DPFLAG_CONFIGURED_SEND;
  394. return S_OK;
  395. }
  396. void SendDSCStream::UnConfigure()
  397. {
  398. if (m_DPFlags & DPFLAG_CONFIGURED_SEND)
  399. {
  400. Stop();
  401. m_pAudioFilter->Close();
  402. ReleaseAudioPackets();
  403. AudioFile::CloseSourceFile(&m_mmioSrc);
  404. m_ThreadFlags = 0;
  405. if (m_pDP->m_pIQoS)
  406. {
  407. m_pDP->m_pIQoS->ReleaseResources((GUID *)&MEDIA_TYPE_H323AUDIO, (LPRESOURCEREQUESTLIST)&m_aRRq);
  408. }
  409. m_DPFlags &= ~DPFLAG_CONFIGURED_SEND;
  410. }
  411. }
  412. DWORD CALLBACK SendDSCStream::StartRecordingThread (LPVOID pVoid)
  413. {
  414. SendDSCStream *pThisStream = (SendDSCStream*)pVoid;
  415. return pThisStream->RecordingThread();
  416. }
  417. HRESULT STDMETHODCALLTYPE
  418. SendDSCStream::Start()
  419. {
  420. FX_ENTRY ("SendDSCStream::Start")
  421. if (m_DPFlags & DPFLAG_STARTED_SEND)
  422. return DPR_SUCCESS;
  423. if (!(m_DPFlags & DPFLAG_ENABLE_SEND))
  424. return DPR_SUCCESS;
  425. if ((!(m_DPFlags & DPFLAG_CONFIGURED_SEND)) || (m_pRTPSend==NULL))
  426. return DPR_NOT_CONFIGURED;
  427. ASSERT(!m_hCapturingThread);
  428. m_ThreadFlags &= ~(DPTFLAG_STOP_RECORD|DPTFLAG_STOP_SEND);
  429. SetFlowSpec();
  430. // Start recording thread
  431. if (!(m_ThreadFlags & DPTFLAG_STOP_RECORD))
  432. m_hCapturingThread = CreateThread(NULL,0, SendDSCStream::StartRecordingThread,(LPVOID)this,0,&m_CaptureThId);
  433. m_DPFlags |= DPFLAG_STARTED_SEND;
  434. DEBUGMSG (ZONE_DP, ("%s: Record threadid=%x,\r\n", _fx_, m_CaptureThId));
  435. return DPR_SUCCESS;
  436. }
  437. HRESULT
  438. SendDSCStream::Stop()
  439. {
  440. DWORD dwWait;
  441. if(!(m_DPFlags & DPFLAG_STARTED_SEND))
  442. {
  443. return DPR_SUCCESS;
  444. }
  445. m_ThreadFlags = m_ThreadFlags |
  446. DPTFLAG_STOP_SEND | DPTFLAG_STOP_RECORD ;
  447. DEBUGMSG (ZONE_DP, ("SendDSCStream::Stop - Waiting for record thread to exit\r\n"));
  448. if (m_hCapturingThread)
  449. {
  450. dwWait = WaitForSingleObject (m_hCapturingThread, INFINITE);
  451. DEBUGMSG (ZONE_DP, ("SendDSCStream::Stop: Recording thread exited\r\n"));
  452. ASSERT(dwWait != WAIT_FAILED);
  453. CloseHandle(m_hCapturingThread);
  454. m_hCapturingThread = NULL;
  455. }
  456. m_DPFlags &= ~DPFLAG_STARTED_SEND;
  457. return DPR_SUCCESS;
  458. }
  459. HRESULT STDMETHODCALLTYPE SendDSCStream::SetMaxBitrate(UINT uMaxBitrate)
  460. {
  461. return S_OK;
  462. }
  463. HRESULT STDMETHODCALLTYPE SendDSCStream::QueryInterface(REFIID iid, void **ppVoid)
  464. {
  465. // resolve duplicate inheritance to the SendMediaStream;
  466. if (iid == IID_IUnknown)
  467. {
  468. *ppVoid = (IUnknown*)((SendMediaStream*)this);
  469. }
  470. else if (iid == IID_IMediaChannel)
  471. {
  472. *ppVoid = (IMediaChannel*)((SendMediaStream *)this);
  473. }
  474. else if (iid == IID_IAudioChannel)
  475. {
  476. *ppVoid = (IAudioChannel*)this;
  477. }
  478. else if (iid == IID_IDTMFSend)
  479. {
  480. *ppVoid = (IDTMFSend*)this;
  481. }
  482. else
  483. {
  484. *ppVoid = NULL;
  485. return E_NOINTERFACE;
  486. }
  487. AddRef();
  488. return S_OK;
  489. }
  490. ULONG STDMETHODCALLTYPE SendDSCStream::AddRef(void)
  491. {
  492. return InterlockedIncrement(&m_lRefCount);
  493. }
  494. ULONG STDMETHODCALLTYPE SendDSCStream::Release(void)
  495. {
  496. LONG lRet;
  497. lRet = InterlockedDecrement(&m_lRefCount);
  498. if (lRet == 0)
  499. {
  500. delete this;
  501. return 0;
  502. }
  503. else
  504. return lRet;
  505. }
  506. HRESULT STDMETHODCALLTYPE SendDSCStream::GetSignalLevel(UINT *pSignalStrength)
  507. {
  508. UINT uLevel;
  509. DWORD dwJammed;
  510. if(!(m_DPFlags & DPFLAG_STARTED_SEND))
  511. {
  512. uLevel = 0;
  513. }
  514. else
  515. {
  516. uLevel = m_AudioMonitor.GetSignalStrength();
  517. if (m_bJammed)
  518. {
  519. uLevel = (2 << 16); // 0x0200
  520. }
  521. else if (m_fSending)
  522. {
  523. uLevel |= (1 << 16); // 0x0100 + uLevel
  524. }
  525. }
  526. *pSignalStrength = uLevel;
  527. return S_OK;
  528. return 0;
  529. }
  530. HRESULT STDMETHODCALLTYPE SendDSCStream::GetProperty(DWORD dwProp, PVOID pBuf, LPUINT pcbBuf)
  531. {
  532. HRESULT hr = DPR_SUCCESS;
  533. RTP_STATS RTPStats;
  534. DWORD dwValue;
  535. UINT len = sizeof(DWORD); // most props are DWORDs
  536. if (!pBuf || *pcbBuf < len)
  537. {
  538. *pcbBuf = len;
  539. return DPR_INVALID_PARAMETER;
  540. }
  541. switch (dwProp)
  542. {
  543. case PROP_SILENCE_LEVEL:
  544. *(DWORD *)pBuf = m_AudioMonitor.GetSilenceLevel();
  545. break;
  546. case PROP_DUPLEX_TYPE:
  547. if(m_bFullDuplex == TRUE)
  548. *(DWORD*)pBuf = DUPLEX_TYPE_FULL;
  549. else
  550. *(DWORD*)pBuf = DUPLEX_TYPE_HALF;
  551. break;
  552. case PROP_RECORD_ON:
  553. *(DWORD *)pBuf = (m_DPFlags & DPFLAG_ENABLE_SEND) !=0;
  554. break;
  555. case PROP_PAUSE_SEND:
  556. // To be determined
  557. break;
  558. case PROP_AUDIO_AUTOMIX:
  559. *(DWORD*)pBuf = m_bAutoMix;
  560. break;
  561. case PROP_RECORD_DEVICE:
  562. *(DWORD *)pBuf = m_CaptureDevice;
  563. break;
  564. default:
  565. hr = DPR_INVALID_PROP_ID;
  566. break;
  567. }
  568. return hr;
  569. }
  570. HRESULT STDMETHODCALLTYPE SendDSCStream::SetProperty(DWORD dwProp, PVOID pBuf, UINT cbBuf)
  571. {
  572. DWORD dw;
  573. HRESULT hr = S_OK;
  574. if (cbBuf < sizeof (DWORD))
  575. return DPR_INVALID_PARAMETER;
  576. switch (dwProp)
  577. {
  578. case PROP_SILENCE_LEVEL:
  579. m_AudioMonitor.SetSilenceLevel(*(DWORD *)pBuf);
  580. break;
  581. case DP_PROP_DUPLEX_TYPE:
  582. m_bFullDuplex = (*(DWORD*)pBuf != 0);
  583. break;
  584. case PROP_AUDIO_AUTOMIX:
  585. m_bAutoMix = *(DWORD*)pBuf;
  586. break;
  587. case PROP_RECORD_DEVICE:
  588. m_CaptureDevice = *(DWORD*)pBuf;
  589. RETAILMSG(("NAC: Setting default record device to %d", m_CaptureDevice));
  590. break;
  591. case PROP_RECORD_ON:
  592. {
  593. DWORD flag = DPFLAG_ENABLE_SEND ;
  594. if (*(DWORD *)pBuf)
  595. {
  596. m_DPFlags |= flag; // set the flag
  597. Start();
  598. }
  599. else
  600. {
  601. m_DPFlags &= ~flag; // clear the flag
  602. Stop();
  603. }
  604. RETAILMSG(("DSCStream: %s", *(DWORD*)pBuf ? "Enabling Stream":"Pausing stream"));
  605. break;
  606. }
  607. default:
  608. return DPR_INVALID_PROP_ID;
  609. break;
  610. }
  611. return hr;
  612. }
  613. void SendDSCStream::EndSend()
  614. {
  615. return;
  616. }
  617. HRESULT SendDSCStream::CreateAudioPackets(MEDIAPACKETINIT *pmpi)
  618. {
  619. int nIndex;
  620. HRESULT hr;
  621. ReleaseAudioPackets();
  622. for (nIndex = 0; nIndex < NUM_AUDIOPACKETS; nIndex++)
  623. {
  624. DBG_SAVE_FILE_LINE
  625. m_aPackets[nIndex] = new AudioPacket;
  626. if (m_aPackets[nIndex] == NULL)
  627. {
  628. return DPR_OUT_OF_MEMORY;
  629. }
  630. pmpi->index = nIndex;
  631. hr = m_aPackets[nIndex]->Initialize(pmpi);
  632. if (FAILED(hr))
  633. {
  634. ReleaseAudioPackets();
  635. return hr;
  636. }
  637. }
  638. m_pAudioFilter->PrepareAudioPackets(m_aPackets, NUM_AUDIOPACKETS, AP_ENCODE);
  639. return S_OK;
  640. }
  641. HRESULT SendDSCStream::ReleaseAudioPackets()
  642. {
  643. for (int nIndex = 0; nIndex < NUM_AUDIOPACKETS; nIndex++)
  644. {
  645. if (m_aPackets[nIndex])
  646. {
  647. m_pAudioFilter->UnPrepareAudioPackets(&m_aPackets[nIndex], 1, AP_ENCODE);
  648. delete m_aPackets[nIndex];
  649. m_aPackets[nIndex] = NULL;
  650. }
  651. }
  652. return S_OK;
  653. }
  654. HRESULT SendDSCStream::CreateDSCBuffer()
  655. {
  656. GUID guid = GUID_NULL;
  657. HRESULT hr;
  658. DSCBUFFERDESC dsBufDesc;
  659. DWORD dwIndex;
  660. DSBPOSITIONNOTIFY *aNotifyPos;
  661. IDirectSoundNotify *pNotify = NULL;
  662. if (!(m_DPFlags & DPFLAG_CONFIGURED_SEND))
  663. {
  664. return E_FAIL;
  665. }
  666. if (!m_pDSC)
  667. {
  668. ASSERT(m_pDSCBuffer==NULL);
  669. DSC_Manager::MapWaveIdToGuid(m_CaptureDevice, &guid);
  670. hr = DSC_Manager::CreateInstance(&guid, &m_pDSC);
  671. if (FAILED(hr))
  672. {
  673. return hr;
  674. }
  675. }
  676. if (!m_pDSCBuffer)
  677. {
  678. ZeroMemory(&dsBufDesc, sizeof(dsBufDesc));
  679. dsBufDesc.dwBufferBytes = m_dwDSCBufferSize;
  680. dsBufDesc.lpwfxFormat = &m_wfPCM;
  681. dsBufDesc.dwSize = sizeof(dsBufDesc);
  682. hr = m_pDSC->CreateCaptureBuffer(&dsBufDesc, &m_pDSCBuffer, NULL);
  683. if (FAILED(hr))
  684. {
  685. dsBufDesc.dwFlags = DSCBCAPS_WAVEMAPPED;
  686. hr = m_pDSC->CreateCaptureBuffer(&dsBufDesc, &m_pDSCBuffer, NULL);
  687. }
  688. if (FAILED(hr))
  689. {
  690. m_pDSC->Release();
  691. m_pDSC = NULL;
  692. return hr;
  693. }
  694. else
  695. {
  696. // do the notification positions
  697. DBG_SAVE_FILE_LINE
  698. aNotifyPos = new DSBPOSITIONNOTIFY[m_dwNumFrames];
  699. for (dwIndex = 0; dwIndex < m_dwNumFrames; dwIndex++)
  700. {
  701. aNotifyPos[dwIndex].hEventNotify = m_hEvent;
  702. aNotifyPos[dwIndex].dwOffset = m_dwFrameSize * dwIndex;
  703. }
  704. hr = m_pDSCBuffer->QueryInterface(IID_IDirectSoundNotify, (void**)&pNotify);
  705. if (SUCCEEDED(hr))
  706. {
  707. hr = pNotify->SetNotificationPositions(m_dwNumFrames, aNotifyPos);
  708. }
  709. if (FAILED(hr))
  710. {
  711. DEBUGMSG (ZONE_DP, ("Failed to set notification positions on DSC Buffer"));
  712. }
  713. }
  714. }
  715. if (aNotifyPos)
  716. {
  717. delete [] aNotifyPos;
  718. }
  719. if (pNotify)
  720. {
  721. pNotify->Release();
  722. }
  723. return S_OK;
  724. }
  725. HRESULT SendDSCStream::ReleaseDSCBuffer()
  726. {
  727. if (m_pDSCBuffer)
  728. {
  729. m_pDSCBuffer->Stop();
  730. m_pDSCBuffer->Release();
  731. m_pDSCBuffer = NULL;
  732. }
  733. if (m_pDSC)
  734. {
  735. m_pDSC->Release();
  736. m_pDSC = NULL;
  737. }
  738. return S_OK;
  739. }
  740. // DTMF functions don't do anything if we aren't streaming
  741. HRESULT __stdcall SendDSCStream::AddDigit(int nDigit)
  742. {
  743. IMediaChannel *pIMC = NULL;
  744. RecvMediaStream *pRecv = NULL;
  745. BOOL bIsStarted;
  746. if ((!(m_DPFlags & DPFLAG_CONFIGURED_SEND)) || (m_pRTPSend==NULL))
  747. {
  748. return DPR_NOT_CONFIGURED;
  749. }
  750. bIsStarted = (m_DPFlags & DPFLAG_STARTED_SEND);
  751. if (bIsStarted)
  752. {
  753. Stop();
  754. }
  755. m_pDTMF->AddDigitToQueue(nDigit);
  756. SendDTMF();
  757. m_pDP->GetMediaChannelInterface(MCF_RECV | MCF_AUDIO, &pIMC);
  758. if (pIMC)
  759. {
  760. pRecv = static_cast<RecvMediaStream *> (pIMC);
  761. pRecv->DTMFBeep();
  762. pIMC->Release();
  763. }
  764. if (bIsStarted)
  765. {
  766. Start();
  767. }
  768. return S_OK;
  769. }
  770. // this function is ALMOST identical to SendAudioStream::SendDTMF
  771. HRESULT __stdcall SendDSCStream::SendDTMF()
  772. {
  773. HRESULT hr=S_OK;
  774. MediaPacket *pPacket=NULL;
  775. ULONG uCount;
  776. UINT uBufferSize, uBytesSent;
  777. void *pBuffer;
  778. bool bMark = true;
  779. MMRESULT mmr;
  780. HANDLE hEvent = m_pDTMF->GetEvent();
  781. UINT uTimerID;
  782. // since the stream is stopped, just grab any packet
  783. // from the packet ring
  784. pPacket = m_aPackets[0];
  785. pPacket->GetDevData(&pBuffer, &uBufferSize);
  786. timeBeginPeriod(5);
  787. ResetEvent(hEvent);
  788. uTimerID = timeSetEvent(m_dwFrameTimeMS-1, 5, (LPTIMECALLBACK )hEvent, 0, TIME_CALLBACK_EVENT_SET|TIME_PERIODIC);
  789. hr = m_pDTMF->ReadFromQueue((BYTE*)pBuffer, uBufferSize);
  790. while (SUCCEEDED(hr))
  791. {
  792. // there should be only 1 tone in the queue (it can handle more)
  793. // so assume we only need to set the mark bit on the first packet
  794. pPacket->m_fMark = bMark;
  795. bMark = false;
  796. pPacket->SetProp(MP_PROP_TIMESTAMP, m_SendTimestamp);
  797. m_SendTimestamp += m_dwSamplesPerFrame;
  798. pPacket->SetState (MP_STATE_RECORDED);
  799. // SendPacket will also compress
  800. SendPacket((AudioPacket*)pPacket);
  801. pPacket->m_fMark=false;
  802. pPacket->SetState(MP_STATE_RESET);
  803. hr = m_pDTMF->ReadFromQueue((BYTE*)pBuffer, uBufferSize);
  804. // so that we don't overload the receive jitter buffer on the remote
  805. // side, sleep a few milliseconds between sending packets
  806. if (SUCCEEDED(hr))
  807. {
  808. WaitForSingleObject(hEvent, m_dwFrameTimeMS);
  809. ResetEvent(hEvent);
  810. }
  811. }
  812. timeKillEvent(uTimerID);
  813. timeEndPeriod(5);
  814. return S_OK;
  815. }
  816. HRESULT __stdcall SendDSCStream::ResetDTMF()
  817. {
  818. if(!(m_DPFlags & DPFLAG_STARTED_SEND))
  819. {
  820. return S_OK;
  821. }
  822. return m_pDTMF->ClearQueue();
  823. }
  824.