static PyObject* PulseAudio_set_volume(output_PulseAudio *self, PyObject *args) { pa_cvolume cvolume; pa_operation *op; struct get_volume_cb_data cb_data = {self->mainloop, &cvolume}; double new_volume_d; pa_volume_t new_volume; if (!PyArg_ParseTuple(args, "d", &new_volume_d)) return NULL; /*ensure output stream is still running*/ /*FIXME*/ /*convert volume to integer pa_volume_t value between PA_VOLUME_MUTED and PA_VOLUME_NORM*/ new_volume = round(new_volume_d * PA_VOLUME_NORM); pa_threaded_mainloop_lock(self->mainloop); /*query stream info for current sink*/ op = pa_context_get_sink_info_by_index( self->context, pa_stream_get_device_index(self->stream), (pa_sink_info_cb_t)get_volume_callback, &cb_data); /*wait for callback to complete*/ while (pa_operation_get_state(op) == PA_OPERATION_RUNNING) { pa_threaded_mainloop_wait(self->mainloop); } pa_operation_unref(op); /*scale values using the new volume setting*/ pa_cvolume_scale(&cvolume, new_volume); /*set sink's volume values*/ op = pa_context_set_sink_volume_by_index( self->context, pa_stream_get_device_index(self->stream), &cvolume, (pa_context_success_cb_t)set_volume_callback, self->mainloop); /*wait for callback to complete*/ while (pa_operation_get_state(op) == PA_OPERATION_RUNNING) { pa_threaded_mainloop_wait(self->mainloop); } pa_operation_unref(op); pa_threaded_mainloop_unlock(self->mainloop); Py_INCREF(Py_None); return Py_None; }
void AudioOutputPulseAudio::SetVolumeChannel(int channel, int volume) { QString fn_log_tag = "SetVolumeChannel, "; if (channel < 0 || channel > PULSE_MAX_CHANNELS || volume < 0) { VBERROR(fn_log_tag + QString("bad volume params, channel %1, volume %2") .arg(channel).arg(volume)); return; } volume_control.values[channel] = (float)volume / 100.0f * (float)PA_VOLUME_NORM; volume = min(100, volume); volume = max(0, volume); uint32_t sink_index = pa_stream_get_device_index(pstream); pa_threaded_mainloop_lock(mainloop); pa_operation *op = pa_context_set_sink_volume_by_index(pcontext, sink_index, &volume_control, OpCompletionCallback, this); pa_threaded_mainloop_unlock(mainloop); if (op) pa_operation_unref(op); else VBERROR(fn_log_tag + QString("set sink volume operation failed, sink %1, error %2 ") .arg(sink_index).arg(pa_strerror(pa_context_errno(pcontext)))); }
void on_monitor_read_callback(pa_stream *p, size_t length, void *userdata) { const void *data; double v; printf("read callback length: %d\n", length); printf("\tget_device_index: %d\n", pa_stream_get_device_index(p)); printf("\tget_device_name: %s\n", pa_stream_get_device_name(p)); printf("\tget_monitor_stream: %d\n", pa_stream_get_monitor_stream(p)); if (pa_stream_peek(p, &data, &length) < 0) { printf("Failed to read data from stream\n"); return; } assert(length > 0); assert(length % sizeof(float) == 0); v = ((const float*) data)[length / sizeof(float) -1]; pa_stream_drop(p); if (v < 0) v = 0; //if (v > 1) v = 1; printf("\tread callback peek: %f\n", v); ret = v; g_main_loop_quit(mainloop); }
static void stream_moved_cb(pa_stream *s, void *userdata) { demux_t *demux = userdata; uint32_t idx = pa_stream_get_device_index(s); msg_Dbg(demux, "connected to source %"PRIu32": %s", idx, pa_stream_get_device_name(s)); stream_buffer_attr_cb(s, userdata); }
/** * Pulseaudio stream state callback */ static void stream_state_callback (pa_stream * s, void *userdata) { GNUNET_assert (NULL != s); switch (pa_stream_get_state (s)) { case PA_STREAM_CREATING: case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: { const pa_buffer_attr *a; char cmt[PA_CHANNEL_MAP_SNPRINT_MAX]; char sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stream successfully created.\n")); if (!(a = pa_stream_get_buffer_attr (s))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_get_buffer_attr() failed: %s\n"), pa_strerror (pa_context_errno (pa_stream_get_context (s)))); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Buffer metrics: maxlength=%u, fragsize=%u\n"), a->maxlength, a->fragsize); } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Using sample spec '%s', channel map '%s'.\n"), pa_sample_spec_snprint (sst, sizeof (sst), pa_stream_get_sample_spec (s)), pa_channel_map_snprint (cmt, sizeof (cmt), pa_stream_get_channel_map (s))); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connected to device %s (%u, %ssuspended).\n"), pa_stream_get_device_name (s), pa_stream_get_device_index (s), pa_stream_is_suspended (s) ? "" : "not "); } break; case PA_STREAM_FAILED: default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Stream error: %s\n"), pa_strerror (pa_context_errno (pa_stream_get_context (s)))); quit (1); } }
static gchar * gst_pulsesrc_device_description (GstPulseSrc * pulsesrc) { pa_operation *o = NULL; gchar *t; if (!pulsesrc->mainloop) goto no_mainloop; pa_threaded_mainloop_lock (pulsesrc->mainloop); if (!pulsesrc->stream) goto unlock; if (!(o = pa_context_get_source_info_by_index (pulsesrc->context, pa_stream_get_device_index (pulsesrc->stream), gst_pulsesrc_source_info_cb, pulsesrc))) { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("pa_stream_get_source_info() failed: %s", pa_strerror (pa_context_errno (pulsesrc->context))), (NULL)); goto unlock; } while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) { if (gst_pulsesrc_is_dead (pulsesrc)) goto unlock; pa_threaded_mainloop_wait (pulsesrc->mainloop); } unlock: if (o) pa_operation_unref (o); t = g_strdup (pulsesrc->device_description); pa_threaded_mainloop_unlock (pulsesrc->mainloop); return t; no_mainloop: { GST_DEBUG_OBJECT (pulsesrc, "have no mainloop"); return NULL; } }
static void stream_moved_cb(pa_stream *s, void *userdata) { audio_output_t *aout = userdata; aout_sys_t *sys = aout->sys; const char *name = pa_stream_get_device_name(s); struct sink *sink = sink_find(sys, pa_stream_get_device_index(s)); msg_Dbg(aout, "connected to sink %s", name); aout_DeviceReport(aout, name); sys->base_volume = likely(sink != NULL) ? sink->base_volume : PA_VOLUME_INVALID; msg_Dbg(aout, "base volume: %"PRIu32, sys->base_volume); if (pa_cvolume_valid(&sys->cvolume)) VolumeReport(aout); }
/* This routine is called whenever the stream state changes */ static void stream_state_callback(pa_stream *s, void *userdata) { pa_assert(s); switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: if (verbose) { const pa_buffer_attr *a; char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_log(_("Stream successfully created.")); if (!(a = pa_stream_get_buffer_attr(s))) pa_log(_("pa_stream_get_buffer_attr() failed: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); else { if (mode == PLAYBACK) pa_log(_("Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u"), a->maxlength, a->tlength, a->prebuf, a->minreq); else { pa_assert(mode == RECORD); pa_log(_("Buffer metrics: maxlength=%u, fragsize=%u"), a->maxlength, a->fragsize); } } pa_log(_("Using sample spec '%s', channel map '%s'."), pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)), pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); pa_log(_("Connected to device %s (%u, %ssuspended)."), pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); } break; case PA_STREAM_FAILED: default: pa_log(_("Stream error: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); quit(1); } }
static void gst_pulsesrc_source_info_cb (pa_context * c, const pa_source_info * i, int eol, void *userdata) { GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata); if (!i) return; if (!pulsesrc->stream) return; g_assert (i->index == pa_stream_get_device_index (pulsesrc->stream)); g_free (pulsesrc->device_description); pulsesrc->device_description = g_strdup (i->description); }
void stream_state_callback(pa_stream *s, void *userdata) { assert(s); switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: break; case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: if (verbose) { const pa_buffer_attr *a; char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; printf("Stream successfully created.\n"); if (!(a = pa_stream_get_buffer_attr(s))) printf("pa_stream_get_buffer_attr() failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); else { printf("Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize); } /* printf("Using sample spec '%s', channel map '%s'.", pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)), pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); */ printf("Connected to device %s (%u, %ssuspended).\n", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); } break; case PA_STREAM_FAILED: default: printf("Stream error: %s", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); exit(1); //quit(1); } }
void stream_state_callback(pa_stream *s, void *userdata) { struct sound_dev *dev = userdata; assert(s); assert(dev); switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: break; case PA_STREAM_TERMINATED: if (quisk_sound_state.verbose_pulse) printf("stream %s terminated\n", dev->name); streams_ready--; break; case PA_STREAM_READY: streams_ready++; //increment counter to tell other thread that this stream is ready if (quisk_sound_state.verbose_pulse) { const pa_buffer_attr *a; printf("Connected to device %s (%u, %ssuspended). ", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); if (!(a = pa_stream_get_buffer_attr(s))) printf("pa_stream_get_buffer_attr() failed: %s", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); else if (!(a->prebuf)) { printf("Buffer metrics %s: maxlength=%u, fragsize=%u\n", dev->name, a->maxlength, a->fragsize); } else { printf("Buffer metrics %s: maxlength=%u, prebuf=%u, tlength=%u minreq=%u\n", dev->name, a->maxlength, a->prebuf, a->tlength, a->minreq); } } break; case PA_STREAM_FAILED: default: printf("Stream error: %s - %s\n", dev->name, pa_strerror(pa_context_errno(pa_stream_get_context(s)))); exit(1); } }
static PyObject* PulseAudio_get_volume(output_PulseAudio *self, PyObject *args) { pa_cvolume cvolume; pa_operation *op; struct get_volume_cb_data cb_data = {self->mainloop, &cvolume}; double max_volume; double norm_volume; pa_threaded_mainloop_lock(self->mainloop); /*ensure outuput stream is still running*/ /*FIXME*/ /*query stream info for current sink*/ op = pa_context_get_sink_info_by_index( self->context, pa_stream_get_device_index(self->stream), (pa_sink_info_cb_t)get_volume_callback, &cb_data); /*wait for callback to complete*/ while (pa_operation_get_state(op) == PA_OPERATION_RUNNING) { pa_threaded_mainloop_wait(self->mainloop); } /*ensure operation has completed successfully before using cvolume*/ /*FIXME*/ pa_operation_unref(op); pa_threaded_mainloop_unlock(self->mainloop); /*convert cvolume to double*/ max_volume = pa_cvolume_max(&cvolume); norm_volume = PA_VOLUME_NORM; /*return double converted to Python object*/ return PyFloat_FromDouble(max_volume / norm_volume); }
static void stream_moved_callback(pa_stream *s, void *userdata) { assert(s); if (verbose) fprintf(stderr, "Stream moved to device %s (%u, %ssuspended).%s \n", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not ", CLEAR_LINE); }
static void stream_moved_callback(pa_stream *s, void *userdata) { pa_assert(s); if (verbose) pa_log(_("Stream moved to device %s (%u, %ssuspended).%s"), pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : _("not "), CLEAR_LINE); }
void QPulseAudioThread::stream_moved_callback(pa_stream *s, void *userdata) { Q_ASSERT(s); if (verbose) fprintf(stderr, "Stream moved to device %s (%u, %ssuspended).\n", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); }
/***************************************************************************** * Open: open the audio device *****************************************************************************/ static int Open ( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys; struct pa_sample_spec ss; const struct pa_buffer_attr *buffer_attr; struct pa_buffer_attr a; struct pa_channel_map map; /* Allocate structures */ p_aout->output.p_sys = p_sys = calloc( 1, sizeof( aout_sys_t ) ); if( p_sys == NULL ) return VLC_ENOMEM; PULSE_DEBUG( "Pulse start initialization"); ss.channels = aout_FormatNbChannels( &p_aout->output.output ); /* Get the input stream channel count */ /* Setup the pulse audio stream based on the input stream count */ switch(ss.channels) { case 8: p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; break; case 6: p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; break; case 4: p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; break; case 2: p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; break; case 1: p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; break; default: msg_Err(p_aout,"Invalid number of channels"); goto fail; } /* Add a quick command line info message */ msg_Info(p_aout, "No. of Audio Channels: %d", ss.channels); ss.rate = p_aout->output.output.i_rate; ss.format = PA_SAMPLE_FLOAT32NE; p_aout->output.output.i_format = VLC_CODEC_FL32; if (!pa_sample_spec_valid(&ss)) { msg_Err(p_aout,"Invalid sample spec"); goto fail; } /* Reduce overall latency to 200mS to reduce audible clicks * Also pulse minreq and internal buffers are now 20mS which reduces resampling */ a.tlength = pa_bytes_per_second(&ss)/5; a.maxlength = a.tlength * 2; a.prebuf = a.tlength / 2; a.minreq = a.tlength / 10; /* Buffer size is 20mS */ p_sys->buffer_size = a.minreq; /* Initialise the speaker map setup above */ pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); if (!(p_sys->mainloop = pa_threaded_mainloop_new())) { msg_Err(p_aout, "Failed to allocate main loop"); goto fail; } if (!(p_sys->context = pa_context_new(pa_threaded_mainloop_get_api(p_sys->mainloop), _( PULSE_CLIENT_NAME )))) { msg_Err(p_aout, "Failed to allocate context"); goto fail; } pa_context_set_state_callback(p_sys->context, context_state_cb, p_aout); PULSE_DEBUG( "Pulse before context connect"); if (pa_context_connect(p_sys->context, NULL, 0, NULL) < 0) { msg_Err(p_aout, "Failed to connect to server: %s", pa_strerror(pa_context_errno(p_sys->context))); goto fail; } PULSE_DEBUG( "Pulse after context connect"); pa_threaded_mainloop_lock(p_sys->mainloop); if (pa_threaded_mainloop_start(p_sys->mainloop) < 0) { msg_Err(p_aout, "Failed to start main loop"); goto unlock_and_fail; } msg_Dbg(p_aout, "Pulse mainloop started"); /* Wait until the context is ready */ pa_threaded_mainloop_wait(p_sys->mainloop); if (pa_context_get_state(p_sys->context) != PA_CONTEXT_READY) { msg_Err(p_aout, "Failed to connect to server: %s", pa_strerror(pa_context_errno(p_sys->context))); goto unlock_and_fail; } if (!(p_sys->stream = pa_stream_new(p_sys->context, "audio stream", &ss, &map))) { msg_Err(p_aout, "Failed to create stream: %s", pa_strerror(pa_context_errno(p_sys->context))); goto unlock_and_fail; } PULSE_DEBUG( "Pulse after new stream"); pa_stream_set_state_callback(p_sys->stream, stream_state_cb, p_aout); pa_stream_set_write_callback(p_sys->stream, stream_request_cb, p_aout); pa_stream_set_latency_update_callback(p_sys->stream, stream_latency_update_cb, p_aout); if (pa_stream_connect_playback(p_sys->stream, NULL, &a, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_ADJUST_LATENCY, NULL, NULL) < 0) { msg_Err(p_aout, "Failed to connect stream: %s", pa_strerror(pa_context_errno(p_sys->context))); goto unlock_and_fail; } PULSE_DEBUG("Pulse stream connect"); /* Wait until the stream is ready */ pa_threaded_mainloop_wait(p_sys->mainloop); msg_Dbg(p_aout,"Pulse stream connected"); if (pa_stream_get_state(p_sys->stream) != PA_STREAM_READY) { msg_Err(p_aout, "Failed to connect to server: %s", pa_strerror(pa_context_errno(p_sys->context))); goto unlock_and_fail; } PULSE_DEBUG("Pulse after stream get status"); pa_threaded_mainloop_unlock(p_sys->mainloop); buffer_attr = pa_stream_get_buffer_attr(p_sys->stream); p_aout->output.i_nb_samples = buffer_attr->minreq / pa_frame_size(&ss); p_aout->output.pf_play = Play; aout_VolumeSoftInit(p_aout); msg_Dbg(p_aout, "Pulse initialized successfully"); { char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; msg_Dbg(p_aout, "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u", buffer_attr->maxlength, buffer_attr->tlength, buffer_attr->prebuf, buffer_attr->minreq); msg_Dbg(p_aout, "Using sample spec '%s', channel map '%s'.", pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(p_sys->stream)), pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(p_sys->stream))); msg_Dbg(p_aout, "Connected to device %s (%u, %ssuspended).", pa_stream_get_device_name(p_sys->stream), pa_stream_get_device_index(p_sys->stream), pa_stream_is_suspended(p_sys->stream) ? "" : "not "); } return VLC_SUCCESS; unlock_and_fail: msg_Dbg(p_aout, "Pulse initialization unlock and fail"); if (p_sys->mainloop) pa_threaded_mainloop_unlock(p_sys->mainloop); fail: msg_Err(p_aout, "Pulse initialization failed"); uninit(p_aout); return VLC_EGENERIC; }