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; }
pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) { pa_volume_t m; pa_assert(v); pa_return_val_if_fail(pa_cvolume_valid(v), NULL); pa_return_val_if_fail(PA_VOLUME_IS_VALID(dec), NULL); m = pa_cvolume_max(v); if (m <= PA_VOLUME_MUTED + dec) m = PA_VOLUME_MUTED; else m -= dec; return pa_cvolume_scale(v, m); }
pa_cvolume* pa_cvolume_inc_clamp(pa_cvolume *v, pa_volume_t inc, pa_volume_t limit) { pa_volume_t m; pa_assert(v); pa_return_val_if_fail(pa_cvolume_valid(v), NULL); pa_return_val_if_fail(PA_VOLUME_IS_VALID(inc), NULL); m = pa_cvolume_max(v); if (m >= limit - inc) m = limit; else m += inc; return pa_cvolume_scale(v, m); }
pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, pa_channel_map *cm, pa_channel_position_mask_t mask) { unsigned c; pa_volume_t t = 0; pa_assert(v); pa_return_val_if_fail(PA_VOLUME_IS_VALID(max), NULL); if (!cm) return pa_cvolume_scale(v, max); pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, cm), NULL); t = pa_cvolume_max_mask(v, cm, mask); if (t <= PA_VOLUME_MUTED) return pa_cvolume_set(v, v->channels, max); for (c = 0; c < v->channels; c++) v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) max) / (uint64_t) t); return v; }