xref: /openbmc/qemu/audio/dsound_template.h (revision 825a215c003cd028e26c7d19aa5049d957345f43)
11d14ffa9Sbellard /*
21d14ffa9Sbellard  * QEMU DirectSound audio driver header
31d14ffa9Sbellard  *
41d14ffa9Sbellard  * Copyright (c) 2005 Vassili Karpov (malc)
51d14ffa9Sbellard  *
61d14ffa9Sbellard  * Permission is hereby granted, free of charge, to any person obtaining a copy
71d14ffa9Sbellard  * of this software and associated documentation files (the "Software"), to deal
81d14ffa9Sbellard  * in the Software without restriction, including without limitation the rights
91d14ffa9Sbellard  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
101d14ffa9Sbellard  * copies of the Software, and to permit persons to whom the Software is
111d14ffa9Sbellard  * furnished to do so, subject to the following conditions:
121d14ffa9Sbellard  *
131d14ffa9Sbellard  * The above copyright notice and this permission notice shall be included in
141d14ffa9Sbellard  * all copies or substantial portions of the Software.
151d14ffa9Sbellard  *
161d14ffa9Sbellard  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171d14ffa9Sbellard  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181d14ffa9Sbellard  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
191d14ffa9Sbellard  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
201d14ffa9Sbellard  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
211d14ffa9Sbellard  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
221d14ffa9Sbellard  * THE SOFTWARE.
231d14ffa9Sbellard  */
241d14ffa9Sbellard #ifdef DSBTYPE_IN
251d14ffa9Sbellard #define NAME "capture buffer"
26ca9cc28cSbalrog #define NAME2 "DirectSoundCapture"
271d14ffa9Sbellard #define TYPE in
281d14ffa9Sbellard #define IFACE IDirectSoundCaptureBuffer
291d14ffa9Sbellard #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
301d14ffa9Sbellard #define FIELD dsound_capture_buffer
31ca9cc28cSbalrog #define FIELD2 dsound_capture
327fa9754aSKővágó, Zoltán #define HWVOICE HWVoiceIn
337fa9754aSKővágó, Zoltán #define DSOUNDVOICE DSoundVoiceIn
341d14ffa9Sbellard #else
351d14ffa9Sbellard #define NAME "playback buffer"
36ca9cc28cSbalrog #define NAME2 "DirectSound"
371d14ffa9Sbellard #define TYPE out
381d14ffa9Sbellard #define IFACE IDirectSoundBuffer
391d14ffa9Sbellard #define BUFPTR LPDIRECTSOUNDBUFFER
401d14ffa9Sbellard #define FIELD dsound_buffer
41ca9cc28cSbalrog #define FIELD2 dsound
427fa9754aSKővágó, Zoltán #define HWVOICE HWVoiceOut
437fa9754aSKővágó, Zoltán #define DSOUNDVOICE DSoundVoiceOut
441d14ffa9Sbellard #endif
451d14ffa9Sbellard 
glue(dsound_unlock_,TYPE)461d14ffa9Sbellard static int glue (dsound_unlock_, TYPE) (
471d14ffa9Sbellard     BUFPTR buf,
481d14ffa9Sbellard     LPVOID p1,
491d14ffa9Sbellard     LPVOID p2,
501d14ffa9Sbellard     DWORD blen1,
511d14ffa9Sbellard     DWORD blen2
521d14ffa9Sbellard     )
531d14ffa9Sbellard {
541d14ffa9Sbellard     HRESULT hr;
551d14ffa9Sbellard 
561d14ffa9Sbellard     hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
571d14ffa9Sbellard     if (FAILED (hr)) {
58c0fe3827Sbellard         dsound_logerr (hr, "Could not unlock " NAME "\n");
591d14ffa9Sbellard         return -1;
601d14ffa9Sbellard     }
611d14ffa9Sbellard 
621d14ffa9Sbellard     return 0;
631d14ffa9Sbellard }
641d14ffa9Sbellard 
glue(dsound_lock_,TYPE)651d14ffa9Sbellard static int glue (dsound_lock_, TYPE) (
661d14ffa9Sbellard     BUFPTR buf,
671d14ffa9Sbellard     struct audio_pcm_info *info,
681d14ffa9Sbellard     DWORD pos,
691d14ffa9Sbellard     DWORD len,
701d14ffa9Sbellard     LPVOID *p1p,
711d14ffa9Sbellard     LPVOID *p2p,
721d14ffa9Sbellard     DWORD *blen1p,
731d14ffa9Sbellard     DWORD *blen2p,
74191e1f0aSKővágó, Zoltán     int entire,
75191e1f0aSKővágó, Zoltán     dsound *s
761d14ffa9Sbellard     )
771d14ffa9Sbellard {
781d14ffa9Sbellard     HRESULT hr;
798ead62cfSbellard     DWORD flag;
801d14ffa9Sbellard 
818ead62cfSbellard #ifdef DSBTYPE_IN
828ead62cfSbellard     flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
838ead62cfSbellard #else
848ead62cfSbellard     flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
858ead62cfSbellard #endif
867fa9754aSKővágó, Zoltán     hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag);
871d14ffa9Sbellard 
881d14ffa9Sbellard     if (FAILED (hr)) {
891d14ffa9Sbellard #ifndef DSBTYPE_IN
901d14ffa9Sbellard         if (hr == DSERR_BUFFERLOST) {
91191e1f0aSKővágó, Zoltán             if (glue (dsound_restore_, TYPE) (buf, s)) {
92c0fe3827Sbellard                 dsound_logerr (hr, "Could not lock " NAME "\n");
931d14ffa9Sbellard             }
942762955fSKővágó, Zoltán             goto fail;
951d14ffa9Sbellard         }
961d14ffa9Sbellard #endif
97c0fe3827Sbellard         dsound_logerr (hr, "Could not lock " NAME "\n");
981d14ffa9Sbellard         goto fail;
991d14ffa9Sbellard     }
1001d14ffa9Sbellard 
1012b9cce8cSKővágó, Zoltán     if ((p1p && *p1p && (*blen1p % info->bytes_per_frame)) ||
1022b9cce8cSKővágó, Zoltán         (p2p && *p2p && (*blen2p % info->bytes_per_frame))) {
1031d14ffa9Sbellard         dolog("DirectSound returned misaligned buffer %ld %ld\n",
1047fa9754aSKővágó, Zoltán               *blen1p, *blen2p);
1057fa9754aSKővágó, Zoltán         glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p,
1067fa9754aSKővágó, Zoltán                                    blen2p ? *blen2p : 0);
1071d14ffa9Sbellard         goto fail;
1081d14ffa9Sbellard     }
1091d14ffa9Sbellard 
1107fa9754aSKővágó, Zoltán     if (p1p && !*p1p && *blen1p) {
1117fa9754aSKővágó, Zoltán         dolog("warning: !p1 && blen1=%ld\n", *blen1p);
1127fa9754aSKővágó, Zoltán         *blen1p = 0;
1131d14ffa9Sbellard     }
1141d14ffa9Sbellard 
1157fa9754aSKővágó, Zoltán     if (p2p && !*p2p && *blen2p) {
1167fa9754aSKővágó, Zoltán         dolog("warning: !p2 && blen2=%ld\n", *blen2p);
1177fa9754aSKővágó, Zoltán         *blen2p = 0;
1181d14ffa9Sbellard     }
1191d14ffa9Sbellard 
1201d14ffa9Sbellard     return 0;
1211d14ffa9Sbellard 
1221d14ffa9Sbellard  fail:
1231d14ffa9Sbellard     *p1p = NULL - 1;
1241d14ffa9Sbellard     *blen1p = -1;
1257fa9754aSKővágó, Zoltán     if (p2p) {
1267fa9754aSKővágó, Zoltán         *p2p = NULL - 1;
1271d14ffa9Sbellard         *blen2p = -1;
1287fa9754aSKővágó, Zoltán     }
1291d14ffa9Sbellard     return -1;
1301d14ffa9Sbellard }
1311d14ffa9Sbellard 
1321d14ffa9Sbellard #ifdef DSBTYPE_IN
dsound_fini_in(HWVoiceIn * hw)1331d14ffa9Sbellard static void dsound_fini_in (HWVoiceIn *hw)
1341d14ffa9Sbellard #else
1351d14ffa9Sbellard static void dsound_fini_out (HWVoiceOut *hw)
1361d14ffa9Sbellard #endif
1371d14ffa9Sbellard {
1381d14ffa9Sbellard     HRESULT hr;
1391d14ffa9Sbellard #ifdef DSBTYPE_IN
1401d14ffa9Sbellard     DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
1411d14ffa9Sbellard #else
1421d14ffa9Sbellard     DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
1431d14ffa9Sbellard #endif
1441d14ffa9Sbellard 
1451d14ffa9Sbellard     if (ds->FIELD) {
1461d14ffa9Sbellard         hr = glue (IFACE, _Stop) (ds->FIELD);
1471d14ffa9Sbellard         if (FAILED (hr)) {
148c0fe3827Sbellard             dsound_logerr (hr, "Could not stop " NAME "\n");
1491d14ffa9Sbellard         }
1501d14ffa9Sbellard 
1511d14ffa9Sbellard         hr = glue (IFACE, _Release) (ds->FIELD);
1521d14ffa9Sbellard         if (FAILED (hr)) {
153c0fe3827Sbellard             dsound_logerr (hr, "Could not release " NAME "\n");
1541d14ffa9Sbellard         }
1551d14ffa9Sbellard         ds->FIELD = NULL;
1561d14ffa9Sbellard     }
1571d14ffa9Sbellard }
1581d14ffa9Sbellard 
1591d14ffa9Sbellard #ifdef DSBTYPE_IN
dsound_init_in(HWVoiceIn * hw,struct audsettings * as,void * drv_opaque)1605706db1dSKővágó, Zoltán static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as,
1615706db1dSKővágó, Zoltán                           void *drv_opaque)
1621d14ffa9Sbellard #else
1635706db1dSKővágó, Zoltán static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
1645706db1dSKővágó, Zoltán                            void *drv_opaque)
1651d14ffa9Sbellard #endif
1661d14ffa9Sbellard {
1671d14ffa9Sbellard     int err;
1681d14ffa9Sbellard     HRESULT hr;
169191e1f0aSKővágó, Zoltán     dsound *s = drv_opaque;
1701d14ffa9Sbellard     WAVEFORMATEX wfx;
1711ea879e5Smalc     struct audsettings obt_as;
1721d14ffa9Sbellard #ifdef DSBTYPE_IN
1731d14ffa9Sbellard     const char *typ = "ADC";
1741d14ffa9Sbellard     DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
1751d14ffa9Sbellard     DSCBUFFERDESC bd;
1761d14ffa9Sbellard     DSCBCAPS bc;
1774a3b8b34SKővágó, Zoltán     AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.in;
1781d14ffa9Sbellard #else
1791d14ffa9Sbellard     const char *typ = "DAC";
1801d14ffa9Sbellard     DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
1811d14ffa9Sbellard     DSBUFFERDESC bd;
1821d14ffa9Sbellard     DSBCAPS bc;
1834a3b8b34SKővágó, Zoltán     AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.out;
1841d14ffa9Sbellard #endif
1851d14ffa9Sbellard 
186ca9cc28cSbalrog     if (!s->FIELD2) {
18726463dbcSbalrog         dolog ("Attempt to initialize voice without " NAME2 " object\n");
188ca9cc28cSbalrog         return -1;
189ca9cc28cSbalrog     }
190ca9cc28cSbalrog 
191c0fe3827Sbellard     err = waveformat_from_audio_settings (&wfx, as);
1921d14ffa9Sbellard     if (err) {
1931d14ffa9Sbellard         return -1;
1941d14ffa9Sbellard     }
1951d14ffa9Sbellard 
1961d14ffa9Sbellard     memset (&bd, 0, sizeof (bd));
1971d14ffa9Sbellard     bd.dwSize = sizeof (bd);
1981d14ffa9Sbellard     bd.lpwfxFormat = &wfx;
1994a3b8b34SKővágó, Zoltán     bd.dwBufferBytes = audio_buffer_bytes(pdo, as, 92880);
2001d14ffa9Sbellard #ifdef DSBTYPE_IN
2011d14ffa9Sbellard     hr = IDirectSoundCapture_CreateCaptureBuffer (
2021d14ffa9Sbellard         s->dsound_capture,
2031d14ffa9Sbellard         &bd,
2041d14ffa9Sbellard         &ds->dsound_capture_buffer,
2051d14ffa9Sbellard         NULL
2061d14ffa9Sbellard         );
2071d14ffa9Sbellard #else
208*401dcf05SVolker Rümelin     bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
2091d14ffa9Sbellard     hr = IDirectSound_CreateSoundBuffer (
2101d14ffa9Sbellard         s->dsound,
2111d14ffa9Sbellard         &bd,
2121d14ffa9Sbellard         &ds->dsound_buffer,
2131d14ffa9Sbellard         NULL
2141d14ffa9Sbellard         );
2151d14ffa9Sbellard #endif
2161d14ffa9Sbellard 
2171d14ffa9Sbellard     if (FAILED (hr)) {
218c0fe3827Sbellard         dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
2191d14ffa9Sbellard         return -1;
2201d14ffa9Sbellard     }
2211d14ffa9Sbellard 
222c0fe3827Sbellard     hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
2231d14ffa9Sbellard     if (FAILED (hr)) {
224c0fe3827Sbellard         dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
2251d14ffa9Sbellard         goto fail0;
2261d14ffa9Sbellard     }
2271d14ffa9Sbellard 
2281d14ffa9Sbellard #ifdef DEBUG_DSOUND
2291d14ffa9Sbellard     dolog (NAME "\n");
2301d14ffa9Sbellard     print_wave_format (&wfx);
2311d14ffa9Sbellard #endif
2321d14ffa9Sbellard 
2331d14ffa9Sbellard     memset (&bc, 0, sizeof (bc));
2341d14ffa9Sbellard     bc.dwSize = sizeof (bc);
2351d14ffa9Sbellard 
2361d14ffa9Sbellard     hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
2371d14ffa9Sbellard     if (FAILED (hr)) {
238c0fe3827Sbellard         dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
2391d14ffa9Sbellard         goto fail0;
2401d14ffa9Sbellard     }
2411d14ffa9Sbellard 
242c0fe3827Sbellard     err = waveformat_to_audio_settings (&wfx, &obt_as);
2431d14ffa9Sbellard     if (err) {
2441d14ffa9Sbellard         goto fail0;
2451d14ffa9Sbellard     }
2461d14ffa9Sbellard 
247fb35c2ceSKővágó, Zoltán     ds->first_time = true;
248d929eba5Sbellard     obt_as.endianness = 0;
249d929eba5Sbellard     audio_pcm_init_info (&hw->info, &obt_as);
250c0fe3827Sbellard 
2512b9cce8cSKővágó, Zoltán     if (bc.dwBufferBytes % hw->info.bytes_per_frame) {
252c0fe3827Sbellard         dolog (
253c0fe3827Sbellard             "GetCaps returned misaligned buffer size %ld, alignment %d\n",
2542b9cce8cSKővágó, Zoltán             bc.dwBufferBytes, hw->info.bytes_per_frame
2551d14ffa9Sbellard             );
256c0fe3827Sbellard     }
2577fa9754aSKővágó, Zoltán     hw->size_emul = bc.dwBufferBytes;
2582b9cce8cSKővágó, Zoltán     hw->samples = bc.dwBufferBytes / hw->info.bytes_per_frame;
259191e1f0aSKővágó, Zoltán     ds->s = s;
2601d14ffa9Sbellard 
2611d14ffa9Sbellard #ifdef DEBUG_DSOUND
2621d14ffa9Sbellard     dolog ("caps %ld, desc %ld\n",
2631d14ffa9Sbellard            bc.dwBufferBytes, bd.dwBufferBytes);
2641d14ffa9Sbellard #endif
2651d14ffa9Sbellard     return 0;
2661d14ffa9Sbellard 
2671d14ffa9Sbellard  fail0:
2681d14ffa9Sbellard     glue (dsound_fini_, TYPE) (hw);
2691d14ffa9Sbellard     return -1;
2701d14ffa9Sbellard }
2711d14ffa9Sbellard 
2721d14ffa9Sbellard #undef NAME
273832e9079Smalc #undef NAME2
2741d14ffa9Sbellard #undef TYPE
2751d14ffa9Sbellard #undef IFACE
2761d14ffa9Sbellard #undef BUFPTR
2771d14ffa9Sbellard #undef FIELD
278832e9079Smalc #undef FIELD2
2797fa9754aSKővágó, Zoltán #undef HWVOICE
2807fa9754aSKővágó, Zoltán #undef DSOUNDVOICE
281