18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU Audio subsystem header
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2005 Vassili Karpov (malc)
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NAME "playback"
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define HWBUF hw->mix_buf
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TYPE out
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define HW HWVoiceOut
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SW SWVoiceOut
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NAME "capture"
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TYPE in
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define HW HWVoiceIn
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SW SWVoiceIn
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define HWBUF hw->conv_buf
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void glue (audio_init_nb_voices_, TYPE) (struct audio_driver *drv)
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AudioState *s = &glob_audio_state;
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int max_voices = glue (drv->max_voices_, TYPE);
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int voice_size = glue (drv->voice_size_, TYPE);
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!max_voices) {
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("Driver `%s' does not support " NAME "\n", drv->name);
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n",
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   drv->name,
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   glue (s->nb_hw_voices_, TYPE),
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   max_voices);
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        glue (s->nb_hw_voices_, TYPE) = max_voices;
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (audio_bug (AUDIO_FUNC, !voice_size && max_voices)) {
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("drv=`%s' voice_size=0 max_voices=%d\n",
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               drv->name, max_voices);
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        glue (s->nb_hw_voices_, TYPE) = 0;
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (audio_bug (AUDIO_FUNC, voice_size && !max_voices)) {
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("drv=`%s' voice_size=%d max_voices=0\n",
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               drv->name, voice_size);
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (HWBUF) {
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free (HWBUF);
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWBUF = NULL;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int glue (audio_pcm_hw_alloc_resources_, TYPE) (HW *hw)
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    HWBUF = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (struct st_sample));
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!HWBUF) {
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Could not allocate " NAME " buffer (%d samples)\n",
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               hw->samples);
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sw->buf) {
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free (sw->buf);
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sw->rate) {
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        st_rate_stop (sw->rate);
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->buf = NULL;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->rate = NULL;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int samples;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    samples = sw->hw->samples;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sw->buf = audio_calloc (AUDIO_FUNC, samples, sizeof (struct st_sample));
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!sw->buf) {
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Could not allocate buffer for `%s' (%d samples)\n",
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               SW_NAME (sw), samples);
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!sw->rate) {
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free (sw->buf);
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sw->buf = NULL;
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int glue (audio_pcm_sw_init_, TYPE) (
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SW *sw,
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HW *hw,
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *name,
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings *as
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    )
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audio_pcm_init_info (&sw->info, as);
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->hw = hw;
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->active = 0;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->total_hw_samples_mixed = 0;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->empty = 1;
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->conv = mixeng_conv
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->clip = mixeng_clip
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        [sw->info.nchannels == 2]
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        [sw->info.sign]
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        [sw->info.swap_endianness]
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        [audio_bits_to_index (sw->info.bits)];
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw->name = qemu_strdup (name);
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free (sw->name);
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sw->name = NULL;
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return err;
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    glue (audio_pcm_sw_free_resources_, TYPE) (sw);
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sw->name) {
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free (sw->name);
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sw->name = NULL;
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
187a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_INSERT_HEAD (&hw->sw_head, sw, entries);
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
192a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_REMOVE (sw, entries);
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AudioState *s = &glob_audio_state;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HW *hw = *hwp;
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!hw->sw_head.lh_first) {
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        audio_detach_capture (hw);
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
204a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        QLIST_REMOVE (hw, entries);
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        glue (s->nb_hw_voices_, TYPE) += 1;
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BEGIN_NOSIGALRM
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        glue (hw->pcm_ops->fini_, TYPE) (hw);
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        END_NOSIGALRM
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free (hw);
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *hwp = NULL;
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic HW *glue (audio_pcm_hw_find_any_, TYPE) (HW *hw)
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AudioState *s = &glob_audio_state;
2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first;
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (HW *hw)
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (hw->enabled) {
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return hw;
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic HW *glue (audio_pcm_hw_find_specific_, TYPE) (
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HW *hw,
2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings *as
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    )
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (audio_pcm_info_eq (&hw->info, as)) {
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return hw;
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic HW *glue (audio_pcm_hw_add_new_, TYPE) (struct audsettings *as)
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HW *hw;
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AudioState *s = &glob_audio_state;
2485d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    struct audio_driver *drv = s->drv;
2495d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int err;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!glue (s->nb_hw_voices_, TYPE)) {
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (audio_bug (AUDIO_FUNC, !drv)) {
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("No host audio driver\n");
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (audio_bug (AUDIO_FUNC, !drv->pcm_ops)) {
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Host audio driver without pcm_ops\n");
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE));
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!hw) {
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Can not allocate voice `%s' size %d\n",
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               drv->name, glue (drv->voice_size_, TYPE));
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->pcm_ops = drv->pcm_ops;
273a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_INIT (&hw->sw_head);
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
275a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_INIT (&hw->cap_head);
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BEGIN_NOSIGALRM
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = glue (hw->pcm_ops->init_, TYPE) (hw, as);
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    END_NOSIGALRM
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err)
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err0;
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) {
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("hw->samples=%d\n", hw->samples);
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err1;
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->clip = mixeng_clip
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->conv = mixeng_conv
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        [hw->info.nchannels == 2]
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        [hw->info.sign]
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        [hw->info.swap_endianness]
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        [audio_bits_to_index (hw->info.bits)];
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err1;
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
302a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    glue (s->nb_hw_voices_, TYPE) -= 1;
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    audio_attach_capture (hw);
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return hw;
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project err1:
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BEGIN_NOSIGALRM
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    glue (hw->pcm_ops->fini_, TYPE) (hw);
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    END_NOSIGALRM
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project err0:
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_free (hw);
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic HW *glue (audio_pcm_hw_add_, TYPE) (struct audsettings *as)
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HW *hw;
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (glue (conf.fixed_, TYPE).enabled && glue (conf.fixed_, TYPE).greedy) {
3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (hw) {
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return hw;
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hw = glue (audio_pcm_hw_find_specific_, TYPE) (NULL, as);
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hw) {
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return hw;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hw) {
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return hw;
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return glue (audio_pcm_hw_find_any_, TYPE) (NULL);
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SW *glue (audio_pcm_create_voice_pair_, TYPE) (
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *sw_name,
3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings *as
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    )
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SW *sw;
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HW *hw;
3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings hw_as;
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (glue (conf.fixed_, TYPE).enabled) {
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw_as = glue (conf.fixed_, TYPE).settings;
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw_as = *as;
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sw = audio_calloc (AUDIO_FUNC, 1, sizeof (*sw));
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!sw) {
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sw_name ? sw_name : "unknown", sizeof (*sw));
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err1;
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hw = glue (audio_pcm_hw_add_, TYPE) (&hw_as);
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!hw) {
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err2;
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err3;
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return sw;
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecterr3:
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    glue (audio_pcm_hw_del_sw_, TYPE) (sw);
3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    glue (audio_pcm_hw_gc_, TYPE) (&hw);
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecterr2:
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_free (sw);
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecterr1:
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void glue (audio_close_, TYPE) (SW *sw)
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    glue (audio_pcm_sw_fini_, TYPE) (sw);
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    glue (audio_pcm_hw_del_sw_, TYPE) (sw);
3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    glue (audio_pcm_hw_gc_, TYPE) (&sw->hw);
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_free (sw);
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sw) {
3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (audio_bug (AUDIO_FUNC, !card)) {
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            dolog ("card=%p\n", card);
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        glue (audio_close_, TYPE) (sw);
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSW *glue (AUD_open_, TYPE) (
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QEMUSoundCard *card,
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SW *sw,
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *name,
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *callback_opaque ,
412a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    audio_callback_fn callback_fn,
4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings *as
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    )
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AudioState *s = &glob_audio_state;
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int live = 0;
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SW *old_sw = NULL;
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            name, as->freq, as->nchannels, as->fmt);
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (audio_bug (AUDIO_FUNC, !card || !name || !callback_fn || !as)) {
4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        dolog ("card=%p name=%p callback_fn=%p as=%p\n",
4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               card, name, callback_fn, as);
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto fail;
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) {
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        audio_print_settings (as);
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto fail;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4365d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    if (audio_bug (AUDIO_FUNC, !s->drv)) {
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Can not open `%s' (no host audio driver)\n", name);
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto fail;
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sw && audio_pcm_info_eq (&sw->info, as)) {
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return sw;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (conf.plive && sw && (!sw->active && !sw->empty)) {
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        live = sw->total_hw_samples_mixed;
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_PLIVE
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Replacing voice %s with %d live samples\n", SW_NAME (sw), live);
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Old %s freq %d, bits %d, channels %d\n",
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               SW_NAME (sw), sw->info.freq, sw->info.bits, sw->info.nchannels);
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("New %s freq %d, bits %d, channels %d\n",
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               name,
4555d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner               as->freq,
4565d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner               (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) ? 16 : 8,
4575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner               as->nchannels);
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (live) {
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            old_sw = sw;
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            old_sw->callback.fn = NULL;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sw = NULL;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!glue (conf.fixed_, TYPE).enabled && sw) {
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        glue (AUD_close_, TYPE) (card, sw);
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sw = NULL;
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sw) {
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        HW *hw = sw->hw;
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!hw) {
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("Internal logic error voice `%s' has no hardware store\n",
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   SW_NAME (sw));
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto fail;
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        glue (audio_pcm_sw_fini_, TYPE) (sw);
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto fail;
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sw = glue (audio_pcm_create_voice_pair_, TYPE) (name, as);
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!sw) {
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("Failed to create voice `%s'\n", name);
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return NULL;
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
495a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    sw->card = card;
496a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    sw->vol = nominal_volume;
497a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    sw->callback.fn = callback_fn;
498a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    sw->callback.opaque = callback_opaque;
4995164d3c53f57dfb468ab11136358b6e3b6cf0513David 'Digit' Turner#ifdef DAC
5005164d3c53f57dfb468ab11136358b6e3b6cf0513David 'Digit' Turner    sw->empty = 1;
5015164d3c53f57dfb468ab11136358b6e3b6cf0513David 'Digit' Turner#endif
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DAC
504a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    if (live) {
505a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        int mixed =
506a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner            (live << old_sw->info.shift)
507a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner            * old_sw->info.bytes_per_second
508a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner            / sw->info.bytes_per_second;
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_PLIVE
511a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        dolog ("Silence will be mixed %d\n", mixed);
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
513a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        sw->total_hw_samples_mixed += mixed;
514a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    }
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_AUDIO
518a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    dolog ("%s\n", name);
519a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    audio_pcm_print_info ("hw", &sw->hw->info);
520a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    audio_pcm_print_info ("sw", &sw->info);
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return sw;
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fail:
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    glue (AUD_close_, TYPE) (card, sw);
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint glue (AUD_is_active_, TYPE) (SW *sw)
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return sw ? sw->active : 0;
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!sw) {
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->old_ts = sw->hw->ts_helper;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint64_t delta, cur_ts, old_ts;
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!sw) {
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cur_ts = sw->hw->ts_helper;
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    old_ts = ts->old_ts;
5545d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    /* dolog ("cur %" PRId64 " old %" PRId64 "\n", cur_ts, old_ts); */
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur_ts >= old_ts) {
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        delta = cur_ts - old_ts;
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        delta = UINT64_MAX - old_ts + cur_ts;
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!delta) {
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
567a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    return muldiv64 (delta, sw->hw->info.freq, 1000000);
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef TYPE
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef HW
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef SW
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef HWBUF
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef NAME
575