2
0

dsound_template.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * QEMU DirectSound audio driver header
  3. *
  4. * Copyright (c) 2005 Vassili Karpov (malc)
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #ifdef DSBTYPE_IN
  25. #define NAME "capture buffer"
  26. #define NAME2 "DirectSoundCapture"
  27. #define TYPE in
  28. #define IFACE IDirectSoundCaptureBuffer
  29. #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
  30. #define FIELD dsound_capture_buffer
  31. #define FIELD2 dsound_capture
  32. #define HWVOICE HWVoiceIn
  33. #define DSOUNDVOICE DSoundVoiceIn
  34. #else
  35. #define NAME "playback buffer"
  36. #define NAME2 "DirectSound"
  37. #define TYPE out
  38. #define IFACE IDirectSoundBuffer
  39. #define BUFPTR LPDIRECTSOUNDBUFFER
  40. #define FIELD dsound_buffer
  41. #define FIELD2 dsound
  42. #define HWVOICE HWVoiceOut
  43. #define DSOUNDVOICE DSoundVoiceOut
  44. #endif
  45. static int glue (dsound_unlock_, TYPE) (
  46. BUFPTR buf,
  47. LPVOID p1,
  48. LPVOID p2,
  49. DWORD blen1,
  50. DWORD blen2
  51. )
  52. {
  53. HRESULT hr;
  54. hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
  55. if (FAILED (hr)) {
  56. dsound_logerr (hr, "Could not unlock " NAME "\n");
  57. return -1;
  58. }
  59. return 0;
  60. }
  61. static int glue (dsound_lock_, TYPE) (
  62. BUFPTR buf,
  63. struct audio_pcm_info *info,
  64. DWORD pos,
  65. DWORD len,
  66. LPVOID *p1p,
  67. LPVOID *p2p,
  68. DWORD *blen1p,
  69. DWORD *blen2p,
  70. int entire,
  71. dsound *s
  72. )
  73. {
  74. HRESULT hr;
  75. DWORD flag;
  76. #ifdef DSBTYPE_IN
  77. flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
  78. #else
  79. flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
  80. #endif
  81. hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag);
  82. if (FAILED (hr)) {
  83. #ifndef DSBTYPE_IN
  84. if (hr == DSERR_BUFFERLOST) {
  85. if (glue (dsound_restore_, TYPE) (buf, s)) {
  86. dsound_logerr (hr, "Could not lock " NAME "\n");
  87. }
  88. goto fail;
  89. }
  90. #endif
  91. dsound_logerr (hr, "Could not lock " NAME "\n");
  92. goto fail;
  93. }
  94. if ((p1p && *p1p && (*blen1p % info->bytes_per_frame)) ||
  95. (p2p && *p2p && (*blen2p % info->bytes_per_frame))) {
  96. dolog("DirectSound returned misaligned buffer %ld %ld\n",
  97. *blen1p, *blen2p);
  98. glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p,
  99. blen2p ? *blen2p : 0);
  100. goto fail;
  101. }
  102. if (p1p && !*p1p && *blen1p) {
  103. dolog("warning: !p1 && blen1=%ld\n", *blen1p);
  104. *blen1p = 0;
  105. }
  106. if (p2p && !*p2p && *blen2p) {
  107. dolog("warning: !p2 && blen2=%ld\n", *blen2p);
  108. *blen2p = 0;
  109. }
  110. return 0;
  111. fail:
  112. *p1p = NULL - 1;
  113. *blen1p = -1;
  114. if (p2p) {
  115. *p2p = NULL - 1;
  116. *blen2p = -1;
  117. }
  118. return -1;
  119. }
  120. #ifdef DSBTYPE_IN
  121. static void dsound_fini_in (HWVoiceIn *hw)
  122. #else
  123. static void dsound_fini_out (HWVoiceOut *hw)
  124. #endif
  125. {
  126. HRESULT hr;
  127. #ifdef DSBTYPE_IN
  128. DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
  129. #else
  130. DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
  131. #endif
  132. if (ds->FIELD) {
  133. hr = glue (IFACE, _Stop) (ds->FIELD);
  134. if (FAILED (hr)) {
  135. dsound_logerr (hr, "Could not stop " NAME "\n");
  136. }
  137. hr = glue (IFACE, _Release) (ds->FIELD);
  138. if (FAILED (hr)) {
  139. dsound_logerr (hr, "Could not release " NAME "\n");
  140. }
  141. ds->FIELD = NULL;
  142. }
  143. }
  144. #ifdef DSBTYPE_IN
  145. static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as,
  146. void *drv_opaque)
  147. #else
  148. static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
  149. void *drv_opaque)
  150. #endif
  151. {
  152. int err;
  153. HRESULT hr;
  154. dsound *s = drv_opaque;
  155. WAVEFORMATEX wfx;
  156. struct audsettings obt_as;
  157. #ifdef DSBTYPE_IN
  158. const char *typ = "ADC";
  159. DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
  160. DSCBUFFERDESC bd;
  161. DSCBCAPS bc;
  162. AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.in;
  163. #else
  164. const char *typ = "DAC";
  165. DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
  166. DSBUFFERDESC bd;
  167. DSBCAPS bc;
  168. AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.out;
  169. #endif
  170. if (!s->FIELD2) {
  171. dolog ("Attempt to initialize voice without " NAME2 " object\n");
  172. return -1;
  173. }
  174. err = waveformat_from_audio_settings (&wfx, as);
  175. if (err) {
  176. return -1;
  177. }
  178. memset (&bd, 0, sizeof (bd));
  179. bd.dwSize = sizeof (bd);
  180. bd.lpwfxFormat = &wfx;
  181. bd.dwBufferBytes = audio_buffer_bytes(pdo, as, 92880);
  182. #ifdef DSBTYPE_IN
  183. hr = IDirectSoundCapture_CreateCaptureBuffer (
  184. s->dsound_capture,
  185. &bd,
  186. &ds->dsound_capture_buffer,
  187. NULL
  188. );
  189. #else
  190. bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
  191. hr = IDirectSound_CreateSoundBuffer (
  192. s->dsound,
  193. &bd,
  194. &ds->dsound_buffer,
  195. NULL
  196. );
  197. #endif
  198. if (FAILED (hr)) {
  199. dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
  200. return -1;
  201. }
  202. hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
  203. if (FAILED (hr)) {
  204. dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
  205. goto fail0;
  206. }
  207. #ifdef DEBUG_DSOUND
  208. dolog (NAME "\n");
  209. print_wave_format (&wfx);
  210. #endif
  211. memset (&bc, 0, sizeof (bc));
  212. bc.dwSize = sizeof (bc);
  213. hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
  214. if (FAILED (hr)) {
  215. dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
  216. goto fail0;
  217. }
  218. err = waveformat_to_audio_settings (&wfx, &obt_as);
  219. if (err) {
  220. goto fail0;
  221. }
  222. ds->first_time = true;
  223. obt_as.endianness = 0;
  224. audio_pcm_init_info (&hw->info, &obt_as);
  225. if (bc.dwBufferBytes % hw->info.bytes_per_frame) {
  226. dolog (
  227. "GetCaps returned misaligned buffer size %ld, alignment %d\n",
  228. bc.dwBufferBytes, hw->info.bytes_per_frame
  229. );
  230. }
  231. hw->size_emul = bc.dwBufferBytes;
  232. hw->samples = bc.dwBufferBytes / hw->info.bytes_per_frame;
  233. ds->s = s;
  234. #ifdef DEBUG_DSOUND
  235. dolog ("caps %ld, desc %ld\n",
  236. bc.dwBufferBytes, bd.dwBufferBytes);
  237. #endif
  238. return 0;
  239. fail0:
  240. glue (dsound_fini_, TYPE) (hw);
  241. return -1;
  242. }
  243. #undef NAME
  244. #undef NAME2
  245. #undef TYPE
  246. #undef IFACE
  247. #undef BUFPTR
  248. #undef FIELD
  249. #undef FIELD2
  250. #undef HWVOICE
  251. #undef DSOUNDVOICE