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