static void context_unlink(pa_context *c) { pa_stream *s; pa_assert(c); s = c->streams ? pa_stream_ref(c->streams) : NULL; while (s) { pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL; pa_stream_set_state(s, c->state == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED); pa_stream_unref(s); s = n; } while (c->operations) pa_operation_cancel(c->operations); if (c->pdispatch) { pa_pdispatch_unref(c->pdispatch); c->pdispatch = NULL; } if (c->pstream) { pa_pstream_unlink(c->pstream); pa_pstream_unref(c->pstream); c->pstream = NULL; } if (c->client) { pa_socket_client_unref(c->client); c->client = NULL; } reset_callbacks(c); }
int pa_stream_connect_upload(pa_stream *s, size_t length) { pa_tagstruct *t; uint32_t tag; const char *name; pa_assert(s); pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, length == (size_t) (uint32_t) length, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); if (!(name = pa_proplist_gets(s->proplist, PA_PROP_EVENT_ID))) name = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME); PA_CHECK_VALIDITY(s->context, name && *name && pa_utf8_valid(name), PA_ERR_INVALID); pa_stream_ref(s); s->direction = PA_STREAM_UPLOAD; s->flags = 0; t = pa_tagstruct_command(s->context, PA_COMMAND_CREATE_UPLOAD_STREAM, &tag); pa_tagstruct_puts(t, name); pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_put_channel_map(t, &s->channel_map); pa_tagstruct_putu32(t, (uint32_t) length); if (s->context->version >= 13) pa_tagstruct_put_proplist(t, s->proplist); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL); pa_stream_set_state(s, PA_STREAM_CREATING); pa_stream_unref(s); return 0; }
int pa_stream_finish_upload(pa_stream *s) { pa_tagstruct *t; uint32_t tag; pa_assert(s); pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED); PA_CHECK_VALIDITY(s->context, s->channel_valid, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); pa_stream_ref(s); t = pa_tagstruct_command(s->context, PA_COMMAND_FINISH_UPLOAD_STREAM, &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s, NULL); pa_stream_unref(s); return 0; }
static int do_connect_pcm(pa_stream *s, snd_pcm_stream_t stream_direction) { snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; int dir; unsigned int rate; const char *dev_name; switch (stream_direction) { default: case SND_PCM_STREAM_PLAYBACK: dev_name = getenv("APULSE_PLAYBACK_DEVICE"); CHECK_A(snd_pcm_open, (&s->ph, dev_name ? dev_name : "default", stream_direction, 0)); break; case SND_PCM_STREAM_CAPTURE: dev_name = getenv("APULSE_CAPTURE_DEVICE"); CHECK_A(snd_pcm_open, (&s->ph, dev_name ? dev_name : "default", stream_direction, 0)); break; } CHECK_A(snd_pcm_hw_params_malloc, (&hw_params)); CHECK_A(snd_pcm_hw_params_any, (s->ph, hw_params)); CHECK_A(snd_pcm_hw_params_set_access, (s->ph, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)); CHECK_A(snd_pcm_hw_params_set_format, (s->ph, hw_params, pa_format_to_alsa(s->ss.format))); CHECK_A(snd_pcm_hw_params_set_rate_resample, (s->ph, hw_params, 1)); rate = s->ss.rate; dir = 0; CHECK_A(snd_pcm_hw_params_set_rate_near, (s->ph, hw_params, &rate, &dir)); CHECK_A(snd_pcm_hw_params_set_channels, (s->ph, hw_params, s->ss.channels)); unsigned int period_time = 20 * 1000; dir = 1; CHECK_A(snd_pcm_hw_params_set_period_time_near, (s->ph, hw_params, &period_time, &dir)); unsigned int buffer_time = 4 * period_time; dir = 1; CHECK_A(snd_pcm_hw_params_set_buffer_time_near, (s->ph, hw_params, &buffer_time, &dir)); CHECK_A(snd_pcm_hw_params, (s->ph, hw_params)); snd_pcm_hw_params_free(hw_params); CHECK_A(snd_pcm_sw_params_malloc, (&sw_params)); CHECK_A(snd_pcm_sw_params_current, (s->ph, sw_params)); const snd_pcm_uframes_t period_size = (uint64_t)period_time * rate / (1000 * 1000); CHECK_A(snd_pcm_sw_params_set_avail_min, (s->ph, sw_params, period_size)); // no period event requested CHECK_A(snd_pcm_sw_params, (s->ph, sw_params)); snd_pcm_sw_params_free(sw_params); CHECK_A(snd_pcm_prepare, (s->ph)); int nfds = snd_pcm_poll_descriptors_count(s->ph); struct pollfd *fds = calloc(nfds, sizeof(struct pollfd)); s->ioe = calloc(nfds, sizeof(pa_io_event *)); s->nioe = nfds; snd_pcm_poll_descriptors(s->ph, fds, nfds); for (int k = 0; k < nfds; k ++) { pa_mainloop_api *api = s->c->mainloop_api; s->ioe[k] = api->io_new(api, fds[k].fd, 0x80000000 | fds[k].events, data_available_for_stream, s); s->ioe[k]->pcm = s->ph; } free(fds); s->state = PA_STREAM_READY; pa_stream_ref(s); s->c->mainloop_api->defer_new(s->c->mainloop_api, deh_stream_state_changed, s); pa_stream_ref(s); s->c->mainloop_api->defer_new(s->c->mainloop_api, deh_stream_first_readwrite_callback, s); return 0; err: return -1; }