/* Called from IO context */ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { struct userdata *u = PA_SINK(o)->userdata; switch (code) { case PA_SINK_MESSAGE_GET_LATENCY: { pa_usec_t r = 0; if (u->fd >= 0) { if (u->use_mmap) r = mmap_sink_get_latency(u); else r = io_sink_get_latency(u); } *((int64_t*) data) = (int64_t)r; return 0; } } return pa_sink_process_msg(o, code, data, offset, chunk); }
/* Called from IO context */ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { struct userdata *u = PA_SINK(o)->userdata; int ret; pa_bool_t do_trigger = FALSE, quick = TRUE; switch (code) { case PA_SINK_MESSAGE_GET_LATENCY: { pa_usec_t r = 0; if (u->fd >= 0) { if (u->use_mmap) r = mmap_sink_get_latency(u); else r = io_sink_get_latency(u); } *((pa_usec_t*) data) = r; return 0; } case PA_SINK_MESSAGE_SET_STATE: switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) { case PA_SINK_SUSPENDED: pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state)); if (!u->source || u->source_suspended) { if (suspend(u) < 0) return -1; } do_trigger = TRUE; u->sink_suspended = TRUE; break; case PA_SINK_IDLE: case PA_SINK_RUNNING: if (u->sink->thread_info.state == PA_SINK_INIT) { do_trigger = TRUE; quick = u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state); } if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { if (!u->source || u->source_suspended) { if (unsuspend(u) < 0) return -1; quick = FALSE; } do_trigger = TRUE; u->out_mmap_current = 0; u->out_mmap_saved_nfrags = 0; u->sink_suspended = FALSE; } break; case PA_SINK_INVALID_STATE: case PA_SINK_UNLINKED: case PA_SINK_INIT: ; } break; } ret = pa_sink_process_msg(o, code, data, offset, chunk); if (ret >= 0 && do_trigger) { if (trigger(u, quick) < 0) return -1; } return ret; }