qemu/audio/paaudio.c
<<
>>
Prefs
   1/* public domain */
   2#include "qemu/osdep.h"
   3#include "qemu-common.h"
   4#include "audio.h"
   5#include "qapi/opts-visitor.h"
   6
   7#include <pulse/pulseaudio.h>
   8
   9#define AUDIO_CAP "pulseaudio"
  10#include "audio_int.h"
  11#include "audio_pt_int.h"
  12
  13typedef struct {
  14    Audiodev *dev;
  15    pa_threaded_mainloop *mainloop;
  16    pa_context *context;
  17} paaudio;
  18
  19typedef struct {
  20    HWVoiceOut hw;
  21    int done;
  22    int live;
  23    int decr;
  24    int rpos;
  25    pa_stream *stream;
  26    void *pcm_buf;
  27    struct audio_pt pt;
  28    paaudio *g;
  29    int samples;
  30} PAVoiceOut;
  31
  32typedef struct {
  33    HWVoiceIn hw;
  34    int done;
  35    int dead;
  36    int incr;
  37    int wpos;
  38    pa_stream *stream;
  39    void *pcm_buf;
  40    struct audio_pt pt;
  41    const void *read_data;
  42    size_t read_index, read_length;
  43    paaudio *g;
  44    int samples;
  45} PAVoiceIn;
  46
  47static void qpa_audio_fini(void *opaque);
  48
  49static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...)
  50{
  51    va_list ap;
  52
  53    va_start (ap, fmt);
  54    AUD_vlog (AUDIO_CAP, fmt, ap);
  55    va_end (ap);
  56
  57    AUD_log (AUDIO_CAP, "Reason: %s\n", pa_strerror (err));
  58}
  59
  60#ifndef PA_CONTEXT_IS_GOOD
  61static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x)
  62{
  63    return
  64        x == PA_CONTEXT_CONNECTING ||
  65        x == PA_CONTEXT_AUTHORIZING ||
  66        x == PA_CONTEXT_SETTING_NAME ||
  67        x == PA_CONTEXT_READY;
  68}
  69#endif
  70
  71#ifndef PA_STREAM_IS_GOOD
  72static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
  73{
  74    return
  75        x == PA_STREAM_CREATING ||
  76        x == PA_STREAM_READY;
  77}
  78#endif
  79
  80#define CHECK_SUCCESS_GOTO(c, rerror, expression, label)        \
  81    do {                                                        \
  82        if (!(expression)) {                                    \
  83            if (rerror) {                                       \
  84                *(rerror) = pa_context_errno ((c)->context);    \
  85            }                                                   \
  86            goto label;                                         \
  87        }                                                       \
  88    } while (0)
  89
  90#define CHECK_DEAD_GOTO(c, stream, rerror, label)                       \
  91    do {                                                                \
  92        if (!(c)->context || !PA_CONTEXT_IS_GOOD (pa_context_get_state((c)->context)) || \
  93            !(stream) || !PA_STREAM_IS_GOOD (pa_stream_get_state ((stream)))) { \
  94            if (((c)->context && pa_context_get_state ((c)->context) == PA_CONTEXT_FAILED) || \
  95                ((stream) && pa_stream_get_state ((stream)) == PA_STREAM_FAILED)) { \
  96                if (rerror) {                                           \
  97                    *(rerror) = pa_context_errno ((c)->context);        \
  98                }                                                       \
  99            } else {                                                    \
 100                if (rerror) {                                           \
 101                    *(rerror) = PA_ERR_BADSTATE;                        \
 102                }                                                       \
 103            }                                                           \
 104            goto label;                                                 \
 105        }                                                               \
 106    } while (0)
 107
 108static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror)
 109{
 110    paaudio *g = p->g;
 111
 112    pa_threaded_mainloop_lock (g->mainloop);
 113
 114    CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail);
 115
 116    while (length > 0) {
 117        size_t l;
 118
 119        while (!p->read_data) {
 120            int r;
 121
 122            r = pa_stream_peek (p->stream, &p->read_data, &p->read_length);
 123            CHECK_SUCCESS_GOTO (g, rerror, r == 0, unlock_and_fail);
 124
 125            if (!p->read_data) {
 126                pa_threaded_mainloop_wait (g->mainloop);
 127                CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail);
 128            } else {
 129                p->read_index = 0;
 130            }
 131        }
 132
 133        l = p->read_length < length ? p->read_length : length;
 134        memcpy (data, (const uint8_t *) p->read_data+p->read_index, l);
 135
 136        data = (uint8_t *) data + l;
 137        length -= l;
 138
 139        p->read_index += l;
 140        p->read_length -= l;
 141
 142        if (!p->read_length) {
 143            int r;
 144
 145            r = pa_stream_drop (p->stream);
 146            p->read_data = NULL;
 147            p->read_length = 0;
 148            p->read_index = 0;
 149
 150            CHECK_SUCCESS_GOTO (g, rerror, r == 0, unlock_and_fail);
 151        }
 152    }
 153
 154    pa_threaded_mainloop_unlock (g->mainloop);
 155    return 0;
 156
 157unlock_and_fail:
 158    pa_threaded_mainloop_unlock (g->mainloop);
 159    return -1;
 160}
 161
 162static int qpa_simple_write (PAVoiceOut *p, const void *data, size_t length, int *rerror)
 163{
 164    paaudio *g = p->g;
 165
 166    pa_threaded_mainloop_lock (g->mainloop);
 167
 168    CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail);
 169
 170    while (length > 0) {
 171        size_t l;
 172        int r;
 173
 174        while (!(l = pa_stream_writable_size (p->stream))) {
 175            pa_threaded_mainloop_wait (g->mainloop);
 176            CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail);
 177        }
 178
 179        CHECK_SUCCESS_GOTO (g, rerror, l != (size_t) -1, unlock_and_fail);
 180
 181        if (l > length) {
 182            l = length;
 183        }
 184
 185        r = pa_stream_write (p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
 186        CHECK_SUCCESS_GOTO (g, rerror, r >= 0, unlock_and_fail);
 187
 188        data = (const uint8_t *) data + l;
 189        length -= l;
 190    }
 191
 192    pa_threaded_mainloop_unlock (g->mainloop);
 193    return 0;
 194
 195unlock_and_fail:
 196    pa_threaded_mainloop_unlock (g->mainloop);
 197    return -1;
 198}
 199
 200static void *qpa_thread_out (void *arg)
 201{
 202    PAVoiceOut *pa = arg;
 203    HWVoiceOut *hw = &pa->hw;
 204
 205    if (audio_pt_lock(&pa->pt, __func__)) {
 206        return NULL;
 207    }
 208
 209    for (;;) {
 210        int decr, to_mix, rpos;
 211
 212        for (;;) {
 213            if (pa->done) {
 214                goto exit;
 215            }
 216
 217            if (pa->live > 0) {
 218                break;
 219            }
 220
 221            if (audio_pt_wait(&pa->pt, __func__)) {
 222                goto exit;
 223            }
 224        }
 225
 226        decr = to_mix = audio_MIN(pa->live, pa->samples >> 5);
 227        rpos = pa->rpos;
 228
 229        if (audio_pt_unlock(&pa->pt, __func__)) {
 230            return NULL;
 231        }
 232
 233        while (to_mix) {
 234            int error;
 235            int chunk = audio_MIN (to_mix, hw->samples - rpos);
 236            struct st_sample *src = hw->mix_buf + rpos;
 237
 238            hw->clip (pa->pcm_buf, src, chunk);
 239
 240            if (qpa_simple_write (pa, pa->pcm_buf,
 241                                  chunk << hw->info.shift, &error) < 0) {
 242                qpa_logerr (error, "pa_simple_write failed\n");
 243                return NULL;
 244            }
 245
 246            rpos = (rpos + chunk) % hw->samples;
 247            to_mix -= chunk;
 248        }
 249
 250        if (audio_pt_lock(&pa->pt, __func__)) {
 251            return NULL;
 252        }
 253
 254        pa->rpos = rpos;
 255        pa->live -= decr;
 256        pa->decr += decr;
 257    }
 258
 259 exit:
 260    audio_pt_unlock(&pa->pt, __func__);
 261    return NULL;
 262}
 263
 264static int qpa_run_out (HWVoiceOut *hw, int live)
 265{
 266    int decr;
 267    PAVoiceOut *pa = (PAVoiceOut *) hw;
 268
 269    if (audio_pt_lock(&pa->pt, __func__)) {
 270        return 0;
 271    }
 272
 273    decr = audio_MIN (live, pa->decr);
 274    pa->decr -= decr;
 275    pa->live = live - decr;
 276    hw->rpos = pa->rpos;
 277    if (pa->live > 0) {
 278        audio_pt_unlock_and_signal(&pa->pt, __func__);
 279    }
 280    else {
 281        audio_pt_unlock(&pa->pt, __func__);
 282    }
 283    return decr;
 284}
 285
 286static int qpa_write (SWVoiceOut *sw, void *buf, int len)
 287{
 288    return audio_pcm_sw_write (sw, buf, len);
 289}
 290
 291/* capture */
 292static void *qpa_thread_in (void *arg)
 293{
 294    PAVoiceIn *pa = arg;
 295    HWVoiceIn *hw = &pa->hw;
 296
 297    if (audio_pt_lock(&pa->pt, __func__)) {
 298        return NULL;
 299    }
 300
 301    for (;;) {
 302        int incr, to_grab, wpos;
 303
 304        for (;;) {
 305            if (pa->done) {
 306                goto exit;
 307            }
 308
 309            if (pa->dead > 0) {
 310                break;
 311            }
 312
 313            if (audio_pt_wait(&pa->pt, __func__)) {
 314                goto exit;
 315            }
 316        }
 317
 318        incr = to_grab = audio_MIN(pa->dead, pa->samples >> 5);
 319        wpos = pa->wpos;
 320
 321        if (audio_pt_unlock(&pa->pt, __func__)) {
 322            return NULL;
 323        }
 324
 325        while (to_grab) {
 326            int error;
 327            int chunk = audio_MIN (to_grab, hw->samples - wpos);
 328            void *buf = advance (pa->pcm_buf, wpos);
 329
 330            if (qpa_simple_read (pa, buf,
 331                                 chunk << hw->info.shift, &error) < 0) {
 332                qpa_logerr (error, "pa_simple_read failed\n");
 333                return NULL;
 334            }
 335
 336            hw->conv (hw->conv_buf + wpos, buf, chunk);
 337            wpos = (wpos + chunk) % hw->samples;
 338            to_grab -= chunk;
 339        }
 340
 341        if (audio_pt_lock(&pa->pt, __func__)) {
 342            return NULL;
 343        }
 344
 345        pa->wpos = wpos;
 346        pa->dead -= incr;
 347        pa->incr += incr;
 348    }
 349
 350 exit:
 351    audio_pt_unlock(&pa->pt, __func__);
 352    return NULL;
 353}
 354
 355static int qpa_run_in (HWVoiceIn *hw)
 356{
 357    int live, incr, dead;
 358    PAVoiceIn *pa = (PAVoiceIn *) hw;
 359
 360    if (audio_pt_lock(&pa->pt, __func__)) {
 361        return 0;
 362    }
 363
 364    live = audio_pcm_hw_get_live_in (hw);
 365    dead = hw->samples - live;
 366    incr = audio_MIN (dead, pa->incr);
 367    pa->incr -= incr;
 368    pa->dead = dead - incr;
 369    hw->wpos = pa->wpos;
 370    if (pa->dead > 0) {
 371        audio_pt_unlock_and_signal(&pa->pt, __func__);
 372    }
 373    else {
 374        audio_pt_unlock(&pa->pt, __func__);
 375    }
 376    return incr;
 377}
 378
 379static int qpa_read (SWVoiceIn *sw, void *buf, int len)
 380{
 381    return audio_pcm_sw_read (sw, buf, len);
 382}
 383
 384static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness)
 385{
 386    int format;
 387
 388    switch (afmt) {
 389    case AUDIO_FORMAT_S8:
 390    case AUDIO_FORMAT_U8:
 391        format = PA_SAMPLE_U8;
 392        break;
 393    case AUDIO_FORMAT_S16:
 394    case AUDIO_FORMAT_U16:
 395        format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
 396        break;
 397    case AUDIO_FORMAT_S32:
 398    case AUDIO_FORMAT_U32:
 399        format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
 400        break;
 401    default:
 402        dolog ("Internal logic error: Bad audio format %d\n", afmt);
 403        format = PA_SAMPLE_U8;
 404        break;
 405    }
 406    return format;
 407}
 408
 409static AudioFormat pa_to_audfmt (pa_sample_format_t fmt, int *endianness)
 410{
 411    switch (fmt) {
 412    case PA_SAMPLE_U8:
 413        return AUDIO_FORMAT_U8;
 414    case PA_SAMPLE_S16BE:
 415        *endianness = 1;
 416        return AUDIO_FORMAT_S16;
 417    case PA_SAMPLE_S16LE:
 418        *endianness = 0;
 419        return AUDIO_FORMAT_S16;
 420    case PA_SAMPLE_S32BE:
 421        *endianness = 1;
 422        return AUDIO_FORMAT_S32;
 423    case PA_SAMPLE_S32LE:
 424        *endianness = 0;
 425        return AUDIO_FORMAT_S32;
 426    default:
 427        dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt);
 428        return AUDIO_FORMAT_U8;
 429    }
 430}
 431
 432static void context_state_cb (pa_context *c, void *userdata)
 433{
 434    paaudio *g = userdata;
 435
 436    switch (pa_context_get_state(c)) {
 437    case PA_CONTEXT_READY:
 438    case PA_CONTEXT_TERMINATED:
 439    case PA_CONTEXT_FAILED:
 440        pa_threaded_mainloop_signal (g->mainloop, 0);
 441        break;
 442
 443    case PA_CONTEXT_UNCONNECTED:
 444    case PA_CONTEXT_CONNECTING:
 445    case PA_CONTEXT_AUTHORIZING:
 446    case PA_CONTEXT_SETTING_NAME:
 447        break;
 448    }
 449}
 450
 451static void stream_state_cb (pa_stream *s, void * userdata)
 452{
 453    paaudio *g = userdata;
 454
 455    switch (pa_stream_get_state (s)) {
 456
 457    case PA_STREAM_READY:
 458    case PA_STREAM_FAILED:
 459    case PA_STREAM_TERMINATED:
 460        pa_threaded_mainloop_signal (g->mainloop, 0);
 461        break;
 462
 463    case PA_STREAM_UNCONNECTED:
 464    case PA_STREAM_CREATING:
 465        break;
 466    }
 467}
 468
 469static void stream_request_cb (pa_stream *s, size_t length, void *userdata)
 470{
 471    paaudio *g = userdata;
 472
 473    pa_threaded_mainloop_signal (g->mainloop, 0);
 474}
 475
 476static pa_stream *qpa_simple_new (
 477        paaudio *g,
 478        const char *name,
 479        pa_stream_direction_t dir,
 480        const char *dev,
 481        const pa_sample_spec *ss,
 482        const pa_channel_map *map,
 483        const pa_buffer_attr *attr,
 484        int *rerror)
 485{
 486    int r;
 487    pa_stream *stream;
 488
 489    pa_threaded_mainloop_lock (g->mainloop);
 490
 491    stream = pa_stream_new (g->context, name, ss, map);
 492    if (!stream) {
 493        goto fail;
 494    }
 495
 496    pa_stream_set_state_callback (stream, stream_state_cb, g);
 497    pa_stream_set_read_callback (stream, stream_request_cb, g);
 498    pa_stream_set_write_callback (stream, stream_request_cb, g);
 499
 500    if (dir == PA_STREAM_PLAYBACK) {
 501        r = pa_stream_connect_playback (stream, dev, attr,
 502                                        PA_STREAM_INTERPOLATE_TIMING
 503#ifdef PA_STREAM_ADJUST_LATENCY
 504                                        |PA_STREAM_ADJUST_LATENCY
 505#endif
 506                                        |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
 507    } else {
 508        r = pa_stream_connect_record (stream, dev, attr,
 509                                      PA_STREAM_INTERPOLATE_TIMING
 510#ifdef PA_STREAM_ADJUST_LATENCY
 511                                      |PA_STREAM_ADJUST_LATENCY
 512#endif
 513                                      |PA_STREAM_AUTO_TIMING_UPDATE);
 514    }
 515
 516    if (r < 0) {
 517      goto fail;
 518    }
 519
 520    pa_threaded_mainloop_unlock (g->mainloop);
 521
 522    return stream;
 523
 524fail:
 525    pa_threaded_mainloop_unlock (g->mainloop);
 526
 527    if (stream) {
 528        pa_stream_unref (stream);
 529    }
 530
 531    *rerror = pa_context_errno (g->context);
 532
 533    return NULL;
 534}
 535
 536static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
 537                        void *drv_opaque)
 538{
 539    int error;
 540    pa_sample_spec ss;
 541    pa_buffer_attr ba;
 542    struct audsettings obt_as = *as;
 543    PAVoiceOut *pa = (PAVoiceOut *) hw;
 544    paaudio *g = pa->g = drv_opaque;
 545    AudiodevPaOptions *popts = &g->dev->u.pa;
 546    AudiodevPaPerDirectionOptions *ppdo = popts->out;
 547
 548    ss.format = audfmt_to_pa (as->fmt, as->endianness);
 549    ss.channels = as->nchannels;
 550    ss.rate = as->freq;
 551
 552    ba.tlength = pa_usec_to_bytes(ppdo->latency, &ss);
 553    ba.minreq = -1;
 554    ba.maxlength = -1;
 555    ba.prebuf = -1;
 556
 557    obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
 558
 559    pa->stream = qpa_simple_new (
 560        g,
 561        "qemu",
 562        PA_STREAM_PLAYBACK,
 563        ppdo->has_name ? ppdo->name : NULL,
 564        &ss,
 565        NULL,                   /* channel map */
 566        &ba,                    /* buffering attributes */
 567        &error
 568        );
 569    if (!pa->stream) {
 570        qpa_logerr (error, "pa_simple_new for playback failed\n");
 571        goto fail1;
 572    }
 573
 574    audio_pcm_init_info (&hw->info, &obt_as);
 575    hw->samples = pa->samples = audio_buffer_samples(
 576        qapi_AudiodevPaPerDirectionOptions_base(ppdo),
 577        &obt_as, ppdo->buffer_length);
 578    pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
 579    pa->rpos = hw->rpos;
 580    if (!pa->pcm_buf) {
 581        dolog ("Could not allocate buffer (%d bytes)\n",
 582               hw->samples << hw->info.shift);
 583        goto fail2;
 584    }
 585
 586    if (audio_pt_init(&pa->pt, qpa_thread_out, hw, AUDIO_CAP, __func__)) {
 587        goto fail3;
 588    }
 589
 590    return 0;
 591
 592 fail3:
 593    g_free (pa->pcm_buf);
 594    pa->pcm_buf = NULL;
 595 fail2:
 596    if (pa->stream) {
 597        pa_stream_unref (pa->stream);
 598        pa->stream = NULL;
 599    }
 600 fail1:
 601    return -1;
 602}
 603
 604static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 605{
 606    int error;
 607    pa_sample_spec ss;
 608    pa_buffer_attr ba;
 609    struct audsettings obt_as = *as;
 610    PAVoiceIn *pa = (PAVoiceIn *) hw;
 611    paaudio *g = pa->g = drv_opaque;
 612    AudiodevPaOptions *popts = &g->dev->u.pa;
 613    AudiodevPaPerDirectionOptions *ppdo = popts->in;
 614
 615    ss.format = audfmt_to_pa (as->fmt, as->endianness);
 616    ss.channels = as->nchannels;
 617    ss.rate = as->freq;
 618
 619    ba.fragsize = pa_usec_to_bytes(ppdo->latency, &ss);
 620    ba.maxlength = -1;
 621    ba.minreq = -1;
 622    ba.prebuf = -1;
 623
 624    obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
 625
 626    pa->stream = qpa_simple_new (
 627        g,
 628        "qemu",
 629        PA_STREAM_RECORD,
 630        ppdo->has_name ? ppdo->name : NULL,
 631        &ss,
 632        NULL,                   /* channel map */
 633        &ba,                    /* buffering attributes */
 634        &error
 635        );
 636    if (!pa->stream) {
 637        qpa_logerr (error, "pa_simple_new for capture failed\n");
 638        goto fail1;
 639    }
 640
 641    audio_pcm_init_info (&hw->info, &obt_as);
 642    hw->samples = pa->samples = audio_buffer_samples(
 643        qapi_AudiodevPaPerDirectionOptions_base(ppdo),
 644        &obt_as, ppdo->buffer_length);
 645    pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
 646    pa->wpos = hw->wpos;
 647    if (!pa->pcm_buf) {
 648        dolog ("Could not allocate buffer (%d bytes)\n",
 649               hw->samples << hw->info.shift);
 650        goto fail2;
 651    }
 652
 653    if (audio_pt_init(&pa->pt, qpa_thread_in, hw, AUDIO_CAP, __func__)) {
 654        goto fail3;
 655    }
 656
 657    return 0;
 658
 659 fail3:
 660    g_free (pa->pcm_buf);
 661    pa->pcm_buf = NULL;
 662 fail2:
 663    if (pa->stream) {
 664        pa_stream_unref (pa->stream);
 665        pa->stream = NULL;
 666    }
 667 fail1:
 668    return -1;
 669}
 670
 671static void qpa_fini_out (HWVoiceOut *hw)
 672{
 673    void *ret;
 674    PAVoiceOut *pa = (PAVoiceOut *) hw;
 675
 676    audio_pt_lock(&pa->pt, __func__);
 677    pa->done = 1;
 678    audio_pt_unlock_and_signal(&pa->pt, __func__);
 679    audio_pt_join(&pa->pt, &ret, __func__);
 680
 681    if (pa->stream) {
 682        pa_stream_unref (pa->stream);
 683        pa->stream = NULL;
 684    }
 685
 686    audio_pt_fini(&pa->pt, __func__);
 687    g_free (pa->pcm_buf);
 688    pa->pcm_buf = NULL;
 689}
 690
 691static void qpa_fini_in (HWVoiceIn *hw)
 692{
 693    void *ret;
 694    PAVoiceIn *pa = (PAVoiceIn *) hw;
 695
 696    audio_pt_lock(&pa->pt, __func__);
 697    pa->done = 1;
 698    audio_pt_unlock_and_signal(&pa->pt, __func__);
 699    audio_pt_join(&pa->pt, &ret, __func__);
 700
 701    if (pa->stream) {
 702        pa_stream_unref (pa->stream);
 703        pa->stream = NULL;
 704    }
 705
 706    audio_pt_fini(&pa->pt, __func__);
 707    g_free (pa->pcm_buf);
 708    pa->pcm_buf = NULL;
 709}
 710
 711static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...)
 712{
 713    PAVoiceOut *pa = (PAVoiceOut *) hw;
 714    pa_operation *op;
 715    pa_cvolume v;
 716    paaudio *g = pa->g;
 717
 718#ifdef PA_CHECK_VERSION    /* macro is present in 0.9.16+ */
 719    pa_cvolume_init (&v);  /* function is present in 0.9.13+ */
 720#endif
 721
 722    switch (cmd) {
 723    case VOICE_VOLUME:
 724        {
 725            SWVoiceOut *sw;
 726            va_list ap;
 727
 728            va_start (ap, cmd);
 729            sw = va_arg (ap, SWVoiceOut *);
 730            va_end (ap);
 731
 732            v.channels = 2;
 733            v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX;
 734            v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX;
 735
 736            pa_threaded_mainloop_lock (g->mainloop);
 737
 738            op = pa_context_set_sink_input_volume (g->context,
 739                pa_stream_get_index (pa->stream),
 740                &v, NULL, NULL);
 741            if (!op)
 742                qpa_logerr (pa_context_errno (g->context),
 743                            "set_sink_input_volume() failed\n");
 744            else
 745                pa_operation_unref (op);
 746
 747            op = pa_context_set_sink_input_mute (g->context,
 748                pa_stream_get_index (pa->stream),
 749               sw->vol.mute, NULL, NULL);
 750            if (!op) {
 751                qpa_logerr (pa_context_errno (g->context),
 752                            "set_sink_input_mute() failed\n");
 753            } else {
 754                pa_operation_unref (op);
 755            }
 756
 757            pa_threaded_mainloop_unlock (g->mainloop);
 758        }
 759    }
 760    return 0;
 761}
 762
 763static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
 764{
 765    PAVoiceIn *pa = (PAVoiceIn *) hw;
 766    pa_operation *op;
 767    pa_cvolume v;
 768    paaudio *g = pa->g;
 769
 770#ifdef PA_CHECK_VERSION
 771    pa_cvolume_init (&v);
 772#endif
 773
 774    switch (cmd) {
 775    case VOICE_VOLUME:
 776        {
 777            SWVoiceIn *sw;
 778            va_list ap;
 779
 780            va_start (ap, cmd);
 781            sw = va_arg (ap, SWVoiceIn *);
 782            va_end (ap);
 783
 784            v.channels = 2;
 785            v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX;
 786            v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX;
 787
 788            pa_threaded_mainloop_lock (g->mainloop);
 789
 790            op = pa_context_set_source_output_volume (g->context,
 791                pa_stream_get_index (pa->stream),
 792                &v, NULL, NULL);
 793            if (!op) {
 794                qpa_logerr (pa_context_errno (g->context),
 795                            "set_source_output_volume() failed\n");
 796            } else {
 797                pa_operation_unref(op);
 798            }
 799
 800            op = pa_context_set_source_output_mute (g->context,
 801                pa_stream_get_index (pa->stream),
 802                sw->vol.mute, NULL, NULL);
 803            if (!op) {
 804                qpa_logerr (pa_context_errno (g->context),
 805                            "set_source_output_mute() failed\n");
 806            } else {
 807                pa_operation_unref (op);
 808            }
 809
 810            pa_threaded_mainloop_unlock (g->mainloop);
 811        }
 812    }
 813    return 0;
 814}
 815
 816static int qpa_validate_per_direction_opts(Audiodev *dev,
 817                                           AudiodevPaPerDirectionOptions *pdo)
 818{
 819    if (!pdo->has_buffer_length) {
 820        pdo->has_buffer_length = true;
 821        pdo->buffer_length = 46440;
 822    }
 823    if (!pdo->has_latency) {
 824        pdo->has_latency = true;
 825        pdo->latency = 15000;
 826    }
 827    return 1;
 828}
 829
 830static void *qpa_audio_init(Audiodev *dev)
 831{
 832    paaudio *g;
 833    AudiodevPaOptions *popts = &dev->u.pa;
 834    const char *server;
 835
 836    if (!popts->has_server) {
 837        char pidfile[64];
 838        char *runtime;
 839        struct stat st;
 840
 841        runtime = getenv("XDG_RUNTIME_DIR");
 842        if (!runtime) {
 843            return NULL;
 844        }
 845        snprintf(pidfile, sizeof(pidfile), "%s/pulse/pid", runtime);
 846        if (stat(pidfile, &st) != 0) {
 847            return NULL;
 848        }
 849    }
 850
 851    assert(dev->driver == AUDIODEV_DRIVER_PA);
 852
 853    g = g_malloc(sizeof(paaudio));
 854    server = popts->has_server ? popts->server : NULL;
 855
 856    if (!qpa_validate_per_direction_opts(dev, popts->in)) {
 857        goto fail;
 858    }
 859    if (!qpa_validate_per_direction_opts(dev, popts->out)) {
 860        goto fail;
 861    }
 862
 863    g->dev = dev;
 864    g->mainloop = NULL;
 865    g->context = NULL;
 866
 867    g->mainloop = pa_threaded_mainloop_new ();
 868    if (!g->mainloop) {
 869        goto fail;
 870    }
 871
 872    g->context = pa_context_new (pa_threaded_mainloop_get_api (g->mainloop),
 873                                 server);
 874    if (!g->context) {
 875        goto fail;
 876    }
 877
 878    pa_context_set_state_callback (g->context, context_state_cb, g);
 879
 880    if (pa_context_connect(g->context, server, 0, NULL) < 0) {
 881        qpa_logerr (pa_context_errno (g->context),
 882                    "pa_context_connect() failed\n");
 883        goto fail;
 884    }
 885
 886    pa_threaded_mainloop_lock (g->mainloop);
 887
 888    if (pa_threaded_mainloop_start (g->mainloop) < 0) {
 889        goto unlock_and_fail;
 890    }
 891
 892    for (;;) {
 893        pa_context_state_t state;
 894
 895        state = pa_context_get_state (g->context);
 896
 897        if (state == PA_CONTEXT_READY) {
 898            break;
 899        }
 900
 901        if (!PA_CONTEXT_IS_GOOD (state)) {
 902            qpa_logerr (pa_context_errno (g->context),
 903                        "Wrong context state\n");
 904            goto unlock_and_fail;
 905        }
 906
 907        /* Wait until the context is ready */
 908        pa_threaded_mainloop_wait (g->mainloop);
 909    }
 910
 911    pa_threaded_mainloop_unlock (g->mainloop);
 912
 913    return g;
 914
 915unlock_and_fail:
 916    pa_threaded_mainloop_unlock (g->mainloop);
 917fail:
 918    AUD_log (AUDIO_CAP, "Failed to initialize PA context");
 919    qpa_audio_fini(g);
 920    return NULL;
 921}
 922
 923static void qpa_audio_fini (void *opaque)
 924{
 925    paaudio *g = opaque;
 926
 927    if (g->mainloop) {
 928        pa_threaded_mainloop_stop (g->mainloop);
 929    }
 930
 931    if (g->context) {
 932        pa_context_disconnect (g->context);
 933        pa_context_unref (g->context);
 934    }
 935
 936    if (g->mainloop) {
 937        pa_threaded_mainloop_free (g->mainloop);
 938    }
 939
 940    g_free(g);
 941}
 942
 943static struct audio_pcm_ops qpa_pcm_ops = {
 944    .init_out = qpa_init_out,
 945    .fini_out = qpa_fini_out,
 946    .run_out  = qpa_run_out,
 947    .write    = qpa_write,
 948    .ctl_out  = qpa_ctl_out,
 949
 950    .init_in  = qpa_init_in,
 951    .fini_in  = qpa_fini_in,
 952    .run_in   = qpa_run_in,
 953    .read     = qpa_read,
 954    .ctl_in   = qpa_ctl_in
 955};
 956
 957static struct audio_driver pa_audio_driver = {
 958    .name           = "pa",
 959    .descr          = "http://www.pulseaudio.org/",
 960    .init           = qpa_audio_init,
 961    .fini           = qpa_audio_fini,
 962    .pcm_ops        = &qpa_pcm_ops,
 963    .can_be_default = 1,
 964    .max_voices_out = INT_MAX,
 965    .max_voices_in  = INT_MAX,
 966    .voice_size_out = sizeof (PAVoiceOut),
 967    .voice_size_in  = sizeof (PAVoiceIn),
 968    .ctl_caps       = VOICE_VOLUME_CAP
 969};
 970
 971static void register_audio_pa(void)
 972{
 973    audio_driver_register(&pa_audio_driver);
 974}
 975type_init(register_audio_pa);
 976