qemu/audio/jackaudio.c
<<
>>
Prefs
   1/*
   2 * QEMU JACK Audio Connection Kit Client
   3 *
   4 * Copyright (c) 2020 Geoffrey McRae (gnif)
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24
  25#include "qemu/osdep.h"
  26#include "qemu/module.h"
  27#include "qemu/atomic.h"
  28#include "qemu/main-loop.h"
  29#include "audio.h"
  30
  31#define AUDIO_CAP "jack"
  32#include "audio_int.h"
  33
  34#include <jack/jack.h>
  35#include <jack/thread.h>
  36
  37struct QJack;
  38
  39typedef enum QJackState {
  40    QJACK_STATE_DISCONNECTED,
  41    QJACK_STATE_RUNNING,
  42    QJACK_STATE_SHUTDOWN
  43}
  44QJackState;
  45
  46typedef struct QJackBuffer {
  47    int          channels;
  48    int          frames;
  49    uint32_t     used;
  50    int          rptr, wptr;
  51    float      **data;
  52}
  53QJackBuffer;
  54
  55typedef struct QJackClient {
  56    AudiodevJackPerDirectionOptions *opt;
  57
  58    bool out;
  59    bool enabled;
  60    bool connect_ports;
  61    int  packets;
  62
  63    QJackState      state;
  64    jack_client_t  *client;
  65    jack_nframes_t  freq;
  66    QEMUBH         *shutdown_bh;
  67
  68    struct QJack   *j;
  69    int             nchannels;
  70    int             buffersize;
  71    jack_port_t   **port;
  72    QJackBuffer     fifo;
  73
  74    /* Used as workspace by qjack_process() */
  75    float **process_buffers;
  76}
  77QJackClient;
  78
  79typedef struct QJackOut {
  80    HWVoiceOut  hw;
  81    QJackClient c;
  82}
  83QJackOut;
  84
  85typedef struct QJackIn {
  86    HWVoiceIn   hw;
  87    QJackClient c;
  88}
  89QJackIn;
  90
  91static int qjack_client_init(QJackClient *c);
  92static void qjack_client_connect_ports(QJackClient *c);
  93static void qjack_client_fini(QJackClient *c);
  94static QemuMutex qjack_shutdown_lock;
  95
  96static void qjack_buffer_create(QJackBuffer *buffer, int channels, int frames)
  97{
  98    buffer->channels = channels;
  99    buffer->frames   = frames;
 100    buffer->used     = 0;
 101    buffer->rptr     = 0;
 102    buffer->wptr     = 0;
 103    buffer->data     = g_new(float *, channels);
 104    for (int i = 0; i < channels; ++i) {
 105        buffer->data[i] = g_new(float, frames);
 106    }
 107}
 108
 109static void qjack_buffer_clear(QJackBuffer *buffer)
 110{
 111    assert(buffer->data);
 112    qatomic_store_release(&buffer->used, 0);
 113    buffer->rptr = 0;
 114    buffer->wptr = 0;
 115}
 116
 117static void qjack_buffer_free(QJackBuffer *buffer)
 118{
 119    if (!buffer->data) {
 120        return;
 121    }
 122
 123    for (int i = 0; i < buffer->channels; ++i) {
 124        g_free(buffer->data[i]);
 125    }
 126
 127    g_free(buffer->data);
 128    buffer->data = NULL;
 129}
 130
 131/* write PCM interleaved */
 132static int qjack_buffer_write(QJackBuffer *buffer, float *data, int size)
 133{
 134    assert(buffer->data);
 135    const int samples = size / sizeof(float);
 136    int frames        = samples / buffer->channels;
 137    const int avail   = buffer->frames - qatomic_load_acquire(&buffer->used);
 138
 139    if (frames > avail) {
 140        frames = avail;
 141    }
 142
 143    int copy = frames;
 144    int wptr = buffer->wptr;
 145
 146    while (copy) {
 147
 148        for (int c = 0; c < buffer->channels; ++c) {
 149            buffer->data[c][wptr] = *data++;
 150        }
 151
 152        if (++wptr == buffer->frames) {
 153            wptr = 0;
 154        }
 155
 156        --copy;
 157    }
 158
 159    buffer->wptr = wptr;
 160
 161    qatomic_add(&buffer->used, frames);
 162    return frames * buffer->channels * sizeof(float);
 163};
 164
 165/* write PCM linear */
 166static int qjack_buffer_write_l(QJackBuffer *buffer, float **dest, int frames)
 167{
 168    assert(buffer->data);
 169    const int avail   = buffer->frames - qatomic_load_acquire(&buffer->used);
 170    int wptr = buffer->wptr;
 171
 172    if (frames > avail) {
 173        frames = avail;
 174    }
 175
 176    int right = buffer->frames - wptr;
 177    if (right > frames) {
 178        right = frames;
 179    }
 180
 181    const int left = frames - right;
 182    for (int c = 0; c < buffer->channels; ++c) {
 183        memcpy(buffer->data[c] + wptr, dest[c]        , right * sizeof(float));
 184        memcpy(buffer->data[c]       , dest[c] + right, left  * sizeof(float));
 185    }
 186
 187    wptr += frames;
 188    if (wptr >= buffer->frames) {
 189        wptr -= buffer->frames;
 190    }
 191    buffer->wptr = wptr;
 192
 193    qatomic_add(&buffer->used, frames);
 194    return frames;
 195}
 196
 197/* read PCM interleaved */
 198static int qjack_buffer_read(QJackBuffer *buffer, float *dest, int size)
 199{
 200    assert(buffer->data);
 201    const int samples = size / sizeof(float);
 202    int frames        = samples / buffer->channels;
 203    const int avail   = qatomic_load_acquire(&buffer->used);
 204
 205    if (frames > avail) {
 206        frames = avail;
 207    }
 208
 209    int copy = frames;
 210    int rptr = buffer->rptr;
 211
 212    while (copy) {
 213
 214        for (int c = 0; c < buffer->channels; ++c) {
 215            *dest++ = buffer->data[c][rptr];
 216        }
 217
 218        if (++rptr == buffer->frames) {
 219            rptr = 0;
 220        }
 221
 222        --copy;
 223    }
 224
 225    buffer->rptr = rptr;
 226
 227    qatomic_sub(&buffer->used, frames);
 228    return frames * buffer->channels * sizeof(float);
 229}
 230
 231/* read PCM linear */
 232static int qjack_buffer_read_l(QJackBuffer *buffer, float **dest, int frames)
 233{
 234    assert(buffer->data);
 235    int copy       = frames;
 236    const int used = qatomic_load_acquire(&buffer->used);
 237    int rptr       = buffer->rptr;
 238
 239    if (copy > used) {
 240        copy = used;
 241    }
 242
 243    int right = buffer->frames - rptr;
 244    if (right > copy) {
 245        right = copy;
 246    }
 247
 248    const int left = copy - right;
 249    for (int c = 0; c < buffer->channels; ++c) {
 250        memcpy(dest[c]        , buffer->data[c] + rptr, right * sizeof(float));
 251        memcpy(dest[c] + right, buffer->data[c]       , left  * sizeof(float));
 252    }
 253
 254    rptr += copy;
 255    if (rptr >= buffer->frames) {
 256        rptr -= buffer->frames;
 257    }
 258    buffer->rptr = rptr;
 259
 260    qatomic_sub(&buffer->used, copy);
 261    return copy;
 262}
 263
 264static int qjack_process(jack_nframes_t nframes, void *arg)
 265{
 266    QJackClient *c = (QJackClient *)arg;
 267
 268    if (c->state != QJACK_STATE_RUNNING) {
 269        return 0;
 270    }
 271
 272    /* get the buffers for the ports */
 273    for (int i = 0; i < c->nchannels; ++i) {
 274        c->process_buffers[i] = jack_port_get_buffer(c->port[i], nframes);
 275    }
 276
 277    if (c->out) {
 278        if (likely(c->enabled)) {
 279            qjack_buffer_read_l(&c->fifo, c->process_buffers, nframes);
 280        } else {
 281            for (int i = 0; i < c->nchannels; ++i) {
 282                memset(c->process_buffers[i], 0, nframes * sizeof(float));
 283            }
 284        }
 285    } else {
 286        if (likely(c->enabled)) {
 287            qjack_buffer_write_l(&c->fifo, c->process_buffers, nframes);
 288        }
 289    }
 290
 291    return 0;
 292}
 293
 294static void qjack_port_registration(jack_port_id_t port, int reg, void *arg)
 295{
 296    if (reg) {
 297        QJackClient *c = (QJackClient *)arg;
 298        c->connect_ports = true;
 299    }
 300}
 301
 302static int qjack_xrun(void *arg)
 303{
 304    QJackClient *c = (QJackClient *)arg;
 305    if (c->state != QJACK_STATE_RUNNING) {
 306        return 0;
 307    }
 308
 309    qjack_buffer_clear(&c->fifo);
 310    return 0;
 311}
 312
 313static void qjack_shutdown_bh(void *opaque)
 314{
 315    QJackClient *c = (QJackClient *)opaque;
 316    qjack_client_fini(c);
 317}
 318
 319static void qjack_shutdown(void *arg)
 320{
 321    QJackClient *c = (QJackClient *)arg;
 322    c->state = QJACK_STATE_SHUTDOWN;
 323    qemu_bh_schedule(c->shutdown_bh);
 324}
 325
 326static void qjack_client_recover(QJackClient *c)
 327{
 328    if (c->state != QJACK_STATE_DISCONNECTED) {
 329        return;
 330    }
 331
 332    /* packets is used simply to throttle this */
 333    if (c->packets % 100 == 0) {
 334
 335        /* if enabled then attempt to recover */
 336        if (c->enabled) {
 337            dolog("attempting to reconnect to server\n");
 338            qjack_client_init(c);
 339        }
 340    }
 341}
 342
 343static size_t qjack_write(HWVoiceOut *hw, void *buf, size_t len)
 344{
 345    QJackOut *jo = (QJackOut *)hw;
 346    ++jo->c.packets;
 347
 348    if (jo->c.state != QJACK_STATE_RUNNING) {
 349        qjack_client_recover(&jo->c);
 350        return len;
 351    }
 352
 353    qjack_client_connect_ports(&jo->c);
 354    return qjack_buffer_write(&jo->c.fifo, buf, len);
 355}
 356
 357static size_t qjack_read(HWVoiceIn *hw, void *buf, size_t len)
 358{
 359    QJackIn *ji = (QJackIn *)hw;
 360    ++ji->c.packets;
 361
 362    if (ji->c.state != QJACK_STATE_RUNNING) {
 363        qjack_client_recover(&ji->c);
 364        return len;
 365    }
 366
 367    qjack_client_connect_ports(&ji->c);
 368    return qjack_buffer_read(&ji->c.fifo, buf, len);
 369}
 370
 371static void qjack_client_connect_ports(QJackClient *c)
 372{
 373    if (!c->connect_ports || !c->opt->connect_ports) {
 374        return;
 375    }
 376
 377    c->connect_ports = false;
 378    const char **ports;
 379    ports = jack_get_ports(c->client, c->opt->connect_ports, NULL,
 380        c->out ? JackPortIsInput : JackPortIsOutput);
 381
 382    if (!ports) {
 383        return;
 384    }
 385
 386    for (int i = 0; i < c->nchannels && ports[i]; ++i) {
 387        const char *p = jack_port_name(c->port[i]);
 388        if (jack_port_connected_to(c->port[i], ports[i])) {
 389            continue;
 390        }
 391
 392        if (c->out) {
 393            dolog("connect %s -> %s\n", p, ports[i]);
 394            jack_connect(c->client, p, ports[i]);
 395        } else {
 396            dolog("connect %s -> %s\n", ports[i], p);
 397            jack_connect(c->client, ports[i], p);
 398        }
 399    }
 400}
 401
 402static int qjack_client_init(QJackClient *c)
 403{
 404    jack_status_t status;
 405    int client_name_len = jack_client_name_size(); /* includes NUL */
 406    g_autofree char *client_name = g_new(char, client_name_len);
 407    jack_options_t options = JackNullOption;
 408
 409    if (c->state == QJACK_STATE_RUNNING) {
 410        return 0;
 411    }
 412
 413    c->connect_ports = true;
 414
 415    snprintf(client_name, client_name_len, "%s-%s",
 416        c->out ? "out" : "in",
 417        c->opt->client_name ? c->opt->client_name : audio_application_name());
 418
 419    if (c->opt->exact_name) {
 420        options |= JackUseExactName;
 421    }
 422
 423    if (!c->opt->start_server) {
 424        options |= JackNoStartServer;
 425    }
 426
 427    if (c->opt->server_name) {
 428        options |= JackServerName;
 429    }
 430
 431    c->client = jack_client_open(client_name, options, &status,
 432      c->opt->server_name);
 433
 434    if (c->client == NULL) {
 435        dolog("jack_client_open failed: status = 0x%2.0x\n", status);
 436        if (status & JackServerFailed) {
 437            dolog("unable to connect to JACK server\n");
 438        }
 439        return -1;
 440    }
 441
 442    c->freq = jack_get_sample_rate(c->client);
 443
 444    if (status & JackServerStarted) {
 445        dolog("JACK server started\n");
 446    }
 447
 448    if (status & JackNameNotUnique) {
 449        dolog("JACK unique name assigned %s\n",
 450          jack_get_client_name(c->client));
 451    }
 452
 453    /* Allocate working buffer for process callback */
 454    c->process_buffers = g_new(float *, c->nchannels);
 455
 456    jack_set_process_callback(c->client, qjack_process , c);
 457    jack_set_port_registration_callback(c->client, qjack_port_registration, c);
 458    jack_set_xrun_callback(c->client, qjack_xrun, c);
 459    jack_on_shutdown(c->client, qjack_shutdown, c);
 460
 461    /* allocate and register the ports */
 462    c->port = g_new(jack_port_t *, c->nchannels);
 463    for (int i = 0; i < c->nchannels; ++i) {
 464
 465        char port_name[16];
 466        snprintf(
 467            port_name,
 468            sizeof(port_name),
 469            c->out ? "output %d" : "input %d",
 470            i);
 471
 472        c->port[i] = jack_port_register(
 473            c->client,
 474            port_name,
 475            JACK_DEFAULT_AUDIO_TYPE,
 476            c->out ? JackPortIsOutput : JackPortIsInput,
 477            0);
 478    }
 479
 480    /* activate the session */
 481    jack_activate(c->client);
 482    c->buffersize = jack_get_buffer_size(c->client);
 483
 484    /*
 485     * ensure the buffersize is no smaller then 512 samples, some (all?) qemu
 486     * virtual devices do not work correctly otherwise
 487     */
 488    if (c->buffersize < 512) {
 489        c->buffersize = 512;
 490    }
 491
 492    /* create a 3 period buffer */
 493    qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 3);
 494
 495    qjack_client_connect_ports(c);
 496    c->state = QJACK_STATE_RUNNING;
 497    return 0;
 498}
 499
 500static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as,
 501    void *drv_opaque)
 502{
 503    QJackOut *jo  = (QJackOut *)hw;
 504    Audiodev *dev = (Audiodev *)drv_opaque;
 505
 506    jo->c.out       = true;
 507    jo->c.enabled   = false;
 508    jo->c.nchannels = as->nchannels;
 509    jo->c.opt       = dev->u.jack.out;
 510
 511    jo->c.shutdown_bh = qemu_bh_new(qjack_shutdown_bh, &jo->c);
 512
 513    int ret = qjack_client_init(&jo->c);
 514    if (ret != 0) {
 515        qemu_bh_delete(jo->c.shutdown_bh);
 516        return ret;
 517    }
 518
 519    /* report the buffer size to qemu */
 520    hw->samples = jo->c.buffersize;
 521
 522    /* report the audio format we support */
 523    struct audsettings os = {
 524        .freq       = jo->c.freq,
 525        .nchannels  = jo->c.nchannels,
 526        .fmt        = AUDIO_FORMAT_F32,
 527        .endianness = 0
 528    };
 529    audio_pcm_init_info(&hw->info, &os);
 530
 531    dolog("JACK output configured for %dHz (%d samples)\n",
 532        jo->c.freq, jo->c.buffersize);
 533
 534    return 0;
 535}
 536
 537static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as,
 538    void *drv_opaque)
 539{
 540    QJackIn  *ji  = (QJackIn *)hw;
 541    Audiodev *dev = (Audiodev *)drv_opaque;
 542
 543    ji->c.out       = false;
 544    ji->c.enabled   = false;
 545    ji->c.nchannels = as->nchannels;
 546    ji->c.opt       = dev->u.jack.in;
 547
 548    ji->c.shutdown_bh = qemu_bh_new(qjack_shutdown_bh, &ji->c);
 549
 550    int ret = qjack_client_init(&ji->c);
 551    if (ret != 0) {
 552        qemu_bh_delete(ji->c.shutdown_bh);
 553        return ret;
 554    }
 555
 556    /* report the buffer size to qemu */
 557    hw->samples = ji->c.buffersize;
 558
 559    /* report the audio format we support */
 560    struct audsettings is = {
 561        .freq       = ji->c.freq,
 562        .nchannels  = ji->c.nchannels,
 563        .fmt        = AUDIO_FORMAT_F32,
 564        .endianness = 0
 565    };
 566    audio_pcm_init_info(&hw->info, &is);
 567
 568    dolog("JACK input configured for %dHz (%d samples)\n",
 569        ji->c.freq, ji->c.buffersize);
 570
 571    return 0;
 572}
 573
 574static void qjack_client_fini_locked(QJackClient *c)
 575{
 576    switch (c->state) {
 577    case QJACK_STATE_RUNNING:
 578        jack_deactivate(c->client);
 579        /* fallthrough */
 580
 581    case QJACK_STATE_SHUTDOWN:
 582        jack_client_close(c->client);
 583        c->client = NULL;
 584
 585        qjack_buffer_free(&c->fifo);
 586        g_free(c->port);
 587        g_free(c->process_buffers);
 588
 589        c->state = QJACK_STATE_DISCONNECTED;
 590        /* fallthrough */
 591
 592    case QJACK_STATE_DISCONNECTED:
 593        break;
 594    }
 595}
 596
 597static void qjack_client_fini(QJackClient *c)
 598{
 599    qemu_mutex_lock(&qjack_shutdown_lock);
 600    qjack_client_fini_locked(c);
 601    qemu_mutex_unlock(&qjack_shutdown_lock);
 602}
 603
 604static void qjack_fini_out(HWVoiceOut *hw)
 605{
 606    QJackOut *jo = (QJackOut *)hw;
 607    qjack_client_fini(&jo->c);
 608
 609    qemu_bh_delete(jo->c.shutdown_bh);
 610}
 611
 612static void qjack_fini_in(HWVoiceIn *hw)
 613{
 614    QJackIn *ji = (QJackIn *)hw;
 615    qjack_client_fini(&ji->c);
 616
 617    qemu_bh_delete(ji->c.shutdown_bh);
 618}
 619
 620static void qjack_enable_out(HWVoiceOut *hw, bool enable)
 621{
 622    QJackOut *jo = (QJackOut *)hw;
 623    jo->c.enabled = enable;
 624}
 625
 626static void qjack_enable_in(HWVoiceIn *hw, bool enable)
 627{
 628    QJackIn *ji = (QJackIn *)hw;
 629    ji->c.enabled = enable;
 630}
 631
 632#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
 633static int qjack_thread_creator(jack_native_thread_t *thread,
 634    const pthread_attr_t *attr, void *(*function)(void *), void *arg)
 635{
 636    int ret = pthread_create(thread, attr, function, arg);
 637    if (ret != 0) {
 638        return ret;
 639    }
 640
 641    /* set the name of the thread */
 642    pthread_setname_np(*thread, "jack-client");
 643
 644    return ret;
 645}
 646#endif
 647
 648static void *qjack_init(Audiodev *dev, Error **errp)
 649{
 650    assert(dev->driver == AUDIODEV_DRIVER_JACK);
 651    return dev;
 652}
 653
 654static void qjack_fini(void *opaque)
 655{
 656}
 657
 658static struct audio_pcm_ops jack_pcm_ops = {
 659    .init_out       = qjack_init_out,
 660    .fini_out       = qjack_fini_out,
 661    .write          = qjack_write,
 662    .buffer_get_free = audio_generic_buffer_get_free,
 663    .run_buffer_out = audio_generic_run_buffer_out,
 664    .enable_out     = qjack_enable_out,
 665
 666    .init_in        = qjack_init_in,
 667    .fini_in        = qjack_fini_in,
 668    .read           = qjack_read,
 669    .run_buffer_in  = audio_generic_run_buffer_in,
 670    .enable_in      = qjack_enable_in
 671};
 672
 673static struct audio_driver jack_driver = {
 674    .name           = "jack",
 675    .descr          = "JACK Audio Connection Kit Client",
 676    .init           = qjack_init,
 677    .fini           = qjack_fini,
 678    .pcm_ops        = &jack_pcm_ops,
 679    .max_voices_out = INT_MAX,
 680    .max_voices_in  = INT_MAX,
 681    .voice_size_out = sizeof(QJackOut),
 682    .voice_size_in  = sizeof(QJackIn)
 683};
 684
 685static void qjack_error(const char *msg)
 686{
 687    dolog("E: %s\n", msg);
 688}
 689
 690static void qjack_info(const char *msg)
 691{
 692    dolog("I: %s\n", msg);
 693}
 694
 695static void register_audio_jack(void)
 696{
 697    qemu_mutex_init(&qjack_shutdown_lock);
 698    audio_driver_register(&jack_driver);
 699#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
 700    jack_set_thread_creator(qjack_thread_creator);
 701#endif
 702    jack_set_error_function(qjack_error);
 703    jack_set_info_function(qjack_info);
 704}
 705type_init(register_audio_jack);
 706