1 /* public domain */ 2 #include "qemu-common.h" 3 #include "audio.h" 4 5 #include <pulse/simple.h> 6 #include <pulse/error.h> 7 8 #define AUDIO_CAP "pulseaudio" 9 #include "audio_int.h" 10 #include "audio_pt_int.h" 11 12 typedef struct { 13 HWVoiceOut hw; 14 int done; 15 int live; 16 int decr; 17 int rpos; 18 pa_simple *s; 19 void *pcm_buf; 20 struct audio_pt pt; 21 } PAVoiceOut; 22 23 typedef struct { 24 HWVoiceIn hw; 25 int done; 26 int dead; 27 int incr; 28 int wpos; 29 pa_simple *s; 30 void *pcm_buf; 31 struct audio_pt pt; 32 } PAVoiceIn; 33 34 static struct { 35 int samples; 36 char *server; 37 char *sink; 38 char *source; 39 } conf = { 40 .samples = 4096, 41 }; 42 43 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...) 44 { 45 va_list ap; 46 47 va_start (ap, fmt); 48 AUD_vlog (AUDIO_CAP, fmt, ap); 49 va_end (ap); 50 51 AUD_log (AUDIO_CAP, "Reason: %s\n", pa_strerror (err)); 52 } 53 54 static void *qpa_thread_out (void *arg) 55 { 56 PAVoiceOut *pa = arg; 57 HWVoiceOut *hw = &pa->hw; 58 59 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { 60 return NULL; 61 } 62 63 for (;;) { 64 int decr, to_mix, rpos; 65 66 for (;;) { 67 if (pa->done) { 68 goto exit; 69 } 70 71 if (pa->live > 0) { 72 break; 73 } 74 75 if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) { 76 goto exit; 77 } 78 } 79 80 decr = to_mix = audio_MIN (pa->live, conf.samples >> 2); 81 rpos = pa->rpos; 82 83 if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) { 84 return NULL; 85 } 86 87 while (to_mix) { 88 int error; 89 int chunk = audio_MIN (to_mix, hw->samples - rpos); 90 struct st_sample *src = hw->mix_buf + rpos; 91 92 hw->clip (pa->pcm_buf, src, chunk); 93 94 if (pa_simple_write (pa->s, pa->pcm_buf, 95 chunk << hw->info.shift, &error) < 0) { 96 qpa_logerr (error, "pa_simple_write failed\n"); 97 return NULL; 98 } 99 100 rpos = (rpos + chunk) % hw->samples; 101 to_mix -= chunk; 102 } 103 104 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { 105 return NULL; 106 } 107 108 pa->rpos = rpos; 109 pa->live -= decr; 110 pa->decr += decr; 111 } 112 113 exit: 114 audio_pt_unlock (&pa->pt, AUDIO_FUNC); 115 return NULL; 116 } 117 118 static int qpa_run_out (HWVoiceOut *hw, int live) 119 { 120 int decr; 121 PAVoiceOut *pa = (PAVoiceOut *) hw; 122 123 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { 124 return 0; 125 } 126 127 decr = audio_MIN (live, pa->decr); 128 pa->decr -= decr; 129 pa->live = live - decr; 130 hw->rpos = pa->rpos; 131 if (pa->live > 0) { 132 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); 133 } 134 else { 135 audio_pt_unlock (&pa->pt, AUDIO_FUNC); 136 } 137 return decr; 138 } 139 140 static int qpa_write (SWVoiceOut *sw, void *buf, int len) 141 { 142 return audio_pcm_sw_write (sw, buf, len); 143 } 144 145 /* capture */ 146 static void *qpa_thread_in (void *arg) 147 { 148 PAVoiceIn *pa = arg; 149 HWVoiceIn *hw = &pa->hw; 150 151 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { 152 return NULL; 153 } 154 155 for (;;) { 156 int incr, to_grab, wpos; 157 158 for (;;) { 159 if (pa->done) { 160 goto exit; 161 } 162 163 if (pa->dead > 0) { 164 break; 165 } 166 167 if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) { 168 goto exit; 169 } 170 } 171 172 incr = to_grab = audio_MIN (pa->dead, conf.samples >> 2); 173 wpos = pa->wpos; 174 175 if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) { 176 return NULL; 177 } 178 179 while (to_grab) { 180 int error; 181 int chunk = audio_MIN (to_grab, hw->samples - wpos); 182 void *buf = advance (pa->pcm_buf, wpos); 183 184 if (pa_simple_read (pa->s, buf, 185 chunk << hw->info.shift, &error) < 0) { 186 qpa_logerr (error, "pa_simple_read failed\n"); 187 return NULL; 188 } 189 190 hw->conv (hw->conv_buf + wpos, buf, chunk); 191 wpos = (wpos + chunk) % hw->samples; 192 to_grab -= chunk; 193 } 194 195 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { 196 return NULL; 197 } 198 199 pa->wpos = wpos; 200 pa->dead -= incr; 201 pa->incr += incr; 202 } 203 204 exit: 205 audio_pt_unlock (&pa->pt, AUDIO_FUNC); 206 return NULL; 207 } 208 209 static int qpa_run_in (HWVoiceIn *hw) 210 { 211 int live, incr, dead; 212 PAVoiceIn *pa = (PAVoiceIn *) hw; 213 214 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { 215 return 0; 216 } 217 218 live = audio_pcm_hw_get_live_in (hw); 219 dead = hw->samples - live; 220 incr = audio_MIN (dead, pa->incr); 221 pa->incr -= incr; 222 pa->dead = dead - incr; 223 hw->wpos = pa->wpos; 224 if (pa->dead > 0) { 225 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); 226 } 227 else { 228 audio_pt_unlock (&pa->pt, AUDIO_FUNC); 229 } 230 return incr; 231 } 232 233 static int qpa_read (SWVoiceIn *sw, void *buf, int len) 234 { 235 return audio_pcm_sw_read (sw, buf, len); 236 } 237 238 static pa_sample_format_t audfmt_to_pa (audfmt_e afmt, int endianness) 239 { 240 int format; 241 242 switch (afmt) { 243 case AUD_FMT_S8: 244 case AUD_FMT_U8: 245 format = PA_SAMPLE_U8; 246 break; 247 case AUD_FMT_S16: 248 case AUD_FMT_U16: 249 format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; 250 break; 251 case AUD_FMT_S32: 252 case AUD_FMT_U32: 253 format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; 254 break; 255 default: 256 dolog ("Internal logic error: Bad audio format %d\n", afmt); 257 format = PA_SAMPLE_U8; 258 break; 259 } 260 return format; 261 } 262 263 static audfmt_e pa_to_audfmt (pa_sample_format_t fmt, int *endianness) 264 { 265 switch (fmt) { 266 case PA_SAMPLE_U8: 267 return AUD_FMT_U8; 268 case PA_SAMPLE_S16BE: 269 *endianness = 1; 270 return AUD_FMT_S16; 271 case PA_SAMPLE_S16LE: 272 *endianness = 0; 273 return AUD_FMT_S16; 274 case PA_SAMPLE_S32BE: 275 *endianness = 1; 276 return AUD_FMT_S32; 277 case PA_SAMPLE_S32LE: 278 *endianness = 0; 279 return AUD_FMT_S32; 280 default: 281 dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt); 282 return AUD_FMT_U8; 283 } 284 } 285 286 static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as) 287 { 288 int error; 289 static pa_sample_spec ss; 290 static pa_buffer_attr ba; 291 struct audsettings obt_as = *as; 292 PAVoiceOut *pa = (PAVoiceOut *) hw; 293 294 ss.format = audfmt_to_pa (as->fmt, as->endianness); 295 ss.channels = as->nchannels; 296 ss.rate = as->freq; 297 298 /* 299 * qemu audio tick runs at 250 Hz (by default), so processing 300 * data chunks worth 4 ms of sound should be a good fit. 301 */ 302 ba.tlength = pa_usec_to_bytes (4 * 1000, &ss); 303 ba.minreq = pa_usec_to_bytes (2 * 1000, &ss); 304 ba.maxlength = -1; 305 ba.prebuf = -1; 306 307 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); 308 309 pa->s = pa_simple_new ( 310 conf.server, 311 "qemu", 312 PA_STREAM_PLAYBACK, 313 conf.sink, 314 "pcm.playback", 315 &ss, 316 NULL, /* channel map */ 317 &ba, /* buffering attributes */ 318 &error 319 ); 320 if (!pa->s) { 321 qpa_logerr (error, "pa_simple_new for playback failed\n"); 322 goto fail1; 323 } 324 325 audio_pcm_init_info (&hw->info, &obt_as); 326 hw->samples = conf.samples; 327 pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); 328 pa->rpos = hw->rpos; 329 if (!pa->pcm_buf) { 330 dolog ("Could not allocate buffer (%d bytes)\n", 331 hw->samples << hw->info.shift); 332 goto fail2; 333 } 334 335 if (audio_pt_init (&pa->pt, qpa_thread_out, hw, AUDIO_CAP, AUDIO_FUNC)) { 336 goto fail3; 337 } 338 339 return 0; 340 341 fail3: 342 qemu_free (pa->pcm_buf); 343 pa->pcm_buf = NULL; 344 fail2: 345 pa_simple_free (pa->s); 346 pa->s = NULL; 347 fail1: 348 return -1; 349 } 350 351 static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as) 352 { 353 int error; 354 static pa_sample_spec ss; 355 struct audsettings obt_as = *as; 356 PAVoiceIn *pa = (PAVoiceIn *) hw; 357 358 ss.format = audfmt_to_pa (as->fmt, as->endianness); 359 ss.channels = as->nchannels; 360 ss.rate = as->freq; 361 362 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); 363 364 pa->s = pa_simple_new ( 365 conf.server, 366 "qemu", 367 PA_STREAM_RECORD, 368 conf.source, 369 "pcm.capture", 370 &ss, 371 NULL, /* channel map */ 372 NULL, /* buffering attributes */ 373 &error 374 ); 375 if (!pa->s) { 376 qpa_logerr (error, "pa_simple_new for capture failed\n"); 377 goto fail1; 378 } 379 380 audio_pcm_init_info (&hw->info, &obt_as); 381 hw->samples = conf.samples; 382 pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); 383 pa->wpos = hw->wpos; 384 if (!pa->pcm_buf) { 385 dolog ("Could not allocate buffer (%d bytes)\n", 386 hw->samples << hw->info.shift); 387 goto fail2; 388 } 389 390 if (audio_pt_init (&pa->pt, qpa_thread_in, hw, AUDIO_CAP, AUDIO_FUNC)) { 391 goto fail3; 392 } 393 394 return 0; 395 396 fail3: 397 qemu_free (pa->pcm_buf); 398 pa->pcm_buf = NULL; 399 fail2: 400 pa_simple_free (pa->s); 401 pa->s = NULL; 402 fail1: 403 return -1; 404 } 405 406 static void qpa_fini_out (HWVoiceOut *hw) 407 { 408 void *ret; 409 PAVoiceOut *pa = (PAVoiceOut *) hw; 410 411 audio_pt_lock (&pa->pt, AUDIO_FUNC); 412 pa->done = 1; 413 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); 414 audio_pt_join (&pa->pt, &ret, AUDIO_FUNC); 415 416 if (pa->s) { 417 pa_simple_free (pa->s); 418 pa->s = NULL; 419 } 420 421 audio_pt_fini (&pa->pt, AUDIO_FUNC); 422 qemu_free (pa->pcm_buf); 423 pa->pcm_buf = NULL; 424 } 425 426 static void qpa_fini_in (HWVoiceIn *hw) 427 { 428 void *ret; 429 PAVoiceIn *pa = (PAVoiceIn *) hw; 430 431 audio_pt_lock (&pa->pt, AUDIO_FUNC); 432 pa->done = 1; 433 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); 434 audio_pt_join (&pa->pt, &ret, AUDIO_FUNC); 435 436 if (pa->s) { 437 pa_simple_free (pa->s); 438 pa->s = NULL; 439 } 440 441 audio_pt_fini (&pa->pt, AUDIO_FUNC); 442 qemu_free (pa->pcm_buf); 443 pa->pcm_buf = NULL; 444 } 445 446 static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) 447 { 448 (void) hw; 449 (void) cmd; 450 return 0; 451 } 452 453 static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...) 454 { 455 (void) hw; 456 (void) cmd; 457 return 0; 458 } 459 460 /* common */ 461 static void *qpa_audio_init (void) 462 { 463 return &conf; 464 } 465 466 static void qpa_audio_fini (void *opaque) 467 { 468 (void) opaque; 469 } 470 471 struct audio_option qpa_options[] = { 472 { 473 .name = "SAMPLES", 474 .tag = AUD_OPT_INT, 475 .valp = &conf.samples, 476 .descr = "buffer size in samples" 477 }, 478 { 479 .name = "SERVER", 480 .tag = AUD_OPT_STR, 481 .valp = &conf.server, 482 .descr = "server address" 483 }, 484 { 485 .name = "SINK", 486 .tag = AUD_OPT_STR, 487 .valp = &conf.sink, 488 .descr = "sink device name" 489 }, 490 { 491 .name = "SOURCE", 492 .tag = AUD_OPT_STR, 493 .valp = &conf.source, 494 .descr = "source device name" 495 }, 496 { /* End of list */ } 497 }; 498 499 static struct audio_pcm_ops qpa_pcm_ops = { 500 .init_out = qpa_init_out, 501 .fini_out = qpa_fini_out, 502 .run_out = qpa_run_out, 503 .write = qpa_write, 504 .ctl_out = qpa_ctl_out, 505 506 .init_in = qpa_init_in, 507 .fini_in = qpa_fini_in, 508 .run_in = qpa_run_in, 509 .read = qpa_read, 510 .ctl_in = qpa_ctl_in 511 }; 512 513 struct audio_driver pa_audio_driver = { 514 .name = "pa", 515 .descr = "http://www.pulseaudio.org/", 516 .options = qpa_options, 517 .init = qpa_audio_init, 518 .fini = qpa_audio_fini, 519 .pcm_ops = &qpa_pcm_ops, 520 .can_be_default = 1, 521 .max_voices_out = INT_MAX, 522 .max_voices_in = INT_MAX, 523 .voice_size_out = sizeof (PAVoiceOut), 524 .voice_size_in = sizeof (PAVoiceIn) 525 }; 526