dsoundaudio.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. /*
  2. * QEMU DirectSound audio driver
  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. /*
  25. * SEAL 1.07 by Carlos 'pel' Hasan was used as documentation
  26. */
  27. #include "qemu/osdep.h"
  28. #include "audio.h"
  29. #define AUDIO_CAP "dsound"
  30. #include "audio_int.h"
  31. #include "qemu/host-utils.h"
  32. #include "qemu/module.h"
  33. #include <windows.h>
  34. #include <mmsystem.h>
  35. #include <objbase.h>
  36. #include <dsound.h>
  37. #include "audio_win_int.h"
  38. /* #define DEBUG_DSOUND */
  39. typedef struct {
  40. LPDIRECTSOUND dsound;
  41. LPDIRECTSOUNDCAPTURE dsound_capture;
  42. struct audsettings settings;
  43. Audiodev *dev;
  44. } dsound;
  45. typedef struct {
  46. HWVoiceOut hw;
  47. LPDIRECTSOUNDBUFFER dsound_buffer;
  48. bool first_time;
  49. dsound *s;
  50. } DSoundVoiceOut;
  51. typedef struct {
  52. HWVoiceIn hw;
  53. LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
  54. bool first_time;
  55. dsound *s;
  56. } DSoundVoiceIn;
  57. static void dsound_log_hresult (HRESULT hr)
  58. {
  59. const char *str = "BUG";
  60. switch (hr) {
  61. case DS_OK:
  62. str = "The method succeeded";
  63. break;
  64. #ifdef DS_NO_VIRTUALIZATION
  65. case DS_NO_VIRTUALIZATION:
  66. str = "The buffer was created, but another 3D algorithm was substituted";
  67. break;
  68. #endif
  69. #ifdef DS_INCOMPLETE
  70. case DS_INCOMPLETE:
  71. str = "The method succeeded, but not all the optional effects were obtained";
  72. break;
  73. #endif
  74. #ifdef DSERR_ACCESSDENIED
  75. case DSERR_ACCESSDENIED:
  76. str = "The request failed because access was denied";
  77. break;
  78. #endif
  79. #ifdef DSERR_ALLOCATED
  80. case DSERR_ALLOCATED:
  81. str = "The request failed because resources, "
  82. "such as a priority level, were already in use "
  83. "by another caller";
  84. break;
  85. #endif
  86. #ifdef DSERR_ALREADYINITIALIZED
  87. case DSERR_ALREADYINITIALIZED:
  88. str = "The object is already initialized";
  89. break;
  90. #endif
  91. #ifdef DSERR_BADFORMAT
  92. case DSERR_BADFORMAT:
  93. str = "The specified wave format is not supported";
  94. break;
  95. #endif
  96. #ifdef DSERR_BADSENDBUFFERGUID
  97. case DSERR_BADSENDBUFFERGUID:
  98. str = "The GUID specified in an audiopath file "
  99. "does not match a valid mix-in buffer";
  100. break;
  101. #endif
  102. #ifdef DSERR_BUFFERLOST
  103. case DSERR_BUFFERLOST:
  104. str = "The buffer memory has been lost and must be restored";
  105. break;
  106. #endif
  107. #ifdef DSERR_BUFFERTOOSMALL
  108. case DSERR_BUFFERTOOSMALL:
  109. str = "The buffer size is not great enough to "
  110. "enable effects processing";
  111. break;
  112. #endif
  113. #ifdef DSERR_CONTROLUNAVAIL
  114. case DSERR_CONTROLUNAVAIL:
  115. str = "The buffer control (volume, pan, and so on) "
  116. "requested by the caller is not available. "
  117. "Controls must be specified when the buffer is created, "
  118. "using the dwFlags member of DSBUFFERDESC";
  119. break;
  120. #endif
  121. #ifdef DSERR_DS8_REQUIRED
  122. case DSERR_DS8_REQUIRED:
  123. str = "A DirectSound object of class CLSID_DirectSound8 or later "
  124. "is required for the requested functionality. "
  125. "For more information, see IDirectSound8 Interface";
  126. break;
  127. #endif
  128. #ifdef DSERR_FXUNAVAILABLE
  129. case DSERR_FXUNAVAILABLE:
  130. str = "The effects requested could not be found on the system, "
  131. "or they are in the wrong order or in the wrong location; "
  132. "for example, an effect expected in hardware "
  133. "was found in software";
  134. break;
  135. #endif
  136. #ifdef DSERR_GENERIC
  137. case DSERR_GENERIC:
  138. str = "An undetermined error occurred inside the DirectSound subsystem";
  139. break;
  140. #endif
  141. #ifdef DSERR_INVALIDCALL
  142. case DSERR_INVALIDCALL:
  143. str = "This function is not valid for the current state of this object";
  144. break;
  145. #endif
  146. #ifdef DSERR_INVALIDPARAM
  147. case DSERR_INVALIDPARAM:
  148. str = "An invalid parameter was passed to the returning function";
  149. break;
  150. #endif
  151. #ifdef DSERR_NOAGGREGATION
  152. case DSERR_NOAGGREGATION:
  153. str = "The object does not support aggregation";
  154. break;
  155. #endif
  156. #ifdef DSERR_NODRIVER
  157. case DSERR_NODRIVER:
  158. str = "No sound driver is available for use, "
  159. "or the given GUID is not a valid DirectSound device ID";
  160. break;
  161. #endif
  162. #ifdef DSERR_NOINTERFACE
  163. case DSERR_NOINTERFACE:
  164. str = "The requested COM interface is not available";
  165. break;
  166. #endif
  167. #ifdef DSERR_OBJECTNOTFOUND
  168. case DSERR_OBJECTNOTFOUND:
  169. str = "The requested object was not found";
  170. break;
  171. #endif
  172. #ifdef DSERR_OTHERAPPHASPRIO
  173. case DSERR_OTHERAPPHASPRIO:
  174. str = "Another application has a higher priority level, "
  175. "preventing this call from succeeding";
  176. break;
  177. #endif
  178. #ifdef DSERR_OUTOFMEMORY
  179. case DSERR_OUTOFMEMORY:
  180. str = "The DirectSound subsystem could not allocate "
  181. "sufficient memory to complete the caller's request";
  182. break;
  183. #endif
  184. #ifdef DSERR_PRIOLEVELNEEDED
  185. case DSERR_PRIOLEVELNEEDED:
  186. str = "A cooperative level of DSSCL_PRIORITY or higher is required";
  187. break;
  188. #endif
  189. #ifdef DSERR_SENDLOOP
  190. case DSERR_SENDLOOP:
  191. str = "A circular loop of send effects was detected";
  192. break;
  193. #endif
  194. #ifdef DSERR_UNINITIALIZED
  195. case DSERR_UNINITIALIZED:
  196. str = "The Initialize method has not been called "
  197. "or has not been called successfully "
  198. "before other methods were called";
  199. break;
  200. #endif
  201. #ifdef DSERR_UNSUPPORTED
  202. case DSERR_UNSUPPORTED:
  203. str = "The function called is not supported at this time";
  204. break;
  205. #endif
  206. default:
  207. AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT 0x%lx)\n", hr);
  208. return;
  209. }
  210. AUD_log (AUDIO_CAP, "Reason: %s\n", str);
  211. }
  212. static void G_GNUC_PRINTF (2, 3) dsound_logerr (
  213. HRESULT hr,
  214. const char *fmt,
  215. ...
  216. )
  217. {
  218. va_list ap;
  219. va_start (ap, fmt);
  220. AUD_vlog (AUDIO_CAP, fmt, ap);
  221. va_end (ap);
  222. dsound_log_hresult (hr);
  223. }
  224. static void G_GNUC_PRINTF (3, 4) dsound_logerr2 (
  225. HRESULT hr,
  226. const char *typ,
  227. const char *fmt,
  228. ...
  229. )
  230. {
  231. va_list ap;
  232. AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
  233. va_start (ap, fmt);
  234. AUD_vlog (AUDIO_CAP, fmt, ap);
  235. va_end (ap);
  236. dsound_log_hresult (hr);
  237. }
  238. #ifdef DEBUG_DSOUND
  239. static void print_wave_format (WAVEFORMATEX *wfx)
  240. {
  241. dolog ("tag = %d\n", wfx->wFormatTag);
  242. dolog ("nChannels = %d\n", wfx->nChannels);
  243. dolog ("nSamplesPerSec = %ld\n", wfx->nSamplesPerSec);
  244. dolog ("nAvgBytesPerSec = %ld\n", wfx->nAvgBytesPerSec);
  245. dolog ("nBlockAlign = %d\n", wfx->nBlockAlign);
  246. dolog ("wBitsPerSample = %d\n", wfx->wBitsPerSample);
  247. dolog ("cbSize = %d\n", wfx->cbSize);
  248. }
  249. #endif
  250. static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb, dsound *s)
  251. {
  252. HRESULT hr;
  253. hr = IDirectSoundBuffer_Restore (dsb);
  254. if (hr != DS_OK) {
  255. dsound_logerr (hr, "Could not restore playback buffer\n");
  256. return -1;
  257. }
  258. return 0;
  259. }
  260. #include "dsound_template.h"
  261. #define DSBTYPE_IN
  262. #include "dsound_template.h"
  263. #undef DSBTYPE_IN
  264. static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp,
  265. dsound *s)
  266. {
  267. HRESULT hr;
  268. hr = IDirectSoundBuffer_GetStatus (dsb, statusp);
  269. if (FAILED (hr)) {
  270. dsound_logerr (hr, "Could not get playback buffer status\n");
  271. return -1;
  272. }
  273. if (*statusp & DSBSTATUS_BUFFERLOST) {
  274. dsound_restore_out(dsb, s);
  275. return -1;
  276. }
  277. return 0;
  278. }
  279. static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb,
  280. DWORD *statusp)
  281. {
  282. HRESULT hr;
  283. hr = IDirectSoundCaptureBuffer_GetStatus (dscb, statusp);
  284. if (FAILED (hr)) {
  285. dsound_logerr (hr, "Could not get capture buffer status\n");
  286. return -1;
  287. }
  288. return 0;
  289. }
  290. static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb,
  291. dsound *s)
  292. {
  293. int err;
  294. LPVOID p1, p2;
  295. DWORD blen1, blen2, len1, len2;
  296. err = dsound_lock_out (
  297. dsb,
  298. &hw->info,
  299. 0,
  300. hw->size_emul,
  301. &p1, &p2,
  302. &blen1, &blen2,
  303. 1,
  304. s
  305. );
  306. if (err) {
  307. return;
  308. }
  309. len1 = blen1 / hw->info.bytes_per_frame;
  310. len2 = blen2 / hw->info.bytes_per_frame;
  311. #ifdef DEBUG_DSOUND
  312. dolog ("clear %p,%ld,%ld %p,%ld,%ld\n",
  313. p1, blen1, len1,
  314. p2, blen2, len2);
  315. #endif
  316. if (p1 && len1) {
  317. audio_pcm_info_clear_buf (&hw->info, p1, len1);
  318. }
  319. if (p2 && len2) {
  320. audio_pcm_info_clear_buf (&hw->info, p2, len2);
  321. }
  322. dsound_unlock_out (dsb, p1, p2, blen1, blen2);
  323. }
  324. static int dsound_set_cooperative_level(dsound *s)
  325. {
  326. HRESULT hr;
  327. HWND hwnd;
  328. hwnd = GetDesktopWindow();
  329. hr = IDirectSound_SetCooperativeLevel (
  330. s->dsound,
  331. hwnd,
  332. DSSCL_PRIORITY
  333. );
  334. if (FAILED (hr)) {
  335. dsound_logerr (hr, "Could not set cooperative level for window %p\n",
  336. hwnd);
  337. return -1;
  338. }
  339. return 0;
  340. }
  341. static void dsound_enable_out(HWVoiceOut *hw, bool enable)
  342. {
  343. HRESULT hr;
  344. DWORD status;
  345. DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
  346. LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
  347. dsound *s = ds->s;
  348. if (!dsb) {
  349. dolog ("Attempt to control voice without a buffer\n");
  350. return;
  351. }
  352. if (enable) {
  353. if (dsound_get_status_out (dsb, &status, s)) {
  354. return;
  355. }
  356. if (status & DSBSTATUS_PLAYING) {
  357. dolog ("warning: Voice is already playing\n");
  358. return;
  359. }
  360. dsound_clear_sample (hw, dsb, s);
  361. hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING);
  362. if (FAILED (hr)) {
  363. dsound_logerr (hr, "Could not start playing buffer\n");
  364. return;
  365. }
  366. } else {
  367. if (dsound_get_status_out (dsb, &status, s)) {
  368. return;
  369. }
  370. if (status & DSBSTATUS_PLAYING) {
  371. hr = IDirectSoundBuffer_Stop (dsb);
  372. if (FAILED (hr)) {
  373. dsound_logerr (hr, "Could not stop playing buffer\n");
  374. return;
  375. }
  376. } else {
  377. dolog ("warning: Voice is not playing\n");
  378. }
  379. }
  380. }
  381. static size_t dsound_buffer_get_free(HWVoiceOut *hw)
  382. {
  383. DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
  384. LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
  385. HRESULT hr;
  386. DWORD ppos, wpos;
  387. hr = IDirectSoundBuffer_GetCurrentPosition(
  388. dsb, &ppos, ds->first_time ? &wpos : NULL);
  389. if (FAILED(hr)) {
  390. dsound_logerr(hr, "Could not get playback buffer position\n");
  391. return 0;
  392. }
  393. if (ds->first_time) {
  394. hw->pos_emul = wpos;
  395. ds->first_time = false;
  396. }
  397. return audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
  398. }
  399. static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
  400. {
  401. DSoundVoiceOut *ds = (DSoundVoiceOut *)hw;
  402. LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
  403. DWORD act_size;
  404. size_t req_size;
  405. int err;
  406. void *ret;
  407. req_size = MIN(*size, hw->size_emul - hw->pos_emul);
  408. assert(req_size > 0);
  409. err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
  410. &act_size, NULL, false, ds->s);
  411. if (err) {
  412. dolog("Failed to lock buffer\n");
  413. *size = 0;
  414. return NULL;
  415. }
  416. *size = act_size;
  417. return ret;
  418. }
  419. static size_t dsound_put_buffer_out(HWVoiceOut *hw, void *buf, size_t len)
  420. {
  421. DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
  422. LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
  423. int err = dsound_unlock_out(dsb, buf, NULL, len, 0);
  424. if (err) {
  425. dolog("Failed to unlock buffer!!\n");
  426. return 0;
  427. }
  428. hw->pos_emul = (hw->pos_emul + len) % hw->size_emul;
  429. return len;
  430. }
  431. static void dsound_enable_in(HWVoiceIn *hw, bool enable)
  432. {
  433. HRESULT hr;
  434. DWORD status;
  435. DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
  436. LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
  437. if (!dscb) {
  438. dolog ("Attempt to control capture voice without a buffer\n");
  439. return;
  440. }
  441. if (enable) {
  442. if (dsound_get_status_in (dscb, &status)) {
  443. return;
  444. }
  445. if (status & DSCBSTATUS_CAPTURING) {
  446. dolog ("warning: Voice is already capturing\n");
  447. return;
  448. }
  449. /* clear ?? */
  450. hr = IDirectSoundCaptureBuffer_Start (dscb, DSCBSTART_LOOPING);
  451. if (FAILED (hr)) {
  452. dsound_logerr (hr, "Could not start capturing\n");
  453. return;
  454. }
  455. } else {
  456. if (dsound_get_status_in (dscb, &status)) {
  457. return;
  458. }
  459. if (status & DSCBSTATUS_CAPTURING) {
  460. hr = IDirectSoundCaptureBuffer_Stop (dscb);
  461. if (FAILED (hr)) {
  462. dsound_logerr (hr, "Could not stop capturing\n");
  463. return;
  464. }
  465. } else {
  466. dolog ("warning: Voice is not capturing\n");
  467. }
  468. }
  469. }
  470. static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size)
  471. {
  472. DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
  473. LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
  474. HRESULT hr;
  475. DWORD rpos, act_size;
  476. size_t req_size;
  477. int err;
  478. void *ret;
  479. hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, NULL, &rpos);
  480. if (FAILED(hr)) {
  481. dsound_logerr(hr, "Could not get capture buffer position\n");
  482. *size = 0;
  483. return NULL;
  484. }
  485. if (ds->first_time) {
  486. hw->pos_emul = rpos;
  487. ds->first_time = false;
  488. }
  489. req_size = audio_ring_dist(rpos, hw->pos_emul, hw->size_emul);
  490. req_size = MIN(*size, MIN(req_size, hw->size_emul - hw->pos_emul));
  491. if (req_size == 0) {
  492. *size = 0;
  493. return NULL;
  494. }
  495. err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
  496. &act_size, NULL, false, ds->s);
  497. if (err) {
  498. dolog("Failed to lock buffer\n");
  499. *size = 0;
  500. return NULL;
  501. }
  502. *size = act_size;
  503. return ret;
  504. }
  505. static void dsound_put_buffer_in(HWVoiceIn *hw, void *buf, size_t len)
  506. {
  507. DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
  508. LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
  509. int err = dsound_unlock_in(dscb, buf, NULL, len, 0);
  510. if (err) {
  511. dolog("Failed to unlock buffer!!\n");
  512. return;
  513. }
  514. hw->pos_emul = (hw->pos_emul + len) % hw->size_emul;
  515. }
  516. static void dsound_audio_fini (void *opaque)
  517. {
  518. HRESULT hr;
  519. dsound *s = opaque;
  520. if (!s->dsound) {
  521. g_free(s);
  522. return;
  523. }
  524. hr = IDirectSound_Release (s->dsound);
  525. if (FAILED (hr)) {
  526. dsound_logerr (hr, "Could not release DirectSound\n");
  527. }
  528. s->dsound = NULL;
  529. if (!s->dsound_capture) {
  530. g_free(s);
  531. return;
  532. }
  533. hr = IDirectSoundCapture_Release (s->dsound_capture);
  534. if (FAILED (hr)) {
  535. dsound_logerr (hr, "Could not release DirectSoundCapture\n");
  536. }
  537. s->dsound_capture = NULL;
  538. g_free(s);
  539. }
  540. static void *dsound_audio_init(Audiodev *dev, Error **errp)
  541. {
  542. int err;
  543. HRESULT hr;
  544. dsound *s = g_new0(dsound, 1);
  545. AudiodevDsoundOptions *dso;
  546. assert(dev->driver == AUDIODEV_DRIVER_DSOUND);
  547. s->dev = dev;
  548. dso = &dev->u.dsound;
  549. if (!dso->has_latency) {
  550. dso->has_latency = true;
  551. dso->latency = 10000; /* 10 ms */
  552. }
  553. hr = CoInitialize (NULL);
  554. if (FAILED (hr)) {
  555. dsound_logerr (hr, "Could not initialize COM\n");
  556. g_free(s);
  557. return NULL;
  558. }
  559. hr = CoCreateInstance (
  560. &CLSID_DirectSound,
  561. NULL,
  562. CLSCTX_ALL,
  563. &IID_IDirectSound,
  564. (void **) &s->dsound
  565. );
  566. if (FAILED (hr)) {
  567. dsound_logerr (hr, "Could not create DirectSound instance\n");
  568. g_free(s);
  569. return NULL;
  570. }
  571. hr = IDirectSound_Initialize (s->dsound, NULL);
  572. if (FAILED (hr)) {
  573. dsound_logerr (hr, "Could not initialize DirectSound\n");
  574. hr = IDirectSound_Release (s->dsound);
  575. if (FAILED (hr)) {
  576. dsound_logerr (hr, "Could not release DirectSound\n");
  577. }
  578. g_free(s);
  579. return NULL;
  580. }
  581. hr = CoCreateInstance (
  582. &CLSID_DirectSoundCapture,
  583. NULL,
  584. CLSCTX_ALL,
  585. &IID_IDirectSoundCapture,
  586. (void **) &s->dsound_capture
  587. );
  588. if (FAILED (hr)) {
  589. dsound_logerr (hr, "Could not create DirectSoundCapture instance\n");
  590. } else {
  591. hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL);
  592. if (FAILED (hr)) {
  593. dsound_logerr (hr, "Could not initialize DirectSoundCapture\n");
  594. hr = IDirectSoundCapture_Release (s->dsound_capture);
  595. if (FAILED (hr)) {
  596. dsound_logerr (hr, "Could not release DirectSoundCapture\n");
  597. }
  598. s->dsound_capture = NULL;
  599. }
  600. }
  601. err = dsound_set_cooperative_level(s);
  602. if (err) {
  603. dsound_audio_fini (s);
  604. return NULL;
  605. }
  606. return s;
  607. }
  608. static struct audio_pcm_ops dsound_pcm_ops = {
  609. .init_out = dsound_init_out,
  610. .fini_out = dsound_fini_out,
  611. .write = audio_generic_write,
  612. .buffer_get_free = dsound_buffer_get_free,
  613. .get_buffer_out = dsound_get_buffer_out,
  614. .put_buffer_out = dsound_put_buffer_out,
  615. .enable_out = dsound_enable_out,
  616. .init_in = dsound_init_in,
  617. .fini_in = dsound_fini_in,
  618. .read = audio_generic_read,
  619. .get_buffer_in = dsound_get_buffer_in,
  620. .put_buffer_in = dsound_put_buffer_in,
  621. .enable_in = dsound_enable_in,
  622. };
  623. static struct audio_driver dsound_audio_driver = {
  624. .name = "dsound",
  625. .descr = "DirectSound http://wikipedia.org/wiki/DirectSound",
  626. .init = dsound_audio_init,
  627. .fini = dsound_audio_fini,
  628. .pcm_ops = &dsound_pcm_ops,
  629. .max_voices_out = INT_MAX,
  630. .max_voices_in = 1,
  631. .voice_size_out = sizeof (DSoundVoiceOut),
  632. .voice_size_in = sizeof (DSoundVoiceIn)
  633. };
  634. static void register_audio_dsound(void)
  635. {
  636. audio_driver_register(&dsound_audio_driver);
  637. }
  638. type_init(register_audio_dsound);