Lines Matching +full:- +full:v
8 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "qemu/error-report.h"
16 #include <spa/param/audio/format-utils.h>
26 #define RINGBUFFER_MASK (RINGBUFFER_SIZE - 1)
61 PWVoice v; member
66 PWVoice v; member
69 #define PW_VOICE_IN(v) ((PWVoiceIn *)v) argument
70 #define PW_VOICE_OUT(v) ((PWVoiceOut *)v) argument
75 PWVoice *v = (PWVoice *) data; in stream_destroy() local
76 spa_hook_remove(&v->stream_listener); in stream_destroy()
77 v->stream = NULL; in stream_destroy()
84 PWVoice *v = data; in playback_on_process() local
91 assert(v->stream); in playback_on_process()
94 b = pw_stream_dequeue_buffer(v->stream); in playback_on_process()
100 buf = b->buffer; in playback_on_process()
101 p = buf->datas[0].data; in playback_on_process()
106 req = b->requested * v->frame_size; in playback_on_process()
108 req = v->req; in playback_on_process()
110 n_bytes = SPA_MIN(req, buf->datas[0].maxsize); in playback_on_process()
113 avail = spa_ringbuffer_get_read_index(&v->ring, &index); in playback_on_process()
116 PWVoiceOut *vo = container_of(data, PWVoiceOut, v); in playback_on_process()
117 audio_pcm_info_clear_buf(&vo->hw.info, p, n_bytes / v->frame_size); in playback_on_process()
128 spa_ringbuffer_read_data(&v->ring, in playback_on_process()
129 v->buffer, RINGBUFFER_SIZE, in playback_on_process()
133 spa_ringbuffer_read_update(&v->ring, index); in playback_on_process()
136 buf->datas[0].chunk->offset = 0; in playback_on_process()
137 buf->datas[0].chunk->stride = v->frame_size; in playback_on_process()
138 buf->datas[0].chunk->size = n_bytes; in playback_on_process()
141 pw_stream_queue_buffer(v->stream, b); in playback_on_process()
148 PWVoice *v = (PWVoice *) data; in capture_on_process() local
155 assert(v->stream); in capture_on_process()
158 b = pw_stream_dequeue_buffer(v->stream); in capture_on_process()
165 buf = b->buffer; in capture_on_process()
166 p = buf->datas[0].data; in capture_on_process()
170 offs = SPA_MIN(buf->datas[0].chunk->offset, buf->datas[0].maxsize); in capture_on_process()
171 n_bytes = SPA_MIN(buf->datas[0].chunk->size, buf->datas[0].maxsize - offs); in capture_on_process()
173 filled = spa_ringbuffer_get_write_index(&v->ring, &index); in capture_on_process()
184 spa_ringbuffer_write_data(&v->ring, in capture_on_process()
185 v->buffer, RINGBUFFER_SIZE, in capture_on_process()
189 spa_ringbuffer_write_update(&v->ring, index); in capture_on_process()
192 pw_stream_queue_buffer(v->stream, b); in capture_on_process()
199 PWVoice *v = (PWVoice *) data; in on_stream_state_changed() local
201 trace_pw_state_changed(pw_stream_get_node_id(v->stream), in on_stream_state_changed()
223 PWVoice *v = &pw->v; in qpw_read() local
224 pwaudio *c = v->g; in qpw_read()
230 pw_thread_loop_lock(c->thread_loop); in qpw_read()
231 if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) { in qpw_read()
237 avail = spa_ringbuffer_get_read_index(&v->ring, &index); in qpw_read()
245 spa_ringbuffer_read_data(&v->ring, in qpw_read()
246 v->buffer, RINGBUFFER_SIZE, in qpw_read()
249 spa_ringbuffer_read_update(&v->ring, index); in qpw_read()
253 pw_thread_loop_unlock(c->thread_loop); in qpw_read()
260 PWVoice *v = &pw->v; in qpw_buffer_get_free() local
261 pwaudio *c = v->g; in qpw_buffer_get_free()
266 pw_thread_loop_lock(c->thread_loop); in qpw_buffer_get_free()
267 if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) { in qpw_buffer_get_free()
273 filled = spa_ringbuffer_get_write_index(&v->ring, &index); in qpw_buffer_get_free()
274 avail = v->highwater_mark - filled; in qpw_buffer_get_free()
277 pw_thread_loop_unlock(c->thread_loop); in qpw_buffer_get_free()
285 PWVoice *v = &pw->v; in qpw_write() local
286 pwaudio *c = v->g; in qpw_write()
291 pw_thread_loop_lock(c->thread_loop); in qpw_write()
292 if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) { in qpw_write()
297 filled = spa_ringbuffer_get_write_index(&v->ring, &index); in qpw_write()
298 avail = v->highwater_mark - filled; in qpw_write()
315 spa_ringbuffer_write_data(&v->ring, in qpw_write()
316 v->buffer, RINGBUFFER_SIZE, in qpw_write()
319 spa_ringbuffer_write_update(&v->ring, index); in qpw_write()
322 pw_thread_loop_unlock(c->thread_loop); in qpw_write()
420 qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name, in qpw_stream_new() argument
434 return -1; in qpw_stream_new()
438 buf_samples = (uint64_t)v->g->dev->timer_period * v->info.rate in qpw_stream_new()
441 buf_samples, v->info.rate); in qpw_stream_new()
443 trace_pw_period(buf_samples, v->info.rate); in qpw_stream_new()
447 v->stream = pw_stream_new(c->core, stream_name, props); in qpw_stream_new()
448 if (v->stream == NULL) { in qpw_stream_new()
450 return -1; in qpw_stream_new()
454 pw_stream_add_listener(v->stream, in qpw_stream_new()
455 &v->stream_listener, &capture_stream_events, v); in qpw_stream_new()
457 pw_stream_add_listener(v->stream, in qpw_stream_new()
458 &v->stream_listener, &playback_stream_events, v); in qpw_stream_new()
465 &v->info); in qpw_stream_new()
468 res = pw_stream_connect(v->stream, in qpw_stream_new()
478 pw_stream_destroy(v->stream); in qpw_stream_new()
479 return -1; in qpw_stream_new()
492 * channels is the usb-audio. We will need some means to set channel in qpw_set_position()
493 * order when a new frontend gains multi-channel support. in qpw_set_position()
522 PWVoice *v = &pw->v; in qpw_init_out() local
524 pwaudio *c = v->g = drv_opaque; in qpw_init_out()
525 AudiodevPipewireOptions *popts = &c->dev->u.pipewire; in qpw_init_out()
526 AudiodevPipewirePerDirectionOptions *ppdo = popts->out; in qpw_init_out()
529 pw_thread_loop_lock(c->thread_loop); in qpw_init_out()
531 v->info.format = audfmt_to_pw(as->fmt, as->endianness); in qpw_init_out()
532 v->info.channels = as->nchannels; in qpw_init_out()
533 qpw_set_position(as->nchannels, v->info.position); in qpw_init_out()
534 v->info.rate = as->freq; in qpw_init_out()
537 pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size); in qpw_init_out()
538 v->frame_size *= as->nchannels; in qpw_init_out()
540 v->req = (uint64_t)c->dev->timer_period * v->info.rate in qpw_init_out()
541 * 1 / 2 / 1000000 * v->frame_size; in qpw_init_out()
544 r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id, in qpw_init_out()
545 ppdo->name, SPA_DIRECTION_OUTPUT); in qpw_init_out()
547 pw_thread_loop_unlock(c->thread_loop); in qpw_init_out()
548 return -1; in qpw_init_out()
552 audio_pcm_init_info(&hw->info, &obt_as); in qpw_init_out()
555 hw->samples = audio_buffer_frames( in qpw_init_out()
557 v->highwater_mark = MIN(RINGBUFFER_SIZE, in qpw_init_out()
558 (ppdo->has_latency ? ppdo->latency : 46440) in qpw_init_out()
559 * (uint64_t)v->info.rate / 1000000 * v->frame_size); in qpw_init_out()
561 pw_thread_loop_unlock(c->thread_loop); in qpw_init_out()
569 PWVoice *v = &pw->v; in qpw_init_in() local
571 pwaudio *c = v->g = drv_opaque; in qpw_init_in()
572 AudiodevPipewireOptions *popts = &c->dev->u.pipewire; in qpw_init_in()
573 AudiodevPipewirePerDirectionOptions *ppdo = popts->in; in qpw_init_in()
576 pw_thread_loop_lock(c->thread_loop); in qpw_init_in()
578 v->info.format = audfmt_to_pw(as->fmt, as->endianness); in qpw_init_in()
579 v->info.channels = as->nchannels; in qpw_init_in()
580 qpw_set_position(as->nchannels, v->info.position); in qpw_init_in()
581 v->info.rate = as->freq; in qpw_init_in()
584 pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size); in qpw_init_in()
585 v->frame_size *= as->nchannels; in qpw_init_in()
588 r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id, in qpw_init_in()
589 ppdo->name, SPA_DIRECTION_INPUT); in qpw_init_in()
591 pw_thread_loop_unlock(c->thread_loop); in qpw_init_in()
592 return -1; in qpw_init_in()
596 audio_pcm_init_info(&hw->info, &obt_as); in qpw_init_in()
599 hw->samples = audio_buffer_frames( in qpw_init_in()
602 pw_thread_loop_unlock(c->thread_loop); in qpw_init_in()
607 qpw_voice_fini(PWVoice *v) in qpw_voice_fini() argument
609 pwaudio *c = v->g; in qpw_voice_fini()
611 if (!v->stream) { in qpw_voice_fini()
614 pw_thread_loop_lock(c->thread_loop); in qpw_voice_fini()
615 pw_stream_destroy(v->stream); in qpw_voice_fini()
616 v->stream = NULL; in qpw_voice_fini()
617 pw_thread_loop_unlock(c->thread_loop); in qpw_voice_fini()
623 qpw_voice_fini(&PW_VOICE_OUT(hw)->v); in qpw_fini_out()
629 qpw_voice_fini(&PW_VOICE_IN(hw)->v); in qpw_fini_in()
633 qpw_voice_set_enabled(PWVoice *v, bool enable) in qpw_voice_set_enabled() argument
635 pwaudio *c = v->g; in qpw_voice_set_enabled()
636 pw_thread_loop_lock(c->thread_loop); in qpw_voice_set_enabled()
637 pw_stream_set_active(v->stream, enable); in qpw_voice_set_enabled()
638 pw_thread_loop_unlock(c->thread_loop); in qpw_voice_set_enabled()
644 qpw_voice_set_enabled(&PW_VOICE_OUT(hw)->v, enable); in qpw_enable_out()
650 qpw_voice_set_enabled(&PW_VOICE_IN(hw)->v, enable); in qpw_enable_in()
654 qpw_voice_set_volume(PWVoice *v, Volume *vol) in qpw_voice_set_volume() argument
656 pwaudio *c = v->g; in qpw_voice_set_volume()
659 pw_thread_loop_lock(c->thread_loop); in qpw_voice_set_volume()
660 v->volume.channels = vol->channels; in qpw_voice_set_volume()
662 for (i = 0; i < vol->channels; ++i) { in qpw_voice_set_volume()
663 v->volume.values[i] = (float)vol->vol[i] / 255; in qpw_voice_set_volume()
666 ret = pw_stream_set_control(v->stream, in qpw_voice_set_volume()
667 SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0); in qpw_voice_set_volume()
670 v->muted = vol->mute; in qpw_voice_set_volume()
671 float val = v->muted ? 1.f : 0.f; in qpw_voice_set_volume()
672 ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0); in qpw_voice_set_volume()
673 pw_thread_loop_unlock(c->thread_loop); in qpw_voice_set_volume()
679 qpw_voice_set_volume(&PW_VOICE_OUT(hw)->v, vol); in qpw_volume_out()
685 qpw_voice_set_volume(&PW_VOICE_IN(hw)->v, vol); in qpw_volume_in()
691 pw->pending_seq = pw_core_sync(pw->core, PW_ID_CORE, pw->pending_seq); in wait_resync()
694 pw_thread_loop_wait(pw->thread_loop); in wait_resync()
696 res = pw->error; in wait_resync()
698 pw->error = 0; in wait_resync()
701 if (pw->pending_seq == pw->last_seq) { in wait_resync()
717 pw_thread_loop_signal(pw->thread_loop, FALSE); in on_core_error()
725 pw->last_seq = seq; in on_core_done()
726 if (pw->pending_seq == seq) { in on_core_done()
728 pw_thread_loop_signal(pw->thread_loop, FALSE); in on_core_done()
743 assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE); in qpw_audio_init()
748 pw->dev = dev; in qpw_audio_init()
749 pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL); in qpw_audio_init()
750 if (pw->thread_loop == NULL) { in qpw_audio_init()
755 pw->context = in qpw_audio_init()
756 pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0); in qpw_audio_init()
757 if (pw->context == NULL) { in qpw_audio_init()
762 if (pw_thread_loop_start(pw->thread_loop) < 0) { in qpw_audio_init()
767 pw_thread_loop_lock(pw->thread_loop); in qpw_audio_init()
769 pw->core = pw_context_connect(pw->context, NULL, 0); in qpw_audio_init()
770 if (pw->core == NULL) { in qpw_audio_init()
771 pw_thread_loop_unlock(pw->thread_loop); in qpw_audio_init()
776 if (pw_core_add_listener(pw->core, &pw->core_listener, in qpw_audio_init()
778 pw_thread_loop_unlock(pw->thread_loop); in qpw_audio_init()
783 pw_thread_loop_unlock(pw->thread_loop); in qpw_audio_init()
786 pw_thread_loop_unlock(pw->thread_loop); in qpw_audio_init()
791 if (pw->thread_loop) { in qpw_audio_init()
792 pw_thread_loop_stop(pw->thread_loop); in qpw_audio_init()
794 g_clear_pointer(&pw->context, pw_context_destroy); in qpw_audio_init()
795 g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy); in qpw_audio_init()
804 if (pw->thread_loop) { in qpw_audio_fini()
805 pw_thread_loop_stop(pw->thread_loop); in qpw_audio_fini()
808 if (pw->core) { in qpw_audio_fini()
809 spa_hook_remove(&pw->core_listener); in qpw_audio_fini()
810 spa_zero(pw->core_listener); in qpw_audio_fini()
811 pw_core_disconnect(pw->core); in qpw_audio_fini()
814 if (pw->context) { in qpw_audio_fini()
815 pw_context_destroy(pw->context); in qpw_audio_fini()
817 pw_thread_loop_destroy(pw->thread_loop); in qpw_audio_fini()