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