1 /*- 2 * Copyright (c) 2012-2022 Hans Petter Selasky 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/queue.h> 27 #include <sys/types.h> 28 #include <sys/filio.h> 29 #include <sys/rtprio.h> 30 #include <sys/nv.h> 31 #include <sys/sndstat.h> 32 #include <sys/soundcard.h> 33 34 #include <dlfcn.h> 35 #include <stdio.h> 36 #include <stdint.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 #include <err.h> 41 #include <sysexits.h> 42 #include <signal.h> 43 #include <fcntl.h> 44 #include <paths.h> 45 46 #include <cuse.h> 47 #include <pthread.h> 48 49 #include "backend.h" 50 #include "int.h" 51 #include "utils.h" 52 #include "virtual_oss.h" 53 54 pthread_mutex_t atomic_mtx; 55 pthread_cond_t atomic_cv; 56 57 static void 58 atomic_init(void) 59 { 60 if (pthread_mutex_init(&atomic_mtx, NULL) != 0) 61 err(1, "pthread_mutex_init"); 62 if (pthread_cond_init(&atomic_cv, NULL) != 0) 63 err(1, "pthread_cond_init"); 64 } 65 66 uint32_t 67 vclient_sample_bytes(vclient_t *pvc) 68 { 69 uint32_t fmt = pvc->format; 70 71 if (fmt & AFMT_16BIT) 72 return (2); 73 else if (fmt & AFMT_24BIT) 74 return (3); 75 else if (fmt & AFMT_32BIT) 76 return (4); 77 else if (fmt & AFMT_8BIT) 78 return (1); 79 else 80 return (0); 81 /* TODO AFMT_BPS */ 82 } 83 84 static uint32_t 85 vclient_output_delay(vclient_t *pvc) 86 { 87 uint64_t size; 88 uint64_t mod; 89 90 if (pvc->tx_busy == 0) 91 vclient_import_write_locked(pvc); 92 93 mod = pvc->channels * vclient_sample_bytes(pvc); 94 95 size = vring_total_read_len(&pvc->tx_ring[0]); 96 size = (size / 8) * vclient_sample_bytes(pvc); 97 98 size = (size * (uint64_t)pvc->sample_rate) / 99 (uint64_t)voss_dsp_sample_rate; 100 size += vring_total_read_len(&pvc->tx_ring[1]); 101 size -= size % mod; 102 103 return (size); 104 } 105 106 static uint32_t 107 vclient_input_delay(vclient_t *pvc) 108 { 109 if (pvc->rx_busy == 0) 110 vclient_export_read_locked(pvc); 111 return (vring_total_read_len(&pvc->rx_ring[1])); 112 } 113 114 uint32_t 115 vclient_bufsize_scaled(vclient_t *pvc) 116 { 117 uint32_t samples_scaled = ((uint64_t)voss_dsp_samples * 118 (uint64_t)pvc->sample_rate) / (uint64_t)voss_dsp_sample_rate; 119 if (samples_scaled == 0) 120 samples_scaled = 1; 121 return (pvc->channels * samples_scaled * vclient_sample_bytes(pvc)); 122 } 123 124 static uint64_t 125 vclient_bufsize_consumed(vclient_t *pvc, uint64_t ts) 126 { 127 int64_t delta; 128 int64_t samples_scaled; 129 int64_t retval; 130 131 delta = virtual_oss_timestamp() - ts; 132 if (delta < 0) 133 delta = 0; 134 samples_scaled = (delta * (uint64_t)pvc->sample_rate) / 1000000000ULL; 135 if (samples_scaled < 0) 136 samples_scaled = 0; 137 retval = pvc->channels * samples_scaled * vclient_sample_bytes(pvc); 138 if (retval < 0) 139 retval = 0; 140 return (retval); 141 } 142 143 /* 144 * VLC and some other audio player use this value for jitter 145 * computations and expect it to be very accurate. VirtualOSS is block 146 * based and does not have sample accuracy. Use the system clock to 147 * update this value as we go along instead: 148 */ 149 static uint32_t 150 vclient_output_delay_adjusted(vclient_t *pvc) 151 { 152 int64_t retval = vclient_output_delay(pvc) - 153 vclient_bufsize_consumed(pvc, pvc->tx_timestamp); 154 if (retval < 0) 155 retval = 0; 156 return (retval); 157 } 158 159 vmonitor_t * 160 vmonitor_alloc(int *pid, vmonitor_head_t *phead) 161 { 162 int id = 0; 163 vmonitor_t *pvm; 164 165 TAILQ_FOREACH(pvm, phead, entry) 166 id++; 167 168 if (id >= 64) { 169 *pid = 0; 170 return (NULL); 171 } 172 pvm = malloc(sizeof(*pvm)); 173 if (pvm == NULL) { 174 *pid = 0; 175 return (NULL); 176 } 177 memset(pvm, 0, sizeof(*pvm)); 178 179 pvm->mute = 1; 180 181 TAILQ_INSERT_TAIL(phead, pvm, entry); 182 183 *pid = id; 184 return (pvm); 185 } 186 187 int64_t 188 vclient_noise(uint32_t *pnoise, int64_t volume, int8_t shift) 189 { 190 const uint32_t prime = 0xFFFF1DU; 191 int64_t temp; 192 193 /* compute next noise sample */ 194 temp = *pnoise; 195 if (temp & 1) 196 temp += prime; 197 temp /= 2; 198 *pnoise = temp; 199 200 /* unsigned to signed conversion */ 201 temp ^= 0x800000ULL; 202 if (temp & 0x800000U) 203 temp |= -0x800000ULL; 204 205 /* properly amplify */ 206 temp *= volume; 207 208 /* bias shift */ 209 shift -= 23 + VVOLUME_UNIT_SHIFT; 210 211 /* range check and shift noise */ 212 if (__predict_false(shift < -63 || shift > 63)) 213 temp = 0; 214 else if (shift < 0) 215 temp >>= -shift; 216 else 217 temp <<= shift; 218 219 return (temp); 220 } 221 222 static void 223 vresample_free(vresample_t *pvr) 224 { 225 if (pvr->state != NULL) 226 src_delete(pvr->state); 227 free(pvr->data_in); 228 free(pvr->data_out); 229 memset(pvr, 0, sizeof(*pvr)); 230 } 231 232 static int 233 vresample_setup(vclient_t *pvc, vresample_t *pvr, int samples) 234 { 235 int code = 0; 236 237 if (pvr->state != NULL) 238 return (0); 239 pvr->state = src_new(voss_libsamplerate_quality, pvc->channels, &code); 240 if (pvr->state == NULL) 241 goto error; 242 pvr->data_in = malloc(sizeof(float) * samples); 243 if (pvr->data_in == NULL) 244 goto error; 245 pvr->data_out = malloc(sizeof(float) * samples); 246 if (pvr->data_out == NULL) 247 goto error; 248 pvr->data.data_in = pvr->data_in; 249 pvr->data.data_out = pvr->data_out; 250 return (0); 251 error: 252 vresample_free(pvr); 253 return (CUSE_ERR_NO_MEMORY); 254 } 255 256 void 257 vclient_free(vclient_t *pvc) 258 { 259 vresample_free(&pvc->rx_resample); 260 vresample_free(&pvc->tx_resample); 261 262 /* free equalizer */ 263 vclient_eq_free(pvc); 264 265 /* free ring buffers */ 266 vring_free(&pvc->rx_ring[0]); 267 vring_free(&pvc->rx_ring[1]); 268 vring_free(&pvc->tx_ring[0]); 269 vring_free(&pvc->tx_ring[1]); 270 271 free(pvc); 272 } 273 274 vclient_t * 275 vclient_alloc(void) 276 { 277 vclient_t *pvc; 278 279 pvc = malloc(sizeof(*pvc)); 280 if (pvc == NULL) 281 return (NULL); 282 283 memset(pvc, 0, sizeof(*pvc)); 284 285 pvc->rx_noise_rem = 1; 286 pvc->tx_noise_rem = 1; 287 pvc->rx_volume = 1 << VVOLUME_UNIT_SHIFT; 288 pvc->tx_volume = 1 << VVOLUME_UNIT_SHIFT; 289 290 return (pvc); 291 } 292 293 int 294 vclient_get_default_fmt(vprofile_t *pvp, int type) 295 { 296 int retval; 297 298 if (type == VTYPE_WAV_HDR) { 299 switch (pvp->bits) { 300 case 16: 301 retval = AFMT_S16_LE; 302 break; 303 case 24: 304 retval = AFMT_S24_LE; 305 break; 306 case 32: 307 retval = AFMT_S32_LE; 308 break; 309 default: 310 retval = AFMT_S8; 311 break; 312 } 313 } else { 314 switch (pvp->bits) { 315 case 16: 316 retval = AFMT_S16_NE; 317 break; 318 case 24: 319 retval = AFMT_S24_NE; 320 break; 321 case 32: 322 retval = AFMT_S32_NE; 323 break; 324 default: 325 retval = AFMT_S8; 326 break; 327 } 328 } 329 return (retval); 330 } 331 332 int 333 vclient_setup_buffers(vclient_t *pvc, int size, int frags, 334 int channels, int format, int sample_rate) 335 { 336 size_t bufsize_internal; 337 size_t bufsize_min; 338 size_t mod_internal; 339 size_t mod; 340 uint64_t ts; 341 int bufsize; 342 343 /* check we are not busy */ 344 if (pvc->rx_busy || pvc->tx_busy) 345 return (CUSE_ERR_BUSY); 346 347 /* free equalizer */ 348 vclient_eq_free(pvc); 349 350 /* free existing ring buffers */ 351 vring_free(&pvc->rx_ring[0]); 352 vring_free(&pvc->rx_ring[1]); 353 vring_free(&pvc->tx_ring[0]); 354 vring_free(&pvc->tx_ring[1]); 355 356 /* reset resampler */ 357 vresample_free(&pvc->rx_resample); 358 vresample_free(&pvc->tx_resample); 359 360 if (sample_rate > 0) 361 pvc->sample_rate = sample_rate; 362 if (format != 0) 363 pvc->format = format; 364 if (channels > 0) 365 pvc->channels = channels; 366 367 mod = pvc->channels * vclient_sample_bytes(pvc); 368 mod_internal = pvc->channels * 8; 369 370 if (size > 0) { 371 size += mod - 1; 372 size -= size % mod; 373 374 pvc->buffer_size = size; 375 pvc->buffer_size_set = 1; 376 } else if (pvc->buffer_size_set == 0) 377 pvc->buffer_size = vclient_bufsize_scaled(pvc); 378 379 pvc->low_water = pvc->buffer_size; 380 381 if (frags > 0) { 382 pvc->buffer_frags = frags; 383 pvc->buffer_frags_set = 1; 384 } else if (pvc->buffer_frags_set == 0) 385 pvc->buffer_frags = 2; 386 387 /* sanity checks */ 388 if (frags < 0 || size < 0) 389 return (CUSE_ERR_INVALID); 390 if (pvc->format == 0) 391 return (CUSE_ERR_INVALID); 392 if (pvc->buffer_frags <= 0 || pvc->buffer_frags >= 1024) 393 return (CUSE_ERR_INVALID); 394 if (pvc->buffer_size <= 0 || pvc->buffer_size >= (1024 * 1024)) 395 return (CUSE_ERR_INVALID); 396 if ((pvc->buffer_size * pvc->buffer_frags) >= (128 * 1024 * 1024)) 397 return (CUSE_ERR_INVALID); 398 if (pvc->channels <= 0 || pvc->channels > pvc->profile->channels) 399 return (CUSE_ERR_INVALID); 400 401 /* get buffer sizes */ 402 bufsize = pvc->buffer_frags * pvc->buffer_size; 403 bufsize_internal = ((uint64_t)bufsize * (uint64_t)voss_dsp_sample_rate * 8ULL) / 404 ((uint64_t)pvc->sample_rate * (uint64_t)vclient_sample_bytes(pvc)); 405 406 bufsize_min = voss_dsp_samples * pvc->channels * 8; 407 408 /* check for too small buffer size */ 409 if (bufsize_internal < bufsize_min) 410 return (CUSE_ERR_INVALID); 411 412 /* allow for jitter */ 413 bufsize_internal *= 2ULL; 414 415 /* align buffer size */ 416 bufsize_internal += (mod_internal - 1); 417 bufsize_internal -= (bufsize_internal % mod_internal); 418 419 /* allocate new buffers */ 420 if (vring_alloc(&pvc->rx_ring[0], bufsize_internal)) 421 goto err_0; 422 if (vring_alloc(&pvc->rx_ring[1], bufsize)) 423 goto err_1; 424 if (vring_alloc(&pvc->tx_ring[0], bufsize_internal)) 425 goto err_2; 426 if (vring_alloc(&pvc->tx_ring[1], bufsize)) 427 goto err_3; 428 if (vclient_eq_alloc(pvc)) 429 goto err_4; 430 431 ts = virtual_oss_timestamp(); 432 433 pvc->rx_samples = 0; 434 pvc->tx_samples = 0; 435 pvc->tx_timestamp = ts; 436 pvc->rx_timestamp = ts; 437 438 return (0); 439 440 err_4: 441 vring_free(&pvc->tx_ring[1]); 442 err_3: 443 vring_free(&pvc->tx_ring[0]); 444 err_2: 445 vring_free(&pvc->rx_ring[1]); 446 err_1: 447 vring_free(&pvc->rx_ring[0]); 448 err_0: 449 return (CUSE_ERR_NO_MEMORY); 450 } 451 452 static int 453 vclient_open_sub(struct cuse_dev *pdev, int fflags __unused, int type) 454 { 455 vclient_t *pvc; 456 vprofile_t *pvp; 457 int error; 458 459 pvp = cuse_dev_get_priv0(pdev); 460 461 pvc = vclient_alloc(); 462 if (pvc == NULL) 463 return (CUSE_ERR_NO_MEMORY); 464 465 pvc->profile = pvp; 466 467 /* setup buffers */ 468 error = vclient_setup_buffers(pvc, 0, 0, pvp->channels, 469 vclient_get_default_fmt(pvp, type), voss_dsp_sample_rate); 470 if (error != 0) { 471 vclient_free(pvc); 472 return (error); 473 } 474 475 pvc->type = type; 476 477 cuse_dev_set_per_file_handle(pdev, pvc); 478 479 atomic_lock(); 480 /* only allow one synchronization source at a time */ 481 if (pvc->profile->synchronized) { 482 if (voss_has_synchronization != 0) 483 error = CUSE_ERR_BUSY; 484 else 485 voss_has_synchronization++; 486 } 487 if (error == 0) 488 TAILQ_INSERT_TAIL(&pvc->profile->head, pvc, entry); 489 atomic_unlock(); 490 491 return (error); 492 } 493 494 static int 495 vclient_open_wav(struct cuse_dev *pdev, int fflags) 496 { 497 return (vclient_open_sub(pdev, fflags, VTYPE_WAV_HDR)); 498 } 499 500 static int 501 vclient_open_oss(struct cuse_dev *pdev, int fflags) 502 { 503 return (vclient_open_sub(pdev, fflags, VTYPE_OSS_DAT)); 504 } 505 506 static int 507 vclient_close(struct cuse_dev *pdev, int fflags __unused) 508 { 509 vclient_t *pvc; 510 511 pvc = cuse_dev_get_per_file_handle(pdev); 512 if (pvc == NULL) 513 return (CUSE_ERR_INVALID); 514 515 atomic_lock(); 516 if (pvc->profile->synchronized) { 517 voss_has_synchronization--; 518 519 /* wait for virtual_oss_process(), if any */ 520 while (pvc->sync_busy) { 521 pvc->sync_wakeup = 1; 522 atomic_wakeup(); 523 atomic_wait(); 524 } 525 } 526 TAILQ_REMOVE(&pvc->profile->head, pvc, entry); 527 atomic_unlock(); 528 529 vclient_free(pvc); 530 531 return (0); 532 } 533 534 static int 535 vclient_read_silence_locked(vclient_t *pvc) 536 { 537 size_t size; 538 int delta_in; 539 540 delta_in = pvc->profile->rec_delay - pvc->rec_delay; 541 if (delta_in < 1) 542 return (0); 543 544 size = delta_in * pvc->channels * 8; 545 size = vring_write_zero(&pvc->rx_ring[0], size); 546 pvc->rec_delay += size / (pvc->channels * 8); 547 548 delta_in = pvc->profile->rec_delay - pvc->rec_delay; 549 if (delta_in < 1) 550 return (0); 551 552 return (1); 553 } 554 555 static int 556 vclient_generate_wav_header_locked(vclient_t *pvc) 557 { 558 uint8_t *ptr; 559 size_t mod; 560 size_t len; 561 562 vring_get_write(&pvc->rx_ring[1], &ptr, &len); 563 564 mod = pvc->channels * vclient_sample_bytes(pvc); 565 566 if (mod == 0 || len < (44 + mod - 1)) 567 return (CUSE_ERR_INVALID); 568 569 /* align to next sample */ 570 len = 44 + mod - 1; 571 len -= len % mod; 572 573 /* pre-advance write pointer */ 574 vring_inc_write(&pvc->rx_ring[1], len); 575 576 /* clear block */ 577 memset(ptr, 0, len); 578 579 /* fill out data header */ 580 ptr[len - 8] = 'd'; 581 ptr[len - 7] = 'a'; 582 ptr[len - 6] = 't'; 583 ptr[len - 5] = 'a'; 584 585 /* magic for unspecified length */ 586 ptr[len - 4] = 0x00; 587 ptr[len - 3] = 0xF0; 588 ptr[len - 2] = 0xFF; 589 ptr[len - 1] = 0x7F; 590 591 /* fill out header */ 592 *ptr++ = 'R'; 593 *ptr++ = 'I'; 594 *ptr++ = 'F'; 595 *ptr++ = 'F'; 596 597 /* total chunk size - unknown */ 598 599 *ptr++ = 0; 600 *ptr++ = 0; 601 *ptr++ = 0; 602 *ptr++ = 0; 603 604 *ptr++ = 'W'; 605 *ptr++ = 'A'; 606 *ptr++ = 'V'; 607 *ptr++ = 'E'; 608 *ptr++ = 'f'; 609 *ptr++ = 'm'; 610 *ptr++ = 't'; 611 *ptr++ = ' '; 612 613 /* make sure header fits in PCM block */ 614 len -= 28; 615 616 *ptr++ = len; 617 *ptr++ = len >> 8; 618 *ptr++ = len >> 16; 619 *ptr++ = len >> 24; 620 621 /* audioformat = PCM */ 622 623 *ptr++ = 0x01; 624 *ptr++ = 0x00; 625 626 /* number of channels */ 627 628 len = pvc->channels; 629 630 *ptr++ = len; 631 *ptr++ = len >> 8; 632 633 /* sample rate */ 634 635 len = pvc->sample_rate; 636 637 *ptr++ = len; 638 *ptr++ = len >> 8; 639 *ptr++ = len >> 16; 640 *ptr++ = len >> 24; 641 642 /* byte rate */ 643 644 len = pvc->sample_rate * pvc->channels * vclient_sample_bytes(pvc); 645 646 *ptr++ = len; 647 *ptr++ = len >> 8; 648 *ptr++ = len >> 16; 649 *ptr++ = len >> 24; 650 651 /* block align */ 652 653 len = pvc->channels * vclient_sample_bytes(pvc); 654 655 *ptr++ = len; 656 *ptr++ = len >> 8; 657 658 /* bits per sample */ 659 660 len = vclient_sample_bytes(pvc) * 8; 661 662 *ptr++ = len; 663 *ptr++ = len >> 8; 664 665 return (0); 666 } 667 668 int 669 vclient_export_read_locked(vclient_t *pvc) __requires_exclusive(atomic_mtx) 670 { 671 enum { MAX_FRAME = 1024 }; 672 size_t dst_mod; 673 size_t src_mod; 674 int error; 675 676 if (pvc->type == VTYPE_WAV_HDR) { 677 error = vclient_generate_wav_header_locked(pvc); 678 if (error != 0) 679 return (error); 680 /* only write header once */ 681 pvc->type = VTYPE_WAV_DAT; 682 } 683 error = vclient_read_silence_locked(pvc); 684 if (error != 0) 685 return (0); 686 687 dst_mod = pvc->channels * vclient_sample_bytes(pvc); 688 src_mod = pvc->channels * 8; 689 690 if (pvc->sample_rate == (int)voss_dsp_sample_rate) { 691 while (1) { 692 uint8_t *src_ptr; 693 size_t src_len; 694 uint8_t *dst_ptr; 695 size_t dst_len; 696 697 vring_get_read(&pvc->rx_ring[0], &src_ptr, &src_len); 698 vring_get_write(&pvc->rx_ring[1], &dst_ptr, &dst_len); 699 700 src_len /= src_mod; 701 dst_len /= dst_mod; 702 703 /* compare number of samples */ 704 if (dst_len > src_len) 705 dst_len = src_len; 706 else 707 src_len = dst_len; 708 709 if (dst_len == 0) 710 break; 711 712 src_len *= src_mod; 713 dst_len *= dst_mod; 714 715 format_export(pvc->format, 716 (const int64_t *)(uintptr_t)src_ptr, 717 dst_ptr, dst_len); 718 719 vring_inc_read(&pvc->rx_ring[0], src_len); 720 vring_inc_write(&pvc->rx_ring[1], dst_len); 721 } 722 } else { 723 vresample_t *pvr = &pvc->rx_resample; 724 725 if (vresample_setup(pvc, pvr, MAX_FRAME * pvc->channels) != 0) 726 return (CUSE_ERR_NO_MEMORY); 727 728 while (1) { 729 uint8_t *src_ptr; 730 size_t src_len; 731 uint8_t *dst_ptr; 732 size_t dst_len; 733 int64_t temp[MAX_FRAME * pvc->channels]; 734 size_t samples; 735 size_t y; 736 737 vring_get_read(&pvc->rx_ring[0], &src_ptr, &src_len); 738 vring_get_write(&pvc->rx_ring[1], &dst_ptr, &dst_len); 739 740 src_len /= src_mod; 741 dst_len /= dst_mod; 742 743 /* compare number of samples */ 744 if (dst_len > src_len) 745 dst_len = src_len; 746 else 747 src_len = dst_len; 748 749 if (dst_len > MAX_FRAME) 750 dst_len = src_len = MAX_FRAME; 751 752 if (dst_len == 0) 753 break; 754 755 src_len *= src_mod; 756 dst_len *= dst_mod; 757 758 for (y = 0; y != src_len; y += 8) { 759 pvr->data_in[y / 8] = 760 *(int64_t *)(uintptr_t)(src_ptr + y); 761 } 762 763 /* setup parameters for transform */ 764 pvr->data.input_frames = src_len / src_mod; 765 pvr->data.output_frames = dst_len / dst_mod; 766 pvr->data.src_ratio = (float)pvc->sample_rate / (float)voss_dsp_sample_rate; 767 768 pvc->rx_busy = 1; 769 atomic_unlock(); 770 error = src_process(pvr->state, &pvr->data); 771 atomic_lock(); 772 pvc->rx_busy = 0; 773 774 if (error != 0) 775 break; 776 777 src_len = pvr->data.input_frames_used * src_mod; 778 dst_len = pvr->data.output_frames_gen * dst_mod; 779 780 samples = pvr->data.output_frames_gen * pvc->channels; 781 782 for (y = 0; y != samples; y++) 783 temp[y] = pvr->data_out[y]; 784 785 format_export(pvc->format, temp, dst_ptr, dst_len); 786 787 vring_inc_read(&pvc->rx_ring[0], src_len); 788 vring_inc_write(&pvc->rx_ring[1], dst_len); 789 790 /* check if no data was moved */ 791 if (src_len == 0 && dst_len == 0) 792 break; 793 } 794 } 795 if (pvc->sync_busy) 796 atomic_wakeup(); 797 return (0); 798 } 799 800 static int 801 vclient_read(struct cuse_dev *pdev, int fflags, 802 void *peer_ptr, int len) 803 { 804 vclient_t *pvc; 805 806 int error; 807 int retval; 808 809 pvc = cuse_dev_get_per_file_handle(pdev); 810 if (pvc == NULL) 811 return (CUSE_ERR_INVALID); 812 813 atomic_lock(); 814 815 if (pvc->rx_busy) { 816 atomic_unlock(); 817 return (CUSE_ERR_BUSY); 818 } 819 pvc->rx_enabled = 1; 820 821 retval = 0; 822 823 while (len > 0) { 824 uint8_t *buf_ptr; 825 size_t buf_len; 826 827 error = vclient_export_read_locked(pvc); 828 if (error != 0) { 829 retval = error; 830 break; 831 } 832 833 vring_get_read(&pvc->rx_ring[1], &buf_ptr, &buf_len); 834 835 if (buf_len == 0) { 836 /* out of data */ 837 if (fflags & CUSE_FFLAG_NONBLOCK) { 838 if (retval == 0) 839 retval = CUSE_ERR_WOULDBLOCK; 840 break; 841 } 842 pvc->rx_busy = 1; 843 atomic_wait(); 844 pvc->rx_busy = 0; 845 if (cuse_got_peer_signal() == 0) { 846 if (retval == 0) 847 retval = CUSE_ERR_SIGNAL; 848 break; 849 } 850 continue; 851 } 852 if ((int)buf_len > len) 853 buf_len = len; 854 855 pvc->rx_busy = 1; 856 atomic_unlock(); 857 error = cuse_copy_out(buf_ptr, peer_ptr, buf_len); 858 atomic_lock(); 859 pvc->rx_busy = 0; 860 861 if (error != 0) { 862 retval = error; 863 break; 864 } 865 peer_ptr = ((uint8_t *)peer_ptr) + buf_len; 866 retval += buf_len; 867 len -= buf_len; 868 869 vring_inc_read(&pvc->rx_ring[1], buf_len); 870 } 871 atomic_unlock(); 872 873 return (retval); 874 } 875 876 void 877 vclient_import_write_locked(vclient_t *pvc) __requires_exclusive(atomic_mtx) 878 { 879 enum { MAX_FRAME = 1024 }; 880 size_t dst_mod; 881 size_t src_mod; 882 883 dst_mod = pvc->channels * 8; 884 src_mod = pvc->channels * vclient_sample_bytes(pvc); 885 886 if (pvc->sample_rate == (int)voss_dsp_sample_rate) { 887 while (1) { 888 uint8_t *src_ptr; 889 size_t src_len; 890 uint8_t *dst_ptr; 891 size_t dst_len; 892 893 vring_get_read(&pvc->tx_ring[1], &src_ptr, &src_len); 894 vring_get_write(&pvc->tx_ring[0], &dst_ptr, &dst_len); 895 896 src_len /= src_mod; 897 dst_len /= dst_mod; 898 899 /* compare number of samples */ 900 if (dst_len > src_len) 901 dst_len = src_len; 902 else 903 src_len = dst_len; 904 905 if (dst_len == 0) 906 break; 907 908 src_len *= src_mod; 909 dst_len *= dst_mod; 910 911 format_import(pvc->format, src_ptr, src_len, 912 (int64_t *)(uintptr_t)dst_ptr); 913 914 vring_inc_read(&pvc->tx_ring[1], src_len); 915 vring_inc_write(&pvc->tx_ring[0], dst_len); 916 } 917 } else { 918 vresample_t *pvr = &pvc->tx_resample; 919 920 if (vresample_setup(pvc, pvr, MAX_FRAME * pvc->channels) != 0) 921 return; 922 923 while (1) { 924 uint8_t *src_ptr; 925 size_t src_len; 926 uint8_t *dst_ptr; 927 size_t dst_len; 928 int64_t temp[MAX_FRAME * pvc->channels]; 929 size_t samples; 930 size_t y; 931 int error; 932 933 vring_get_read(&pvc->tx_ring[1], &src_ptr, &src_len); 934 vring_get_write(&pvc->tx_ring[0], &dst_ptr, &dst_len); 935 936 src_len /= src_mod; 937 dst_len /= dst_mod; 938 939 /* compare number of samples */ 940 if (dst_len > src_len) 941 dst_len = src_len; 942 else 943 src_len = dst_len; 944 945 if (dst_len > MAX_FRAME) 946 dst_len = src_len = MAX_FRAME; 947 948 if (dst_len == 0) 949 break; 950 951 src_len *= src_mod; 952 dst_len *= dst_mod; 953 954 format_import(pvc->format, src_ptr, src_len, temp); 955 956 src_len /= vclient_sample_bytes(pvc); 957 958 for (y = 0; y != src_len; y++) 959 pvr->data_in[y] = temp[y]; 960 961 src_len *= vclient_sample_bytes(pvc); 962 963 /* setup parameters for transform */ 964 pvr->data.input_frames = src_len / src_mod; 965 pvr->data.output_frames = dst_len / dst_mod; 966 pvr->data.src_ratio = (float)voss_dsp_sample_rate / (float)pvc->sample_rate; 967 968 pvc->tx_busy = 1; 969 atomic_unlock(); 970 error = src_process(pvr->state, &pvr->data); 971 atomic_lock(); 972 pvc->tx_busy = 0; 973 974 if (error != 0) 975 break; 976 977 src_len = pvr->data.input_frames_used * src_mod; 978 dst_len = pvr->data.output_frames_gen * dst_mod; 979 980 samples = pvr->data.output_frames_gen * pvc->channels; 981 982 for (y = 0; y != samples; y++) { 983 ((int64_t *)(uintptr_t)dst_ptr)[y] = 984 pvr->data_out[y]; 985 } 986 987 vring_inc_read(&pvc->tx_ring[1], src_len); 988 vring_inc_write(&pvc->tx_ring[0], dst_len); 989 990 /* check if no data was moved */ 991 if (src_len == 0 && dst_len == 0) 992 break; 993 } 994 } 995 if (pvc->sync_busy) 996 atomic_wakeup(); 997 } 998 999 static int 1000 vclient_write_oss(struct cuse_dev *pdev, int fflags, 1001 const void *peer_ptr, int len) 1002 { 1003 vclient_t *pvc; 1004 1005 int error; 1006 int retval; 1007 1008 pvc = cuse_dev_get_per_file_handle(pdev); 1009 if (pvc == NULL) 1010 return (CUSE_ERR_INVALID); 1011 1012 retval = 0; 1013 1014 atomic_lock(); 1015 1016 if (pvc->tx_busy) { 1017 atomic_unlock(); 1018 return (CUSE_ERR_BUSY); 1019 } 1020 pvc->tx_enabled = 1; 1021 1022 while (1) { 1023 uint8_t *buf_ptr; 1024 size_t buf_len; 1025 1026 vclient_import_write_locked(pvc); 1027 1028 if (len < 1) 1029 break; 1030 1031 vring_get_write(&pvc->tx_ring[1], &buf_ptr, &buf_len); 1032 1033 if (buf_len == 0) { 1034 /* out of data */ 1035 if (fflags & CUSE_FFLAG_NONBLOCK) { 1036 if (retval == 0) 1037 retval = CUSE_ERR_WOULDBLOCK; 1038 break; 1039 } 1040 pvc->tx_busy = 1; 1041 atomic_wait(); 1042 pvc->tx_busy = 0; 1043 if (cuse_got_peer_signal() == 0) { 1044 if (retval == 0) 1045 retval = CUSE_ERR_SIGNAL; 1046 break; 1047 } 1048 continue; 1049 } 1050 if ((int)buf_len > len) 1051 buf_len = len; 1052 1053 pvc->tx_busy = 1; 1054 atomic_unlock(); 1055 error = cuse_copy_in(peer_ptr, buf_ptr, buf_len); 1056 atomic_lock(); 1057 pvc->tx_busy = 0; 1058 1059 if (error != 0) { 1060 retval = error; 1061 break; 1062 } 1063 peer_ptr = ((const uint8_t *)peer_ptr) + buf_len; 1064 retval += buf_len; 1065 len -= buf_len; 1066 1067 vring_inc_write(&pvc->tx_ring[1], buf_len); 1068 } 1069 atomic_unlock(); 1070 1071 return (retval); 1072 } 1073 1074 static int 1075 vclient_write_wav(struct cuse_dev *pdev __unused, int fflags __unused, 1076 const void *peer_ptr __unused, int len __unused) 1077 { 1078 return (CUSE_ERR_INVALID); 1079 } 1080 1081 static int 1082 vclient_set_channels(vclient_t *pvc, int channels) 1083 { 1084 if (pvc->channels == channels) 1085 return (0); 1086 return (vclient_setup_buffers(pvc, 0, 0, channels, 0, 0)); 1087 } 1088 1089 /* greatest common divisor, Euclid equation */ 1090 static uint64_t 1091 vclient_gcd_64(uint64_t a, uint64_t b) 1092 { 1093 uint64_t an; 1094 uint64_t bn; 1095 1096 while (b != 0) { 1097 an = b; 1098 bn = a % b; 1099 a = an; 1100 b = bn; 1101 } 1102 return (a); 1103 } 1104 1105 static uint64_t 1106 vclient_scale(uint64_t value, uint64_t mul, uint64_t div) 1107 { 1108 uint64_t gcd = vclient_gcd_64(mul, div); 1109 1110 mul /= gcd; 1111 div /= gcd; 1112 1113 return ((value * mul) / div); 1114 } 1115 1116 static int 1117 vclient_ioctl_oss(struct cuse_dev *pdev, int fflags __unused, 1118 unsigned long cmd, void *peer_data) 1119 { 1120 union { 1121 int val; 1122 unsigned long long lval; 1123 oss_sysinfo sysinfo; 1124 oss_card_info card_info; 1125 oss_audioinfo audioinfo; 1126 audio_buf_info buf_info; 1127 oss_count_t oss_count; 1128 count_info oss_count_info; 1129 audio_errinfo errinfo; 1130 oss_label_t label; 1131 oss_longname_t longname; 1132 } data; 1133 1134 vclient_t *pvc; 1135 1136 uint64_t bytes; 1137 1138 int len; 1139 int error; 1140 int temp; 1141 1142 pvc = cuse_dev_get_per_file_handle(pdev); 1143 if (pvc == NULL) 1144 return (CUSE_ERR_INVALID); 1145 1146 len = IOCPARM_LEN(cmd); 1147 1148 if (len < 0 || len > (int)sizeof(data)) 1149 return (CUSE_ERR_INVALID); 1150 1151 if (cmd & IOC_IN) { 1152 error = cuse_copy_in(peer_data, &data, len); 1153 if (error) 1154 return (error); 1155 } else { 1156 error = 0; 1157 } 1158 1159 atomic_lock(); 1160 1161 switch (cmd) { 1162 case OSS_GETVERSION: 1163 data.val = SOUND_VERSION; 1164 break; 1165 case SNDCTL_SYSINFO: 1166 memset(&data.sysinfo, 0, sizeof(data.sysinfo)); 1167 strcpy(data.sysinfo.product, "VOSS"); 1168 strcpy(data.sysinfo.version, "1.0"); 1169 data.sysinfo.versionnum = SOUND_VERSION; 1170 data.sysinfo.numaudios = 1; 1171 data.sysinfo.numcards = 1; 1172 data.sysinfo.numaudioengines = 1; 1173 strcpy(data.sysinfo.license, "BSD"); 1174 memset(data.sysinfo.filler, -1, sizeof(data.sysinfo.filler)); 1175 break; 1176 case SNDCTL_CARDINFO: 1177 memset(&data.card_info, 0, sizeof(data.card_info)); 1178 strlcpy(data.card_info.shortname, pvc->profile->oss_name, 1179 sizeof(data.card_info.shortname)); 1180 break; 1181 case SNDCTL_AUDIOINFO: 1182 case SNDCTL_AUDIOINFO_EX: 1183 case SNDCTL_ENGINEINFO: 1184 memset(&data.audioinfo, 0, sizeof(data.audioinfo)); 1185 strlcpy(data.audioinfo.name, pvc->profile->oss_name, 1186 sizeof(data.audioinfo.name)); 1187 snprintf(data.audioinfo.devnode, sizeof(data.audioinfo.devnode), 1188 "/dev/%s", pvc->profile->oss_name); 1189 data.audioinfo.caps = DSP_CAP_INPUT | DSP_CAP_OUTPUT; 1190 data.audioinfo.iformats = VSUPPORTED_AFMT; 1191 data.audioinfo.oformats = VSUPPORTED_AFMT; 1192 data.audioinfo.enabled = 1; 1193 data.audioinfo.min_rate = (int)8000; 1194 data.audioinfo.max_rate = (int)voss_dsp_sample_rate; 1195 data.audioinfo.max_channels = pvc->profile->channels; 1196 /* range check */ 1197 if (voss_libsamplerate_enable == 0 || 1198 data.audioinfo.min_rate > data.audioinfo.max_rate) 1199 data.audioinfo.min_rate = data.audioinfo.max_rate; 1200 data.audioinfo.nrates = 1; 1201 data.audioinfo.rates[0] = (int)voss_dsp_sample_rate; 1202 if (voss_libsamplerate_enable != 0 && 1203 96000 != voss_dsp_sample_rate) 1204 data.audioinfo.rates[data.audioinfo.nrates++] = 96000; 1205 if (voss_libsamplerate_enable != 0 && 1206 48000 != voss_dsp_sample_rate) 1207 data.audioinfo.rates[data.audioinfo.nrates++] = 48000; 1208 if (voss_libsamplerate_enable != 0 && 1209 44100 != voss_dsp_sample_rate) 1210 data.audioinfo.rates[data.audioinfo.nrates++] = 44100; 1211 if (voss_libsamplerate_enable != 0 && 1212 24000 != voss_dsp_sample_rate) 1213 data.audioinfo.rates[data.audioinfo.nrates++] = 24000; 1214 if (voss_libsamplerate_enable != 0 && 1215 16000 != voss_dsp_sample_rate) 1216 data.audioinfo.rates[data.audioinfo.nrates++] = 16000; 1217 if (voss_libsamplerate_enable != 0 && 1218 8000 != voss_dsp_sample_rate) 1219 data.audioinfo.rates[data.audioinfo.nrates++] = 8000; 1220 data.audioinfo.latency = -1; 1221 break; 1222 case FIONREAD: 1223 data.val = vclient_input_delay(pvc); 1224 break; 1225 case FIONWRITE: 1226 data.val = vring_total_read_len(&pvc->tx_ring[1]); 1227 break; 1228 case FIOASYNC: 1229 case SNDCTL_DSP_NONBLOCK: 1230 case FIONBIO: 1231 break; 1232 case SNDCTL_DSP_SETBLKSIZE: 1233 case _IOWR('P', 4, int): 1234 error = vclient_setup_buffers(pvc, data.val, 0, 0, 0, 0); 1235 /* FALLTHROUGH */ 1236 case SNDCTL_DSP_GETBLKSIZE: 1237 data.val = pvc->buffer_size; 1238 break; 1239 case SNDCTL_DSP_SETFRAGMENT: 1240 if ((data.val & 0xFFFF) < 4) { 1241 /* need at least 16 bytes of buffer */ 1242 data.val &= ~0xFFFF; 1243 data.val |= 4; 1244 } else if ((data.val & 0xFFFF) > 24) { 1245 /* no more than 16MBytes of buffer */ 1246 data.val &= ~0xFFFF; 1247 data.val |= 24; 1248 } 1249 error = vclient_setup_buffers(pvc, 1250 (1 << (data.val & 0xFFFF)), (data.val >> 16), 0, 0, 0); 1251 if (error) { 1252 /* fallback to defaults */ 1253 pvc->buffer_size_set = 0; 1254 pvc->buffer_frags_set = 0; 1255 error = vclient_setup_buffers(pvc, 0, 0, 0, 0, 0); 1256 if (error) 1257 break; 1258 /* figure out log2() of actual buffer size */ 1259 for (data.val = 0; 1260 data.val < 24 && (1U << data.val) < pvc->buffer_size; 1261 data.val++) 1262 ; 1263 /* or in the actual number of fragments */ 1264 data.val |= (pvc->buffer_frags << 16); 1265 } 1266 break; 1267 case SNDCTL_DSP_RESET: 1268 error = vclient_setup_buffers(pvc, 0, 0, 0, 0, 0); 1269 break; 1270 case SNDCTL_DSP_SYNC: 1271 break; 1272 case SNDCTL_DSP_SPEED: 1273 if (data.val >= 8000 && data.val <= 96000 && 1274 voss_libsamplerate_enable != 0) { 1275 error = vclient_setup_buffers(pvc, 0, 0, 0, 0, data.val); 1276 } 1277 /* return current speed */ 1278 data.val = (int)pvc->sample_rate; 1279 break; 1280 case SOUND_PCM_READ_RATE: 1281 data.val = (int)pvc->sample_rate; 1282 break; 1283 case SNDCTL_DSP_STEREO: 1284 if (data.val != 0) { 1285 error = vclient_set_channels(pvc, 2); 1286 } else { 1287 error = vclient_set_channels(pvc, 1); 1288 } 1289 data.val = (pvc->channels == 2); 1290 break; 1291 case SOUND_PCM_WRITE_CHANNELS: 1292 if (data.val < 0) { 1293 data.val = 0; 1294 error = CUSE_ERR_INVALID; 1295 break; 1296 } 1297 if (data.val == 0) { 1298 data.val = pvc->channels; 1299 } else { 1300 error = vclient_set_channels(pvc, data.val); 1301 } 1302 break; 1303 case SOUND_PCM_READ_CHANNELS: 1304 data.val = pvc->channels; 1305 break; 1306 case AIOGFMT: 1307 case SNDCTL_DSP_GETFMTS: 1308 data.val = VSUPPORTED_AFMT | AFMT_FULLDUPLEX | 1309 (pvc->profile->channels > 1 ? AFMT_STEREO : 0); 1310 break; 1311 case AIOSFMT: 1312 case SNDCTL_DSP_SETFMT: 1313 if (data.val != AFMT_QUERY) { 1314 temp = data.val & VSUPPORTED_AFMT; 1315 if (temp == 0 || (temp & (temp - 1)) != 0) { 1316 error = CUSE_ERR_INVALID; 1317 } else { 1318 error = vclient_setup_buffers(pvc, 0, 0, 0, temp, 0); 1319 } 1320 } else { 1321 data.val = pvc->format; 1322 } 1323 break; 1324 case SNDCTL_DSP_GETISPACE: 1325 memset(&data.buf_info, 0, sizeof(data.buf_info)); 1326 data.buf_info.fragsize = pvc->buffer_size; 1327 data.buf_info.fragstotal = pvc->buffer_frags; 1328 bytes = (pvc->buffer_size * pvc->buffer_frags); 1329 temp = vclient_input_delay(pvc); 1330 if (temp < 0 || (uint64_t)temp > bytes) 1331 temp = bytes; 1332 data.buf_info.fragments = temp / pvc->buffer_size; 1333 data.buf_info.bytes = temp; 1334 break; 1335 case SNDCTL_DSP_GETOSPACE: 1336 memset(&data.buf_info, 0, sizeof(data.buf_info)); 1337 data.buf_info.fragsize = pvc->buffer_size; 1338 data.buf_info.fragstotal = pvc->buffer_frags; 1339 bytes = (pvc->buffer_size * pvc->buffer_frags); 1340 temp = vclient_output_delay(pvc); 1341 if (temp < 0 || (uint64_t)temp >= bytes) { 1342 /* buffer is full */ 1343 data.buf_info.fragments = 0; 1344 data.buf_info.bytes = 0; 1345 } else { 1346 /* buffer is not full */ 1347 bytes -= temp; 1348 data.buf_info.fragments = bytes / pvc->buffer_size; 1349 data.buf_info.bytes = bytes; 1350 } 1351 break; 1352 case SNDCTL_DSP_GETCAPS: 1353 data.val = PCM_CAP_REALTIME | PCM_CAP_DUPLEX | 1354 PCM_CAP_INPUT | PCM_CAP_OUTPUT | PCM_CAP_TRIGGER | 1355 PCM_CAP_VIRTUAL; 1356 break; 1357 case SOUND_PCM_READ_BITS: 1358 data.val = vclient_sample_bytes(pvc) * 8; 1359 break; 1360 case SNDCTL_DSP_SETTRIGGER: 1361 if (data.val & PCM_ENABLE_INPUT) { 1362 pvc->rx_enabled = 1; 1363 } else { 1364 pvc->rx_enabled = 0; 1365 vring_reset(&pvc->rx_ring[1]); 1366 } 1367 1368 if (data.val & PCM_ENABLE_OUTPUT) { 1369 pvc->tx_enabled = 1; 1370 } else { 1371 pvc->tx_enabled = 0; 1372 vring_reset(&pvc->tx_ring[1]); 1373 } 1374 break; 1375 case SNDCTL_DSP_GETTRIGGER: 1376 data.val = 0; 1377 if (pvc->rx_enabled) 1378 data.val |= PCM_ENABLE_INPUT; 1379 if (pvc->tx_enabled) 1380 data.val |= PCM_ENABLE_OUTPUT; 1381 break; 1382 case SNDCTL_DSP_GETODELAY: 1383 data.val = vclient_output_delay_adjusted(pvc); 1384 break; 1385 case SNDCTL_DSP_POST: 1386 break; 1387 case SNDCTL_DSP_SETDUPLEX: 1388 break; 1389 case SNDCTL_DSP_GETRECVOL: 1390 temp = (pvc->rx_volume * 100) >> VVOLUME_UNIT_SHIFT; 1391 data.val = (temp & 0x00FF) | 1392 ((temp << 8) & 0xFF00); 1393 break; 1394 case SNDCTL_DSP_SETRECVOL: 1395 pvc->rx_volume = ((data.val & 0xFF) << VVOLUME_UNIT_SHIFT) / 100; 1396 break; 1397 case SNDCTL_DSP_GETPLAYVOL: 1398 temp = (pvc->tx_volume * 100) >> VVOLUME_UNIT_SHIFT; 1399 data.val = (temp & 0x00FF) | 1400 ((temp << 8) & 0xFF00); 1401 break; 1402 case SNDCTL_DSP_SETPLAYVOL: 1403 pvc->tx_volume = ((data.val & 0xFF) << VVOLUME_UNIT_SHIFT) / 100; 1404 break; 1405 case SNDCTL_DSP_CURRENT_IPTR: 1406 memset(&data.oss_count, 0, sizeof(data.oss_count)); 1407 /* compute input samples per channel */ 1408 data.oss_count.samples = 1409 vclient_scale(pvc->rx_samples, pvc->sample_rate, voss_dsp_sample_rate); 1410 data.oss_count.samples /= pvc->channels; 1411 data.oss_count.fifo_samples = 1412 vclient_input_delay(pvc) / (pvc->channels * vclient_sample_bytes(pvc)); 1413 break; 1414 case SNDCTL_DSP_CURRENT_OPTR: 1415 memset(&data.oss_count, 0, sizeof(data.oss_count)); 1416 /* compute output samples per channel */ 1417 data.oss_count.samples = 1418 vclient_scale(pvc->tx_samples, pvc->sample_rate, voss_dsp_sample_rate); 1419 data.oss_count.samples /= pvc->channels; 1420 data.oss_count.fifo_samples = 1421 vclient_output_delay(pvc) / (pvc->channels * vclient_sample_bytes(pvc)); 1422 break; 1423 case SNDCTL_DSP_GETIPTR: 1424 memset(&data.oss_count_info, 0, sizeof(data.oss_count_info)); 1425 /* compute input bytes */ 1426 bytes = 1427 vclient_scale(pvc->rx_samples, pvc->sample_rate, voss_dsp_sample_rate) * 1428 vclient_sample_bytes(pvc); 1429 data.oss_count_info.bytes = bytes; 1430 data.oss_count_info.blocks = bytes / pvc->buffer_size; 1431 data.oss_count_info.ptr = bytes % (pvc->buffer_size * pvc->buffer_frags); 1432 break; 1433 case SNDCTL_DSP_GETOPTR: 1434 memset(&data.oss_count_info, 0, sizeof(data.oss_count_info)); 1435 /* compute output bytes */ 1436 bytes = 1437 vclient_scale(pvc->tx_samples, pvc->sample_rate, voss_dsp_sample_rate) * 1438 vclient_sample_bytes(pvc); 1439 data.oss_count_info.bytes = bytes; 1440 data.oss_count_info.blocks = bytes / pvc->buffer_size; 1441 data.oss_count_info.ptr = bytes % (pvc->buffer_size * pvc->buffer_frags); 1442 break; 1443 case SNDCTL_DSP_HALT_OUTPUT: 1444 pvc->tx_enabled = 0; 1445 break; 1446 case SNDCTL_DSP_HALT_INPUT: 1447 pvc->rx_enabled = 0; 1448 break; 1449 case SNDCTL_DSP_LOW_WATER: 1450 if (data.val > 0 && data.val < 1451 (int)(pvc->buffer_frags * pvc->buffer_size)) { 1452 pvc->low_water = data.val; 1453 } else { 1454 error = CUSE_ERR_INVALID; 1455 } 1456 break; 1457 case SNDCTL_DSP_GETERROR: 1458 memset(&data.errinfo, 0, sizeof(data.errinfo)); 1459 break; 1460 case SNDCTL_DSP_SYNCGROUP: 1461 case SNDCTL_DSP_SYNCSTART: 1462 break; 1463 case SNDCTL_DSP_POLICY: 1464 break; 1465 case SNDCTL_DSP_COOKEDMODE: 1466 break; 1467 case SNDCTL_DSP_GET_CHNORDER: 1468 data.lval = CHNORDER_NORMAL; 1469 break; 1470 case SNDCTL_DSP_GETCHANNELMASK: 1471 data.val = DSP_BIND_FRONT; 1472 break; 1473 case SNDCTL_DSP_BIND_CHANNEL: 1474 break; 1475 case SNDCTL_GETLABEL: 1476 memset(&data.label, 0, sizeof(data.label)); 1477 break; 1478 case SNDCTL_SETLABEL: 1479 break; 1480 case SNDCTL_GETSONG: 1481 memset(&data.longname, 0, sizeof(data.longname)); 1482 break; 1483 case SNDCTL_SETSONG: 1484 break; 1485 case SNDCTL_SETNAME: 1486 break; 1487 default: 1488 error = CUSE_ERR_INVALID; 1489 break; 1490 } 1491 atomic_unlock(); 1492 1493 if (error == 0) { 1494 if (cmd & IOC_OUT) 1495 error = cuse_copy_out(&data, peer_data, len); 1496 } 1497 return (error); 1498 } 1499 1500 static int 1501 vclient_ioctl_wav(struct cuse_dev *pdev, int fflags __unused, 1502 unsigned long cmd, void *peer_data) 1503 { 1504 union { 1505 int val; 1506 } data; 1507 1508 vclient_t *pvc; 1509 int len; 1510 int error; 1511 1512 pvc = cuse_dev_get_per_file_handle(pdev); 1513 if (pvc == NULL) 1514 return (CUSE_ERR_INVALID); 1515 1516 len = IOCPARM_LEN(cmd); 1517 1518 if (len < 0 || len > (int)sizeof(data)) 1519 return (CUSE_ERR_INVALID); 1520 1521 if (cmd & IOC_IN) { 1522 error = cuse_copy_in(peer_data, &data, len); 1523 if (error) 1524 return (error); 1525 } else { 1526 error = 0; 1527 } 1528 1529 atomic_lock(); 1530 switch (cmd) { 1531 case FIONREAD: 1532 data.val = vclient_input_delay(pvc); 1533 break; 1534 case FIOASYNC: 1535 case SNDCTL_DSP_NONBLOCK: 1536 case FIONBIO: 1537 break; 1538 default: 1539 error = CUSE_ERR_INVALID; 1540 break; 1541 } 1542 atomic_unlock(); 1543 1544 if (error == 0) { 1545 if (cmd & IOC_OUT) 1546 error = cuse_copy_out(&data, peer_data, len); 1547 } 1548 return (error); 1549 } 1550 1551 static int 1552 vclient_poll(struct cuse_dev *pdev, int fflags, int events) 1553 { 1554 vclient_t *pvc; 1555 1556 int retval = CUSE_POLL_NONE; 1557 1558 pvc = cuse_dev_get_per_file_handle(pdev); 1559 if (pvc == NULL) 1560 return (retval); 1561 1562 atomic_lock(); 1563 if ((events & CUSE_POLL_READ) && (fflags & CUSE_FFLAG_READ)) { 1564 pvc->rx_enabled = 1; 1565 if (vclient_input_delay(pvc) >= pvc->low_water) 1566 retval |= CUSE_POLL_READ; 1567 } 1568 if ((events & CUSE_POLL_WRITE) && (fflags & CUSE_FFLAG_WRITE)) { 1569 const uint32_t out_dly = vclient_output_delay(pvc); 1570 const uint32_t out_buf = (pvc->buffer_frags * pvc->buffer_size); 1571 1572 if (out_dly < out_buf && (out_buf - out_dly) >= pvc->low_water) 1573 retval |= CUSE_POLL_WRITE; 1574 } 1575 atomic_unlock(); 1576 1577 return (retval); 1578 } 1579 1580 static const struct cuse_methods vclient_oss_methods = { 1581 .cm_open = vclient_open_oss, 1582 .cm_close = vclient_close, 1583 .cm_read = vclient_read, 1584 .cm_write = vclient_write_oss, 1585 .cm_ioctl = vclient_ioctl_oss, 1586 .cm_poll = vclient_poll, 1587 }; 1588 1589 static const struct cuse_methods vclient_wav_methods = { 1590 .cm_open = vclient_open_wav, 1591 .cm_close = vclient_close, 1592 .cm_read = vclient_read, 1593 .cm_write = vclient_write_wav, 1594 .cm_ioctl = vclient_ioctl_wav, 1595 .cm_poll = vclient_poll, 1596 }; 1597 1598 vprofile_head_t virtual_profile_client_head; 1599 vprofile_head_t virtual_profile_loopback_head; 1600 1601 vmonitor_head_t virtual_monitor_input; 1602 vmonitor_head_t virtual_monitor_output; 1603 vmonitor_head_t virtual_monitor_local; 1604 1605 uint32_t voss_max_channels; 1606 uint32_t voss_mix_channels; 1607 uint32_t voss_dsp_samples; 1608 uint32_t voss_dsp_max_channels; 1609 uint32_t voss_dsp_sample_rate; 1610 uint32_t voss_dsp_bits; 1611 uint8_t voss_libsamplerate_enable; 1612 uint8_t voss_libsamplerate_quality = SRC_SINC_FASTEST; 1613 int voss_is_recording = 1; 1614 int voss_has_synchronization; 1615 volatile sig_atomic_t voss_exit = 0; 1616 1617 static int voss_dsp_perm = 0666; 1618 static int voss_do_background; 1619 static const char *voss_pid_path; 1620 1621 uint32_t voss_dsp_rx_refresh; 1622 uint32_t voss_dsp_tx_refresh; 1623 char voss_dsp_rx_device[VMAX_STRING]; 1624 char voss_dsp_tx_device[VMAX_STRING]; 1625 char voss_ctl_device[VMAX_STRING]; 1626 1627 uint32_t voss_jitter_up; 1628 uint32_t voss_jitter_down; 1629 1630 struct voss_backend *voss_rx_backend; 1631 struct voss_backend *voss_tx_backend; 1632 1633 static int voss_dups; 1634 static int voss_ntds; 1635 static pthread_t *voss_tds; 1636 1637 /* XXX I do not like the prefix argument... */ 1638 static struct voss_backend * 1639 voss_load_backend(const char *prefix, const char *name, const char *dir) 1640 { 1641 struct voss_backend *backend; 1642 void *hdl; 1643 char lpath[64], bsym[64]; 1644 1645 snprintf(lpath, sizeof(lpath), "%s/lib/virtual_oss/voss_%s.so", 1646 prefix, name); 1647 snprintf(bsym, sizeof(bsym), "voss_backend_%s_%s", name, dir); 1648 1649 if ((hdl = dlopen(lpath, RTLD_NOW)) == NULL) 1650 errx(1, "%s", dlerror()); 1651 if ((backend = dlsym(hdl, bsym)) == NULL) { 1652 warnx("%s", dlerror()); 1653 dlclose(hdl); 1654 exit(EXIT_FAILURE); 1655 } 1656 1657 return (backend); 1658 } 1659 1660 static void 1661 voss_rx_backend_refresh(void) 1662 { 1663 /* setup RX backend */ 1664 if (strcmp(voss_dsp_rx_device, "/dev/null") == 0) { 1665 voss_rx_backend = voss_load_backend("/usr", "null", "rec"); 1666 } else if (strstr(voss_dsp_rx_device, "/dev/bluetooth/") == voss_dsp_rx_device) { 1667 voss_rx_backend = voss_load_backend("/usr/local", "bt", "rec"); 1668 } else if (strstr(voss_dsp_rx_device, "/dev/sndio/") == voss_dsp_rx_device) { 1669 voss_rx_backend = voss_load_backend("/usr/local", "sndio", "rec"); 1670 } else { 1671 voss_rx_backend = voss_load_backend("/usr", "oss", "rec"); 1672 } 1673 } 1674 1675 static void 1676 voss_tx_backend_refresh(void) 1677 { 1678 /* setup TX backend */ 1679 if (strcmp(voss_dsp_tx_device, "/dev/null") == 0) { 1680 voss_tx_backend = voss_load_backend("/usr", "null", "play"); 1681 } else if (strstr(voss_dsp_tx_device, "/dev/bluetooth/") == voss_dsp_tx_device) { 1682 voss_tx_backend = voss_load_backend("/usr/local", "bt", "play"); 1683 } else if (strstr(voss_dsp_tx_device, "/dev/sndio/") == voss_dsp_tx_device) { 1684 voss_tx_backend = voss_load_backend("/usr/local", "sndio", "play"); 1685 } else { 1686 voss_tx_backend = voss_load_backend("/usr", "oss", "play"); 1687 } 1688 } 1689 1690 static void 1691 usage(void) 1692 { 1693 fprintf(stderr, "Usage: virtual_oss [options...] [device] \\\n" 1694 "\t" "-C 2 -c 2 -r 48000 -b 16 -s 100.0ms -f /dev/dsp3 \\\n" 1695 "\t" "-P /dev/dsp3 -R /dev/dsp1 \\\n" 1696 "\t" "-O /dev/dsp3 -R /dev/null \\\n" 1697 "\t" "-c 1 -m 0,0 [-w wav.0] -d dsp100.0 \\\n" 1698 "\t" "-c 1 -m 0,0 [-w wav.0] -d vdsp.0 \\\n" 1699 "\t" "-c 2 -m 0,0,1,1 [-w wav.1] -d vdsp.1 \\\n" 1700 "\t" "-c 2 -m 0,0,1,1 [-w wav.loopback] -l vdsp.loopback \\\n" 1701 "\t" "-c 2 -m 0,0,1,1 [-w wav.loopback] -L vdsp.loopback \\\n" 1702 "\t" "-B # run in background \\\n" 1703 "\t" "-s <samples> or <milliseconds>ms \\\n" 1704 "\t" "-S # enable automatic resampling using libsamplerate \\\n" 1705 "\t" "-Q <0,1,2> # quality of resampling 0=best,1=medium,2=fastest (default) \\\n" 1706 "\t" "-b <bits> \\\n" 1707 "\t" "-r <rate> \\\n" 1708 "\t" "-i <rtprio> \\\n" 1709 "\t" "-a <amp -63..63> \\\n" 1710 "\t" "-a i,<rx_amp -63..63> \\\n" 1711 "\t" "-a o,<tx_amp -63..63> \\\n" 1712 "\t" "-g <knee,attack,decay> # enable device RX compressor\\\n" 1713 "\t" "-x <knee,attack,decay> # enable output compressor\\\n" 1714 "\t" "-p <pol 0..1> \\\n" 1715 "\t" "-e <rxtx_mute 0..1> \\\n" 1716 "\t" "-e <rx_mute 0..1>,<tx_mute 0..1> \\\n" 1717 "\t" "-m <mapping> \\\n" 1718 "\t" "-m <rx0,tx0,rx1,tx1...rxN,txN> \\\n" 1719 "\t" "-C <mixchans>\\\n" 1720 "\t" "-c <dspchans> \\\n" 1721 "\t" "-M <monitorfilter> \\\n" 1722 "\t" "-M i,<src>,<dst>,<pol>,<mute>,<amp> \\\n" 1723 "\t" "-M o,<src>,<dst>,<pol>,<mute>,<amp> \\\n" 1724 "\t" "-M x,<src>,<dst>,<pol>,<mute>,<amp> \\\n" 1725 "\t" "-F <rx_filter_samples> or <milliseconds>ms \\\n" 1726 "\t" "-G <tx_filter_samples> or <milliseconds>ms \\\n" 1727 "\t" "-E <enable_recording, 0 or 1> \\\n" 1728 "\t" "-N <max HTTP connections, default is 1> \\\n" 1729 "\t" "-H <bind HTTP server to this host> \\\n" 1730 "\t" "-o <bind HTTP server to this port, default is 80> \\\n" 1731 "\t" "-J <bind RTP server to this network interface> \\\n" 1732 "\t" "-k <bind RTP server to this port, default is 8080> \\\n" 1733 "\t" "-t vdsp.ctl \n" 1734 "\t" "Left channel = 0\n" 1735 "\t" "Right channel = 1\n" 1736 "\t" "Max channels = %d\n", VMAX_CHAN); 1737 1738 exit(EX_USAGE); 1739 } 1740 1741 static void 1742 init_compressor(struct virtual_profile *pvp) 1743 { 1744 int x; 1745 1746 memset(&pvp->rx_compressor_param, 0, sizeof(pvp->rx_compressor_param)); 1747 1748 pvp->rx_compressor_param.knee = 85; 1749 pvp->rx_compressor_param.attack = 3; 1750 pvp->rx_compressor_param.decay = 20; 1751 1752 for (x = 0; x != VMAX_CHAN; x++) 1753 pvp->rx_compressor_gain[x] = 1.0; 1754 } 1755 1756 static void 1757 init_mapping(struct virtual_profile *pvp) 1758 { 1759 int x; 1760 1761 for (x = 0; x != VMAX_CHAN; x++) { 1762 pvp->rx_src[x] = x; 1763 pvp->tx_dst[x] = x; 1764 } 1765 } 1766 1767 static void 1768 init_sndstat(vprofile_t *ptr) 1769 { 1770 int err; 1771 nvlist_t *nvl; 1772 nvlist_t *di = NULL, *dichild = NULL; 1773 struct sndstioc_nv_arg arg; 1774 unsigned int min_rate, max_rate; 1775 1776 nvl = nvlist_create(0); 1777 if (nvl == NULL) { 1778 warn("Failed to create nvlist"); 1779 goto done; 1780 } 1781 1782 di = nvlist_create(0); 1783 if (di == NULL) { 1784 warn("Failed to create nvlist"); 1785 goto done; 1786 } 1787 1788 dichild = nvlist_create(0); 1789 if (dichild == NULL) { 1790 warn("Failed to create nvlist"); 1791 goto done; 1792 } 1793 1794 nvlist_add_string(di, SNDST_DSPS_PROVIDER, "virtual_oss"); 1795 nvlist_add_string(di, SNDST_DSPS_DESC, "virtual_oss device"); 1796 nvlist_add_number(di, SNDST_DSPS_PCHAN, 1); 1797 nvlist_add_number(di, SNDST_DSPS_RCHAN, 1); 1798 min_rate = 8000; 1799 max_rate = voss_dsp_sample_rate; 1800 if (voss_libsamplerate_enable == 0 || 1801 min_rate > max_rate) 1802 min_rate = max_rate; 1803 if (voss_libsamplerate_enable != 0 && max_rate < 96000) 1804 max_rate = 96000; 1805 nvlist_add_number(dichild, SNDST_DSPS_INFO_MIN_RATE, min_rate); 1806 nvlist_add_number(dichild, SNDST_DSPS_INFO_MAX_RATE, max_rate); 1807 nvlist_add_number(dichild, SNDST_DSPS_INFO_FORMATS, VSUPPORTED_AFMT); 1808 nvlist_add_number(dichild, SNDST_DSPS_INFO_MIN_CHN, ptr->channels); 1809 nvlist_add_number(dichild, SNDST_DSPS_INFO_MAX_CHN, ptr->channels); 1810 nvlist_add_nvlist(di, SNDST_DSPS_INFO_PLAY, dichild); 1811 nvlist_add_nvlist(di, SNDST_DSPS_INFO_REC, dichild); 1812 1813 nvlist_add_string(di, SNDST_DSPS_DEVNODE, 1814 ptr->oss_name); 1815 nvlist_append_nvlist_array(nvl, SNDST_DSPS, di); 1816 1817 if (nvlist_error(nvl)) { 1818 warn("Failed building nvlist"); 1819 goto done; 1820 } 1821 1822 arg.buf = nvlist_pack(nvl, &arg.nbytes); 1823 if (arg.buf == NULL) { 1824 warn("Failed to pack nvlist"); 1825 goto done; 1826 } 1827 err = ioctl(ptr->fd_sta, SNDSTIOC_ADD_USER_DEVS, &arg); 1828 free(arg.buf); 1829 if (err != 0) { 1830 warn("Failed to issue ioctl(SNDSTIOC_ADD_USER_DEVS)"); 1831 goto done; 1832 } 1833 1834 done: 1835 nvlist_destroy(di); 1836 nvlist_destroy(dichild); 1837 nvlist_destroy(nvl); 1838 } 1839 1840 static const char * 1841 dup_profile(vprofile_t *pvp, int *pamp, int pol, int rx_mute, 1842 int tx_mute, int synchronized, int is_client) 1843 { 1844 vprofile_t *ptr; 1845 struct cuse_dev *pdev; 1846 int x; 1847 1848 rx_mute = rx_mute ? 1 : 0; 1849 tx_mute = tx_mute ? 1 : 0; 1850 pol = pol ? 1 : 0; 1851 1852 /* Range check amplitude argument. */ 1853 for (x = 0; x != 2; x++) { 1854 if (pamp[x] < -63) 1855 pamp[x] = -63; 1856 else if (pamp[x] > 63) 1857 pamp[x] = 63; 1858 } 1859 1860 ptr = malloc(sizeof(*ptr)); 1861 if (ptr == NULL) 1862 return ("Out of memory"); 1863 1864 memcpy(ptr, pvp, sizeof(*ptr)); 1865 1866 ptr->synchronized = synchronized; 1867 ptr->fd_sta = -1; 1868 TAILQ_INIT(&ptr->head); 1869 1870 for (x = 0; x != ptr->channels; x++) { 1871 ptr->tx_mute[x] = tx_mute; 1872 ptr->rx_mute[x] = rx_mute; 1873 ptr->tx_shift[x] = pamp[1]; 1874 ptr->rx_shift[x] = pamp[0]; 1875 ptr->tx_pol[x] = pol; 1876 ptr->rx_pol[x] = pol; 1877 } 1878 1879 /* create DSP device */ 1880 if (ptr->oss_name[0] != 0) { 1881 /* 1882 * Detect /dev/dsp creation and try to disable system 1883 * basename cloning automatically: 1884 */ 1885 if (strcmp(ptr->oss_name, "dsp") == 0) 1886 system("sysctl hw.snd.basename_clone=0"); 1887 1888 /* create DSP character device */ 1889 pdev = cuse_dev_create(&vclient_oss_methods, ptr, NULL, 1890 0, 0, voss_dsp_perm, ptr->oss_name); 1891 if (pdev == NULL) { 1892 free(ptr); 1893 return ("Could not create CUSE DSP device"); 1894 } 1895 1896 /* register to sndstat */ 1897 ptr->fd_sta = open("/dev/sndstat", O_WRONLY); 1898 if (ptr->fd_sta < 0) { 1899 warn("Could not open /dev/sndstat"); 1900 } else { 1901 init_sndstat(ptr); 1902 } 1903 } 1904 /* create WAV device */ 1905 if (ptr->wav_name[0] != 0) { 1906 pdev = cuse_dev_create(&vclient_wav_methods, ptr, NULL, 1907 0, 0, voss_dsp_perm, ptr->wav_name); 1908 if (pdev == NULL) { 1909 free(ptr); 1910 return ("Could not create CUSE WAV device"); 1911 } 1912 } 1913 1914 atomic_lock(); 1915 if (is_client) 1916 TAILQ_INSERT_TAIL(&virtual_profile_client_head, ptr, entry); 1917 else 1918 TAILQ_INSERT_TAIL(&virtual_profile_loopback_head, ptr, entry); 1919 atomic_unlock(); 1920 1921 voss_dups++; 1922 1923 /* need new names next time */ 1924 memset(pvp->oss_name, 0, sizeof(pvp->oss_name)); 1925 memset(pvp->wav_name, 0, sizeof(pvp->wav_name)); 1926 1927 /* need to set new filter sizes */ 1928 pvp->rx_filter_size = 0; 1929 pvp->tx_filter_size = 0; 1930 1931 /* need to specify new HTTP parameters next time */ 1932 pvp->http.host = NULL; 1933 pvp->http.port = NULL; 1934 pvp->http.nstate = 0; 1935 pvp->http.rtp_ifname = NULL; 1936 pvp->http.rtp_port = NULL; 1937 1938 /* need to specify new amplification next time */ 1939 pamp[0] = 0; 1940 pamp[1] = 0; 1941 1942 /* need to set new compressor parameters next time */ 1943 init_compressor(pvp); 1944 1945 return (voss_httpd_start(ptr)); 1946 } 1947 1948 static void 1949 virtual_pipe(int sig __unused) 1950 { 1951 voss_dsp_tx_refresh = 1; 1952 voss_dsp_rx_refresh = 1; 1953 } 1954 1955 static void 1956 virtual_cuse_hup(int sig __unused) 1957 { 1958 atomic_wakeup(); 1959 } 1960 1961 static void * 1962 virtual_cuse_process(void *arg __unused) 1963 { 1964 signal(SIGHUP, &virtual_cuse_hup); 1965 1966 while (1) { 1967 if (cuse_wait_and_process() != 0) 1968 break; 1969 } 1970 return (NULL); 1971 } 1972 1973 static void 1974 virtual_cuse_init_profile(struct virtual_profile *pvp) 1975 { 1976 memset(pvp, 0, sizeof(*pvp)); 1977 1978 init_compressor(pvp); 1979 init_mapping(pvp); 1980 } 1981 1982 static void 1983 virtual_sig_exit(int sig __unused) 1984 { 1985 voss_exit = 1; 1986 } 1987 1988 static const char * 1989 parse_options(int narg, char **pparg, int is_main) 1990 { 1991 const char *ptr; 1992 int a, b, c; 1993 int val; 1994 int idx; 1995 int type; 1996 int opt_mute[2] = {0, 0}; 1997 int opt_amp[2] = {0, 0}; 1998 int opt_pol = 0; 1999 const char *optstr; 2000 struct virtual_profile profile; 2001 struct rtprio rtp; 2002 float samples_ms; 2003 2004 if (is_main) 2005 optstr = "N:J:k:H:o:F:G:w:e:p:a:C:c:r:b:f:g:x:i:m:M:d:l:L:s:t:h?O:P:Q:R:SBD:E:"; 2006 else 2007 optstr = "F:G:w:e:p:a:c:b:f:m:M:d:l:L:s:O:P:R:E:"; 2008 2009 virtual_cuse_init_profile(&profile); 2010 2011 /* reset getopt parsing */ 2012 optreset = 1; 2013 optind = 1; 2014 2015 while ((c = getopt(narg, pparg, optstr)) != -1) { 2016 switch (c) { 2017 case 'B': 2018 voss_do_background = 1; 2019 break; 2020 case 'D': 2021 voss_pid_path = optarg; 2022 break; 2023 case 'C': 2024 if (voss_mix_channels != 0) { 2025 return ("The -C argument may only be used once"); 2026 } 2027 voss_mix_channels = atoi(optarg); 2028 if (voss_mix_channels >= VMAX_CHAN) { 2029 return ("Number of mixing channels is too high"); 2030 } 2031 break; 2032 case 'a': 2033 switch (optarg[0]) { 2034 case '-': 2035 case '0': 2036 case '1': 2037 case '2': 2038 case '3': 2039 case '4': 2040 case '5': 2041 case '6': 2042 case '7': 2043 case '8': 2044 case '9': 2045 opt_amp[0] = -(opt_amp[1] = atoi(optarg)); 2046 break; 2047 case 'i': 2048 if (optarg[1] != ',') 2049 return ("Expected comma after 'i'"); 2050 opt_amp[0] = atoi(optarg + 2); 2051 break; 2052 case 'o': 2053 if (optarg[1] != ',') 2054 return ("Expected comma after 'o'"); 2055 opt_amp[1] = atoi(optarg + 2); 2056 break; 2057 default: 2058 return ("Invalid syntax for amplitude argument"); 2059 } 2060 break; 2061 case 'E': 2062 voss_is_recording = (atoi(optarg) != 0); 2063 break; 2064 case 'e': 2065 idx = 0; 2066 ptr = optarg; 2067 memset(opt_mute, 0, sizeof(opt_mute)); 2068 while (1) { 2069 c = *ptr++; 2070 if (c == ',' || c == 0) { 2071 idx++; 2072 if (c == 0) 2073 break; 2074 continue; 2075 } 2076 if (idx < 2 && c >= '0' && c <= '1') { 2077 opt_mute[idx] = c - '0'; 2078 } else { 2079 return ("Invalid -e parameter"); 2080 } 2081 } 2082 switch (idx) { 2083 case 1: 2084 opt_mute[1] = opt_mute[0]; 2085 break; 2086 case 2: 2087 break; 2088 default: 2089 return ("Invalid -e parameter"); 2090 } 2091 break; 2092 case 'p': 2093 opt_pol = atoi(optarg); 2094 break; 2095 case 'c': 2096 profile.channels = atoi(optarg); 2097 if (profile.channels == 0) 2098 return ("Number of channels is zero"); 2099 if (profile.channels > VMAX_CHAN) 2100 return ("Number of channels is too high"); 2101 break; 2102 case 'r': 2103 voss_dsp_sample_rate = atoi(optarg); 2104 if (voss_dsp_sample_rate < 8000) 2105 return ("Sample rate is too low, 8000 Hz"); 2106 if (voss_dsp_sample_rate > 0xFFFFFF) 2107 return ("Sample rate is too high"); 2108 break; 2109 case 'i': 2110 memset(&rtp, 0, sizeof(rtp)); 2111 rtp.type = RTP_PRIO_REALTIME; 2112 rtp.prio = atoi(optarg); 2113 if (rtprio(RTP_SET, getpid(), &rtp) != 0) 2114 printf("Cannot set realtime priority\n"); 2115 break; 2116 case 'b': 2117 profile.bits = atoi(optarg); 2118 switch (profile.bits) { 2119 case 8: 2120 case 16: 2121 case 24: 2122 case 32: 2123 break; 2124 default: 2125 return ("Invalid number of sample bits"); 2126 } 2127 break; 2128 case 'g': 2129 if (profile.rx_compressor_param.enabled) 2130 return ("Compressor already enabled for this device"); 2131 if (sscanf(optarg, "%d,%d,%d", &a, &b, &c) != 3 || 2132 a < VIRTUAL_OSS_KNEE_MIN || 2133 a > VIRTUAL_OSS_KNEE_MAX || 2134 b < VIRTUAL_OSS_ATTACK_MIN || 2135 b > VIRTUAL_OSS_ATTACK_MAX || 2136 c < VIRTUAL_OSS_DECAY_MIN || 2137 c > VIRTUAL_OSS_DECAY_MAX) 2138 return ("Invalid device compressor argument(s)"); 2139 profile.rx_compressor_param.enabled = 1; 2140 profile.rx_compressor_param.knee = a; 2141 profile.rx_compressor_param.attack = b; 2142 profile.rx_compressor_param.decay = c; 2143 break; 2144 case 'x': 2145 if (voss_output_compressor_param.enabled) 2146 return ("Compressor already enabled for output"); 2147 if (sscanf(optarg, "%d,%d,%d", &a, &b, &c) != 3 || 2148 a < VIRTUAL_OSS_KNEE_MIN || 2149 a > VIRTUAL_OSS_KNEE_MAX || 2150 b < VIRTUAL_OSS_ATTACK_MIN || 2151 b > VIRTUAL_OSS_ATTACK_MAX || 2152 c < VIRTUAL_OSS_DECAY_MIN || 2153 c > VIRTUAL_OSS_DECAY_MAX) 2154 return ("Invalid output compressor argument(s)"); 2155 voss_output_compressor_param.enabled = 1; 2156 voss_output_compressor_param.knee = a; 2157 voss_output_compressor_param.attack = b; 2158 voss_output_compressor_param.decay = c; 2159 break; 2160 case 'f': 2161 case 'O': 2162 case 'P': 2163 case 'R': 2164 if (voss_dsp_sample_rate == 0 || voss_dsp_samples == 0) 2165 return ("Missing -r or -s parameters"); 2166 if (voss_dsp_bits == 0) { 2167 if (profile.bits == 0) 2168 return ("Missing -b parameter"); 2169 voss_dsp_bits = profile.bits; 2170 } 2171 if (voss_dsp_max_channels == 0) { 2172 if (profile.channels == 0) 2173 return ("Missing -c parameter"); 2174 voss_dsp_max_channels = profile.channels; 2175 } 2176 if (c == 'f' || c == 'R') { 2177 if (strlen(optarg) > VMAX_STRING - 1) 2178 return ("Device name too long"); 2179 strncpy(voss_dsp_rx_device, optarg, sizeof(voss_dsp_rx_device)); 2180 voss_rx_backend_refresh(); 2181 voss_dsp_rx_refresh = 1; 2182 } 2183 if (c == 'f' || c == 'P' || c == 'O') { 2184 if (strlen(optarg) > VMAX_STRING - 1) 2185 return ("Device name too long"); 2186 strncpy(voss_dsp_tx_device, optarg, sizeof(voss_dsp_tx_device)); 2187 voss_tx_backend_refresh(); 2188 voss_dsp_tx_refresh = 1; 2189 2190 if (c == 'O' && voss_has_synchronization == 0) 2191 voss_has_synchronization++; 2192 } 2193 break; 2194 case 'w': 2195 if (strlen(optarg) > VMAX_STRING - 1) 2196 return ("Device name too long"); 2197 strncpy(profile.wav_name, optarg, sizeof(profile.wav_name)); 2198 break; 2199 case 'd': 2200 if (strlen(optarg) > VMAX_STRING - 1) 2201 return ("Device name too long"); 2202 strncpy(profile.oss_name, optarg, sizeof(profile.oss_name)); 2203 2204 if (profile.bits == 0 || voss_dsp_sample_rate == 0 || 2205 profile.channels == 0 || voss_dsp_samples == 0) 2206 return ("Missing -b, -r, -c or -s parameters"); 2207 2208 val = (voss_dsp_samples * 2209 profile.bits * profile.channels) / 8; 2210 if (val <= 0 || val >= (1024 * 1024)) 2211 return ("-s option value is too big"); 2212 2213 ptr = dup_profile(&profile, opt_amp, opt_pol, 2214 opt_mute[0], opt_mute[1], 0, 1); 2215 if (ptr != NULL) 2216 return (ptr); 2217 break; 2218 case 'L': 2219 case 'l': 2220 if (strlen(optarg) > VMAX_STRING - 1) 2221 return ("Device name too long"); 2222 strncpy(profile.oss_name, optarg, sizeof(profile.oss_name)); 2223 2224 if (profile.bits == 0 || voss_dsp_sample_rate == 0 || 2225 profile.channels == 0 || voss_dsp_samples == 0) 2226 return ("Missing -b, -r, -r or -s parameters"); 2227 2228 val = (voss_dsp_samples * 2229 profile.bits * profile.channels) / 8; 2230 if (val <= 0 || val >= (1024 * 1024)) 2231 return ("-s option value is too big"); 2232 2233 ptr = dup_profile(&profile, opt_amp, opt_pol, 2234 opt_mute[0], opt_mute[1], c == 'L', 0); 2235 if (ptr != NULL) 2236 return (ptr); 2237 break; 2238 case 'S': 2239 voss_libsamplerate_enable = 1; 2240 break; 2241 case 'Q': 2242 c = atoi(optarg); 2243 switch (c) { 2244 case 0: 2245 voss_libsamplerate_quality = SRC_SINC_BEST_QUALITY; 2246 break; 2247 case 1: 2248 voss_libsamplerate_quality = SRC_SINC_MEDIUM_QUALITY; 2249 break; 2250 default: 2251 voss_libsamplerate_quality = SRC_SINC_FASTEST; 2252 break; 2253 } 2254 break; 2255 case 's': 2256 if (voss_dsp_samples != 0) 2257 return ("-s option may only be used once"); 2258 if (profile.bits == 0 || profile.channels == 0) 2259 return ("-s option requires -b and -c options"); 2260 if (strlen(optarg) > 2 && 2261 sscanf(optarg, "%f", &samples_ms) == 1 && 2262 strcmp(optarg + strlen(optarg) - 2, "ms") == 0) { 2263 if (voss_dsp_sample_rate == 0) 2264 return ("-s <X>ms option requires -r option"); 2265 if (samples_ms < 0.125 || samples_ms >= 1000.0) 2266 return ("-s <X>ms option has invalid value"); 2267 voss_dsp_samples = voss_dsp_sample_rate * samples_ms / 1000.0; 2268 } else { 2269 voss_dsp_samples = atoi(optarg); 2270 } 2271 if (voss_dsp_samples >= (1U << 24)) 2272 return ("-s option requires a non-zero positive value"); 2273 break; 2274 case 't': 2275 if (voss_ctl_device[0]) 2276 return ("-t parameter may only be used once"); 2277 2278 strlcpy(voss_ctl_device, optarg, sizeof(voss_ctl_device)); 2279 break; 2280 case 'm': 2281 ptr = optarg; 2282 val = 0; 2283 idx = 0; 2284 init_mapping(&profile); 2285 while (1) { 2286 c = *ptr++; 2287 if (c == ',' || c == 0) { 2288 if (idx >= (2 * VMAX_CHAN)) 2289 return ("Too many channels in mask"); 2290 if (idx & 1) 2291 profile.tx_dst[idx / 2] = val; 2292 else 2293 profile.rx_src[idx / 2] = val; 2294 if (c == 0) 2295 break; 2296 val = 0; 2297 idx++; 2298 continue; 2299 } 2300 if (c >= '0' && c <= '9') { 2301 val *= 10; 2302 val += c - '0'; 2303 } 2304 } 2305 break; 2306 case 'M': 2307 ptr = optarg; 2308 type = *ptr; 2309 if (type == 'i' || type == 'o' || type == 'x') { 2310 vmonitor_t *pvm; 2311 2312 int src = 0; 2313 int dst = 0; 2314 int pol = 0; 2315 int mute = 0; 2316 int amp = 0; 2317 int neg; 2318 2319 ptr++; 2320 if (*ptr == ',') 2321 ptr++; 2322 else if (type == 'i') 2323 return ("Expected comma after 'i'"); 2324 else if (type == 'o') 2325 return ("Expected comma after 'o'"); 2326 else 2327 return ("Expected comma after 'x'"); 2328 2329 val = 0; 2330 neg = 0; 2331 idx = 0; 2332 while (1) { 2333 c = *ptr++; 2334 if (c == '-') { 2335 neg = 1; 2336 continue; 2337 } 2338 if (c == ',' || c == 0) { 2339 switch (idx) { 2340 case 0: 2341 src = val; 2342 break; 2343 case 1: 2344 dst = val; 2345 break; 2346 case 2: 2347 pol = val ? 1 : 0; 2348 break; 2349 case 3: 2350 mute = val ? 1 : 0; 2351 break; 2352 case 4: 2353 if (val > 31) { 2354 return ("Absolute amplitude " 2355 "for -M parameter " 2356 "cannot exceed 31"); 2357 } 2358 amp = neg ? -val : val; 2359 break; 2360 default: 2361 break; 2362 } 2363 if (c == 0) 2364 break; 2365 val = 0; 2366 neg = 0; 2367 idx++; 2368 continue; 2369 } 2370 if (c >= '0' && c <= '9') { 2371 val *= 10; 2372 val += c - '0'; 2373 } 2374 } 2375 if (idx < 4) 2376 return ("Too few parameters for -M"); 2377 2378 pvm = vmonitor_alloc(&idx, 2379 (type == 'i') ? &virtual_monitor_input : 2380 (type == 'x') ? &virtual_monitor_local : 2381 &virtual_monitor_output); 2382 2383 if (pvm == NULL) 2384 return ("Out of memory"); 2385 2386 pvm->src_chan = src; 2387 pvm->dst_chan = dst; 2388 pvm->pol = pol; 2389 pvm->mute = mute; 2390 pvm->shift = amp; 2391 } else { 2392 return ("Invalid -M parameter"); 2393 } 2394 break; 2395 case 'F': 2396 if (strlen(optarg) > 2 && 2397 sscanf(optarg, "%f", &samples_ms) == 1 && 2398 strcmp(optarg + strlen(optarg) - 2, "ms") == 0) { 2399 if (voss_dsp_sample_rate == 0) 2400 return ("-F <X>ms option requires -r option"); 2401 if (samples_ms < 0.125 || samples_ms >= 1000.0) 2402 return ("-F <X>ms option has invalid value"); 2403 profile.rx_filter_size = voss_dsp_sample_rate * samples_ms / 1000.0; 2404 } else { 2405 profile.rx_filter_size = atoi(optarg); 2406 } 2407 /* make value power of two */ 2408 while ((profile.rx_filter_size - 1) & profile.rx_filter_size) 2409 profile.rx_filter_size += ~(profile.rx_filter_size - 1) & profile.rx_filter_size; 2410 /* range check */ 2411 if (profile.rx_filter_size > VIRTUAL_OSS_FILTER_MAX) 2412 return ("Invalid -F parameter is out of range"); 2413 break; 2414 case 'G': 2415 if (strlen(optarg) > 2 && 2416 sscanf(optarg, "%f", &samples_ms) == 1 && 2417 strcmp(optarg + strlen(optarg) - 2, "ms") == 0) { 2418 if (voss_dsp_sample_rate == 0) 2419 return ("-G <X>ms option requires -r option"); 2420 if (samples_ms < 0.125 || samples_ms >= 1000.0) 2421 return ("-G <X>ms option has invalid value"); 2422 profile.tx_filter_size = voss_dsp_sample_rate * samples_ms / 1000.0; 2423 } else { 2424 profile.tx_filter_size = atoi(optarg); 2425 } 2426 /* make value power of two */ 2427 while ((profile.tx_filter_size - 1) & profile.tx_filter_size) 2428 profile.tx_filter_size += ~(profile.tx_filter_size - 1) & profile.tx_filter_size; 2429 /* range check */ 2430 if (profile.tx_filter_size > VIRTUAL_OSS_FILTER_MAX) 2431 return ("Invalid -F parameter is out of range"); 2432 break; 2433 case 'N': 2434 profile.http.nstate = atoi(optarg); 2435 break; 2436 case 'H': 2437 profile.http.host = optarg; 2438 if (profile.http.port == NULL) 2439 profile.http.port = "80"; 2440 if (profile.http.nstate == 0) 2441 profile.http.nstate = 1; 2442 break; 2443 case 'o': 2444 profile.http.port = optarg; 2445 break; 2446 case 'J': 2447 profile.http.rtp_ifname = optarg; 2448 if (profile.http.rtp_port == NULL) 2449 profile.http.rtp_port = "8080"; 2450 break; 2451 case 'k': 2452 profile.http.rtp_port = optarg; 2453 break; 2454 default: 2455 if (is_main) 2456 usage(); 2457 else 2458 return ("Invalid option detected"); 2459 break; 2460 } 2461 } 2462 return (NULL); 2463 } 2464 2465 static void 2466 create_threads(void) 2467 { 2468 int idx; 2469 2470 /* Give each DSP device 4 threads */ 2471 voss_ntds = voss_dups * 4; 2472 voss_tds = malloc(voss_ntds * sizeof(pthread_t)); 2473 if (voss_tds == NULL) 2474 err(1, "malloc"); 2475 2476 for (idx = 0; idx < voss_ntds; idx++) { 2477 if (pthread_create(&voss_tds[idx], NULL, &virtual_cuse_process, 2478 NULL) != 0) 2479 err(1, "pthread_create"); 2480 } 2481 2482 /* Reset until next time called */ 2483 voss_dups = 0; 2484 } 2485 2486 static void 2487 destroy_threads(void) 2488 { 2489 int idx; 2490 2491 for (idx = 0; idx < voss_ntds; idx++) 2492 pthread_cancel(voss_tds[idx]); 2493 free(voss_tds); 2494 } 2495 2496 void 2497 voss_add_options(char *str) 2498 { 2499 static char name[] = { "virtual_oss" }; 2500 const char sep[] = "\t "; 2501 const char *ptrerr; 2502 char *parg[64]; 2503 char *word; 2504 char *brkt; 2505 int narg = 0; 2506 2507 parg[narg++] = name; 2508 2509 for (word = strtok_r(str, sep, &brkt); word != NULL; 2510 word = strtok_r(NULL, sep, &brkt)) { 2511 if (narg >= 64) { 2512 ptrerr = "Too many arguments"; 2513 goto done; 2514 } 2515 parg[narg++] = word; 2516 } 2517 ptrerr = parse_options(narg, parg, 0); 2518 done: 2519 if (ptrerr != NULL) { 2520 strlcpy(str, ptrerr, VIRTUAL_OSS_OPTIONS_MAX); 2521 } else { 2522 str[0] = 0; 2523 create_threads(); 2524 } 2525 } 2526 2527 int 2528 main(int argc, char **argv) 2529 { 2530 const char *ptrerr; 2531 struct sigaction sa; 2532 struct cuse_dev *pdev = NULL; 2533 2534 TAILQ_INIT(&virtual_profile_client_head); 2535 TAILQ_INIT(&virtual_profile_loopback_head); 2536 2537 TAILQ_INIT(&virtual_monitor_input); 2538 TAILQ_INIT(&virtual_monitor_output); 2539 TAILQ_INIT(&virtual_monitor_local); 2540 2541 atomic_init(); 2542 2543 /* automagically load the cuse.ko module, if any */ 2544 if (feature_present("cuse") == 0) { 2545 if (system("kldload cuse") == -1) 2546 warn("Failed to kldload cuse"); 2547 } 2548 2549 if (cuse_init() != 0) 2550 errx(EX_USAGE, "Could not connect to cuse module"); 2551 2552 signal(SIGPIPE, &virtual_pipe); 2553 2554 memset(&sa, 0, sizeof(sa)); 2555 sigfillset(&sa.sa_mask); 2556 sa.sa_handler = virtual_sig_exit; 2557 if (sigaction(SIGINT, &sa, NULL) < 0) 2558 err(1, "sigaction(SIGINT)"); 2559 if (sigaction(SIGTERM, &sa, NULL) < 0) 2560 err(1, "sigaction(SIGTERM)"); 2561 2562 ptrerr = parse_options(argc, argv, 1); 2563 if (ptrerr != NULL) 2564 errx(EX_USAGE, "%s", ptrerr); 2565 2566 if (voss_dsp_rx_device[0] == 0 || voss_dsp_tx_device[0] == 0) 2567 errx(EX_USAGE, "Missing -f argument"); 2568 2569 /* use DSP channels as default */ 2570 if (voss_mix_channels == 0) 2571 voss_mix_channels = voss_dsp_max_channels; 2572 2573 if (voss_mix_channels > voss_dsp_max_channels) 2574 voss_max_channels = voss_mix_channels; 2575 else 2576 voss_max_channels = voss_dsp_max_channels; 2577 2578 if (voss_dsp_samples > (voss_dsp_sample_rate / 4)) 2579 errx(EX_USAGE, "Too many buffer samples given by -s argument"); 2580 2581 /* check if daemon mode is requested */ 2582 if (voss_do_background != 0 && daemon(0, 0) != 0) 2583 errx(EX_SOFTWARE, "Cannot become daemon"); 2584 2585 if (voss_pid_path != NULL) { 2586 int pidfile = open(voss_pid_path, O_RDWR | O_CREAT | O_TRUNC, 0600); 2587 pid_t mypid = getpid(); 2588 char mypidstr[8]; 2589 snprintf(mypidstr, sizeof(mypidstr), "%d\n", mypid); 2590 if (pidfile < 0) 2591 errx(EX_SOFTWARE, "Cannot create PID file '%s'", voss_pid_path); 2592 if (write(pidfile, mypidstr, strlen(mypidstr)) != 2593 (ssize_t)strlen(mypidstr)) 2594 errx(EX_SOFTWARE, "Cannot write PID file"); 2595 close(pidfile); 2596 } 2597 2598 /* setup audio delay unit */ 2599 voss_ad_init(voss_dsp_sample_rate); 2600 2601 /* Create CTL device */ 2602 2603 if (voss_ctl_device[0] != 0) { 2604 pdev = cuse_dev_create(&vctl_methods, NULL, NULL, 2605 0, 0, voss_dsp_perm, voss_ctl_device); 2606 if (pdev == NULL) 2607 errx(EX_USAGE, "Could not create '/dev/%s'", voss_ctl_device); 2608 2609 voss_dups++; 2610 } 2611 2612 /* Create worker threads */ 2613 create_threads(); 2614 2615 /* Run DSP threads */ 2616 2617 virtual_oss_process(NULL); 2618 2619 destroy_threads(); 2620 2621 if (voss_ctl_device[0] != 0) 2622 cuse_dev_destroy(pdev); 2623 2624 return (0); 2625 } 2626