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.

308 lines
9.4 KiB

  1. /*
  2. * File: acmcaps.cpp
  3. *
  4. * Base ACM implementation of Microsoft Network Audio capability object.
  5. *
  6. * Revision History:
  7. *
  8. * 12/20/95 mikev created
  9. * 06/11/96 mikev separated protocol implementation specifics into
  10. * msiacaps.cpp (the original proprietary version) and
  11. * acmh323.cpp (H.323/H.245 implementation)
  12. */
  13. #include "precomp.h"
  14. LPACMFORMATTAGDETAILS paftd_g;
  15. ACMDRIVERDETAILS *padd;
  16. ACMDRIVERDETAILS add;
  17. static UINT uMaxFormatSize =0;
  18. LPWAVEFORMATEX lpScratchFormat;
  19. //Variables imported from msiacaps.cpp.
  20. //uDefTableEntries is the count of default entries
  21. //and default_id_table is the table itself
  22. extern UINT uDefTableEntries;
  23. extern AUDCAP_DETAILS default_id_table[];
  24. BOOL __stdcall DriverEnumCallback(HACMDRIVERID hadid,
  25. DWORD_PTR dwInstance, DWORD fdwSupport);
  26. BOOL __stdcall ACMFormatTagEnumCallback(HACMDRIVERID hadid,
  27. LPACMFORMATTAGDETAILS paftd, DWORD_PTR dwInstance, DWORD fdwSupport);
  28. BOOL __stdcall FormatEnumCallback(HACMDRIVERID hadid,
  29. LPACMFORMATDETAILS pafd, DWORD_PTR dwInstance, DWORD fdwSupport);
  30. CAcmCapability::CAcmCapability()
  31. {
  32. hAcmDriver = NULL;
  33. }
  34. CAcmCapability::~CAcmCapability()
  35. {
  36. CloseACMDriver();
  37. }
  38. BOOL CAcmCapability::OpenACMDriver(HACMDRIVERID hadid)
  39. {
  40. MMRESULT mResult;
  41. // clear any previous open
  42. CloseACMDriver();
  43. // do it
  44. mResult = acmDriverOpen(&hAcmDriver, hadid, 0);
  45. if(mResult != MMSYSERR_NOERROR)
  46. {
  47. return FALSE;
  48. }
  49. return TRUE;
  50. }
  51. VOID CAcmCapability:: CloseACMDriver()
  52. {
  53. if(hAcmDriver)
  54. {
  55. acmDriverClose(hAcmDriver, 0);
  56. hAcmDriver = NULL;
  57. }
  58. }
  59. //
  60. // DriverEnum() is the root level enumeration of ACM formats. Each permutation of
  61. // format tag, bits per sample, and sample rate is considered a unique format
  62. // and will have a unique registry entry if it is "enabled" for internet audio
  63. //
  64. //
  65. // acmDriverEnum() calls DriverEnumCallback() which calls acmFormatTagEnum()
  66. // which calls FormatTagEnumCallback() which calls acmFormatEnum() which
  67. // calls FormatEnumCallback().
  68. //
  69. BOOL CAcmCapability::DriverEnum(DWORD_PTR pAppParam)
  70. {
  71. MMRESULT mResult;
  72. if(!GetFormatBuffer())
  73. {
  74. return FALSE;
  75. }
  76. mResult = acmDriverEnum(DriverEnumCallback, pAppParam, NULL);
  77. if(lpScratchFormat) {
  78. MEMFREE(lpScratchFormat);
  79. lpScratchFormat=NULL;
  80. }
  81. if(mResult != MMSYSERR_NOERROR)
  82. {
  83. return FALSE;
  84. }
  85. return TRUE;
  86. }
  87. // default implementation of FormatEnumHandler does nothing
  88. BOOL CAcmCapability::FormatEnumHandler(HACMDRIVERID hadid,
  89. LPACMFORMATDETAILS pafd, DWORD_PTR dwInstance, DWORD fdwSupport)
  90. {
  91. return FALSE;
  92. }
  93. BOOL __stdcall DriverEnumCallback(HACMDRIVERID hadid,
  94. DWORD_PTR dwInstance, DWORD fdwSupport)
  95. {
  96. MMRESULT mResult;
  97. PACM_APP_PARAM pAppParam = (PACM_APP_PARAM) dwInstance;
  98. CAcmCapability *pCapObject = pAppParam->pCapObject;
  99. ACMFORMATTAGDETAILS aftd;
  100. // not interested unless it's a codec driver
  101. if(!(fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC))
  102. return TRUE; // continue enumeration
  103. add.cbStruct = sizeof(add);
  104. aftd.cbStruct = sizeof(ACMFORMATTAGDETAILS);
  105. aftd.dwFormatTagIndex=0;
  106. aftd.cbFormatSize=0;
  107. // I do NOT know why, but fdwSupport MUST be initialized to zero before
  108. // calling acmFormatTagEnum(). (returns MMSYSERR_INVALPARAM otherwise)
  109. aftd.fdwSupport = 0;
  110. aftd.dwFormatTag = WAVE_FORMAT_UNKNOWN;
  111. aftd.szFormatTag[0]=0;
  112. // now see what formats this driver supports
  113. mResult = acmDriverDetails(hadid, &add, 0);
  114. if(mResult != MMSYSERR_NOERROR)
  115. {
  116. return TRUE; //error, but continue enumerating
  117. }
  118. // set global driver details pointer
  119. padd = &add;
  120. // # of formats are in add.cFormatTags;
  121. DEBUGMSG(ZONE_ACM,("DriverEnumCallback: driver %s has %d formats\r\n",
  122. add.szShortName, add.cFormatTags));
  123. aftd.cStandardFormats = add.cFormatTags;
  124. // open the driver so we can query it for stuff
  125. //mResult = acmDriverOpen(&had, hadid, 0);
  126. //if(mResult != MMSYSERR_NOERROR)
  127. if(!pCapObject->OpenACMDriver(hadid))
  128. {
  129. ERRORMESSAGE(("DriverEnumCallback: driver open failed:0x%08lX\r\n",mResult));
  130. padd = NULL;
  131. return TRUE; //error, but continue enumerating
  132. }
  133. mResult = acmFormatTagEnum(pCapObject->GetDriverHandle(), &aftd, ACMFormatTagEnumCallback, dwInstance, 0);
  134. if(mResult != MMSYSERR_NOERROR)
  135. {
  136. ERRORMESSAGE(("DriverEnumCallback: acmFormatTagEnum failed:0x%08lX\r\n",mResult));
  137. }
  138. // cleanup
  139. pCapObject->CloseACMDriver();
  140. padd = NULL;
  141. return TRUE;
  142. }
  143. BOOL GetFormatBuffer()
  144. {
  145. // get size of largest WAVEFORMATEX structure in the system
  146. MMRESULT mResult = acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT,
  147. (LPVOID) &uMaxFormatSize);
  148. if(mResult != MMSYSERR_NOERROR)
  149. {
  150. ERRORMESSAGE(("GetFormatBuffer: acmMetrics failed:0x%08lX\r\n",mResult));
  151. return FALSE;
  152. }
  153. // workaround bug in some third party codecs: it has been observed that the
  154. // Voxware RT-24 codec distributed by Netscape CoolTalk corrupts the heap when
  155. // the codec is enumerated. It writes more data to the WAVEFORMATEX that it
  156. // indicates when metrics are evaluated. Workaround by allocating twice as much as
  157. // we think we need.
  158. lpScratchFormat = (LPWAVEFORMATEX) MEMALLOC(2* uMaxFormatSize);
  159. if(!lpScratchFormat)
  160. {
  161. ERRORMESSAGE(("GetFormatBuffer: allocation failed\r\n"));
  162. return FALSE;
  163. }
  164. ZeroMemory(lpScratchFormat, uMaxFormatSize);
  165. //Set the size of the extra buffer to maximum possible size...
  166. lpScratchFormat->cbSize=(WORD)(uMaxFormatSize - sizeof (WAVEFORMATEX));
  167. return TRUE;
  168. }
  169. //
  170. // Gets format details (all permutations of formats) for a given format tag that
  171. // the driver supports
  172. //
  173. BOOL __stdcall ACMFormatTagEnumCallback(
  174. HACMDRIVERID hadid,
  175. LPACMFORMATTAGDETAILS paftd,
  176. DWORD_PTR dwInstance,
  177. DWORD fdwSupport)
  178. {
  179. PACM_APP_PARAM pAppParam = (PACM_APP_PARAM) dwInstance;
  180. CAcmCapability *pCapObject = pAppParam->pCapObject;
  181. MMRESULT mResult;
  182. ACMFORMATDETAILS afd;
  183. UINT i;
  184. //Set this first, so that if we are using a default format, we can help the enumerator
  185. //narrow the field.
  186. afd.pwfx = lpScratchFormat;
  187. // if caller wanted to enum ALL formats go right to it (for adding a format)
  188. if (((pAppParam->dwFlags && ACMAPP_FORMATENUMHANDLER_MASK) != ACMAPP_FORMATENUMHANDLER_ADD) &&
  189. (pAppParam->pRegCache)) {
  190. //Do we care about this particular format?
  191. //rrf_nFormats is the number of formats we read in the
  192. //registry.
  193. if (pAppParam->pRegCache->nFormats) {
  194. for (i=0;i<pAppParam->pRegCache->nFormats;i++) {
  195. if (((AUDCAP_DETAILS *)pAppParam->pRegCache->pData[i])->wFormatTag == paftd->dwFormatTag){
  196. //Add some guesses based on the default information
  197. break;
  198. }
  199. }
  200. // i is the index of either the found tag (so we care.) or
  201. // equal to the # of formats in the cache, which means not
  202. // found, so check the default list.
  203. if (i==pAppParam->pRegCache->nFormats) {
  204. //Check the case that some (but not all) of the default formats are missing.
  205. for (i=0;i<uDefTableEntries;i++) {
  206. if (paftd->dwFormatTag == default_id_table[i].wFormatTag) {
  207. break;
  208. }
  209. }
  210. if (i==uDefTableEntries) {
  211. //We don't care about this format, it's not in the cache, or default list
  212. return TRUE;
  213. }
  214. }
  215. }
  216. }
  217. //We support mono formats
  218. afd.pwfx->nChannels=1;
  219. afd.cbStruct = sizeof(afd);
  220. afd.dwFormatIndex = 0;
  221. afd.dwFormatTag = paftd->dwFormatTag;
  222. afd.fdwSupport = 0;
  223. afd.cbwfx = uMaxFormatSize;
  224. afd.szFormat[0]=0;
  225. //afd.dwFormatTag = WAVE_FORMAT_UNKNOWN;
  226. //lpScratchFormat->wFormatTag = WAVE_FORMAT_UNKNOWN;
  227. lpScratchFormat->wFormatTag = LOWORD(paftd->dwFormatTag);
  228. DEBUGMSG(ZONE_ACM,("ACMFormatTagEnumCallback:dwFormatTag 0x%08lX, cbFormatSize 0x%08lX,\r\n",
  229. paftd->dwFormatTag, paftd->cbFormatSize));
  230. DEBUGMSG(ZONE_ACM,("ACMFormatTagEnumCallback:cStandardFormats 0x%08lX, szTag %s,\r\n",
  231. paftd->cStandardFormats, paftd->szFormatTag));
  232. paftd_g = paftd;
  233. // just setting the global paftd_g should be fine, but I'd like to rid of it later
  234. pAppParam->paftd = paftd;
  235. DEBUGMSG(ZONE_ACM,(""));
  236. DEBUGMSG(ZONE_ACM,("All %s formats known to ACM", paftd->szFormatTag));
  237. DEBUGMSG(ZONE_ACM,("====================================="));
  238. DEBUGMSG(ZONE_ACM,("Tag Channels SampPerSec AvgBytPerSec Block BitsPerSample cbSize szFormat"));
  239. mResult = acmFormatEnum(pCapObject->GetDriverHandle(), &afd,
  240. FormatEnumCallback, dwInstance, ACM_FORMATENUMF_WFORMATTAG|ACM_FORMATENUMF_NCHANNELS);
  241. return TRUE;
  242. }
  243. BOOL __stdcall FormatEnumCallback(HACMDRIVERID hadid,
  244. LPACMFORMATDETAILS pafd, DWORD_PTR dwInstance, DWORD fdwSupport)
  245. {
  246. PACM_APP_PARAM pAppParam = (PACM_APP_PARAM) dwInstance;
  247. CAcmCapability *pCapObject = pAppParam->pCapObject;
  248. DEBUGMSG(ZONE_ACM,("0x%04x %8d 0x%08lx 0x%010lx 0x%04x 0x%011x 0x%04x %s",
  249. pafd->pwfx->wFormatTag, pafd->pwfx->nChannels,
  250. pafd->pwfx->nSamplesPerSec, pafd->pwfx->nAvgBytesPerSec,
  251. pafd->pwfx->nBlockAlign, pafd->pwfx->wBitsPerSample,
  252. pafd->pwfx->cbSize, pafd->szFormat));
  253. return pCapObject->FormatEnumHandler(hadid, pafd, dwInstance, fdwSupport);
  254. }
  255.