153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2009 Tanu Kaskinen 553a5a1b3Sopenharmony_ci 653a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 753a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 853a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 953a5a1b3Sopenharmony_ci or (at your option) any later version. 1053a5a1b3Sopenharmony_ci 1153a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1253a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1353a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1453a5a1b3Sopenharmony_ci General Public License for more details. 1553a5a1b3Sopenharmony_ci 1653a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1753a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1853a5a1b3Sopenharmony_ci***/ 1953a5a1b3Sopenharmony_ci 2053a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2153a5a1b3Sopenharmony_ci#include <config.h> 2253a5a1b3Sopenharmony_ci#endif 2353a5a1b3Sopenharmony_ci 2453a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 2553a5a1b3Sopenharmony_ci#include <pulsecore/dbus-util.h> 2653a5a1b3Sopenharmony_ci#include <pulsecore/namereg.h> 2753a5a1b3Sopenharmony_ci#include <pulsecore/protocol-dbus.h> 2853a5a1b3Sopenharmony_ci 2953a5a1b3Sopenharmony_ci#include "iface-sample.h" 3053a5a1b3Sopenharmony_ci 3153a5a1b3Sopenharmony_ci#define OBJECT_NAME "sample" 3253a5a1b3Sopenharmony_ci 3353a5a1b3Sopenharmony_cistruct pa_dbusiface_sample { 3453a5a1b3Sopenharmony_ci pa_dbusiface_core *core; 3553a5a1b3Sopenharmony_ci 3653a5a1b3Sopenharmony_ci pa_scache_entry *sample; 3753a5a1b3Sopenharmony_ci char *path; 3853a5a1b3Sopenharmony_ci pa_proplist *proplist; 3953a5a1b3Sopenharmony_ci 4053a5a1b3Sopenharmony_ci pa_hook_slot *sample_cache_changed_slot; 4153a5a1b3Sopenharmony_ci 4253a5a1b3Sopenharmony_ci pa_dbus_protocol *dbus_protocol; 4353a5a1b3Sopenharmony_ci}; 4453a5a1b3Sopenharmony_ci 4553a5a1b3Sopenharmony_cistatic void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); 4653a5a1b3Sopenharmony_cistatic void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); 4753a5a1b3Sopenharmony_cistatic void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata); 4853a5a1b3Sopenharmony_cistatic void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata); 4953a5a1b3Sopenharmony_cistatic void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata); 5053a5a1b3Sopenharmony_cistatic void handle_get_default_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); 5153a5a1b3Sopenharmony_cistatic void handle_get_duration(DBusConnection *conn, DBusMessage *msg, void *userdata); 5253a5a1b3Sopenharmony_cistatic void handle_get_bytes(DBusConnection *conn, DBusMessage *msg, void *userdata); 5353a5a1b3Sopenharmony_cistatic void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); 5453a5a1b3Sopenharmony_ci 5553a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); 5653a5a1b3Sopenharmony_ci 5753a5a1b3Sopenharmony_cistatic void handle_play(DBusConnection *conn, DBusMessage *msg, void *userdata); 5853a5a1b3Sopenharmony_cistatic void handle_play_to_sink(DBusConnection *conn, DBusMessage *msg, void *userdata); 5953a5a1b3Sopenharmony_cistatic void handle_remove(DBusConnection *conn, DBusMessage *msg, void *userdata); 6053a5a1b3Sopenharmony_ci 6153a5a1b3Sopenharmony_cienum property_handler_index { 6253a5a1b3Sopenharmony_ci PROPERTY_HANDLER_INDEX, 6353a5a1b3Sopenharmony_ci PROPERTY_HANDLER_NAME, 6453a5a1b3Sopenharmony_ci PROPERTY_HANDLER_SAMPLE_FORMAT, 6553a5a1b3Sopenharmony_ci PROPERTY_HANDLER_SAMPLE_RATE, 6653a5a1b3Sopenharmony_ci PROPERTY_HANDLER_CHANNELS, 6753a5a1b3Sopenharmony_ci PROPERTY_HANDLER_DEFAULT_VOLUME, 6853a5a1b3Sopenharmony_ci PROPERTY_HANDLER_DURATION, 6953a5a1b3Sopenharmony_ci PROPERTY_HANDLER_BYTES, 7053a5a1b3Sopenharmony_ci PROPERTY_HANDLER_PROPERTY_LIST, 7153a5a1b3Sopenharmony_ci PROPERTY_HANDLER_MAX 7253a5a1b3Sopenharmony_ci}; 7353a5a1b3Sopenharmony_ci 7453a5a1b3Sopenharmony_cistatic pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { 7553a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, 7653a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, 7753a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_SAMPLE_FORMAT] = { .property_name = "SampleFormat", .type = "u", .get_cb = handle_get_sample_format, .set_cb = NULL }, 7853a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_SAMPLE_RATE] = { .property_name = "SampleRate", .type = "u", .get_cb = handle_get_sample_rate, .set_cb = NULL }, 7953a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_CHANNELS] = { .property_name = "Channels", .type = "au", .get_cb = handle_get_channels, .set_cb = NULL }, 8053a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_DEFAULT_VOLUME] = { .property_name = "DefaultVolume", .type = "au", .get_cb = handle_get_default_volume, .set_cb = NULL }, 8153a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_DURATION] = { .property_name = "Duration", .type = "t", .get_cb = handle_get_duration, .set_cb = NULL }, 8253a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_BYTES] = { .property_name = "Bytes", .type = "u", .get_cb = handle_get_bytes, .set_cb = NULL }, 8353a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } 8453a5a1b3Sopenharmony_ci}; 8553a5a1b3Sopenharmony_ci 8653a5a1b3Sopenharmony_cienum method_handler_index { 8753a5a1b3Sopenharmony_ci METHOD_HANDLER_PLAY, 8853a5a1b3Sopenharmony_ci METHOD_HANDLER_PLAY_TO_SINK, 8953a5a1b3Sopenharmony_ci METHOD_HANDLER_REMOVE, 9053a5a1b3Sopenharmony_ci METHOD_HANDLER_MAX 9153a5a1b3Sopenharmony_ci}; 9253a5a1b3Sopenharmony_ci 9353a5a1b3Sopenharmony_cistatic pa_dbus_arg_info play_args[] = { { "volume", "u", "in" }, { "property_list", "a{say}", "in" } }; 9453a5a1b3Sopenharmony_cistatic pa_dbus_arg_info play_to_sink_args[] = { { "sink", "o", "in" }, 9553a5a1b3Sopenharmony_ci { "volume", "u", "in" }, 9653a5a1b3Sopenharmony_ci { "property_list", "a{say}", "in" } }; 9753a5a1b3Sopenharmony_ci 9853a5a1b3Sopenharmony_cistatic pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { 9953a5a1b3Sopenharmony_ci [METHOD_HANDLER_PLAY] = { 10053a5a1b3Sopenharmony_ci .method_name = "Play", 10153a5a1b3Sopenharmony_ci .arguments = play_args, 10253a5a1b3Sopenharmony_ci .n_arguments = sizeof(play_args) / sizeof(pa_dbus_arg_info), 10353a5a1b3Sopenharmony_ci .receive_cb = handle_play }, 10453a5a1b3Sopenharmony_ci [METHOD_HANDLER_PLAY_TO_SINK] = { 10553a5a1b3Sopenharmony_ci .method_name = "PlayToSink", 10653a5a1b3Sopenharmony_ci .arguments = play_to_sink_args, 10753a5a1b3Sopenharmony_ci .n_arguments = sizeof(play_to_sink_args) / sizeof(pa_dbus_arg_info), 10853a5a1b3Sopenharmony_ci .receive_cb = handle_play_to_sink }, 10953a5a1b3Sopenharmony_ci [METHOD_HANDLER_REMOVE] = { 11053a5a1b3Sopenharmony_ci .method_name = "Remove", 11153a5a1b3Sopenharmony_ci .arguments = NULL, 11253a5a1b3Sopenharmony_ci .n_arguments = 0, 11353a5a1b3Sopenharmony_ci .receive_cb = handle_remove } 11453a5a1b3Sopenharmony_ci}; 11553a5a1b3Sopenharmony_ci 11653a5a1b3Sopenharmony_cienum signal_index { 11753a5a1b3Sopenharmony_ci SIGNAL_PROPERTY_LIST_UPDATED, 11853a5a1b3Sopenharmony_ci SIGNAL_MAX 11953a5a1b3Sopenharmony_ci}; 12053a5a1b3Sopenharmony_ci 12153a5a1b3Sopenharmony_cistatic pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; 12253a5a1b3Sopenharmony_ci 12353a5a1b3Sopenharmony_cistatic pa_dbus_signal_info signals[SIGNAL_MAX] = { 12453a5a1b3Sopenharmony_ci [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 } 12553a5a1b3Sopenharmony_ci}; 12653a5a1b3Sopenharmony_ci 12753a5a1b3Sopenharmony_cistatic pa_dbus_interface_info sample_interface_info = { 12853a5a1b3Sopenharmony_ci .name = PA_DBUSIFACE_SAMPLE_INTERFACE, 12953a5a1b3Sopenharmony_ci .method_handlers = method_handlers, 13053a5a1b3Sopenharmony_ci .n_method_handlers = METHOD_HANDLER_MAX, 13153a5a1b3Sopenharmony_ci .property_handlers = property_handlers, 13253a5a1b3Sopenharmony_ci .n_property_handlers = PROPERTY_HANDLER_MAX, 13353a5a1b3Sopenharmony_ci .get_all_properties_cb = handle_get_all, 13453a5a1b3Sopenharmony_ci .signals = signals, 13553a5a1b3Sopenharmony_ci .n_signals = SIGNAL_MAX 13653a5a1b3Sopenharmony_ci}; 13753a5a1b3Sopenharmony_ci 13853a5a1b3Sopenharmony_cistatic void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { 13953a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 14053a5a1b3Sopenharmony_ci dbus_uint32_t idx = 0; 14153a5a1b3Sopenharmony_ci 14253a5a1b3Sopenharmony_ci pa_assert(conn); 14353a5a1b3Sopenharmony_ci pa_assert(msg); 14453a5a1b3Sopenharmony_ci pa_assert(s); 14553a5a1b3Sopenharmony_ci 14653a5a1b3Sopenharmony_ci idx = s->sample->index; 14753a5a1b3Sopenharmony_ci 14853a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); 14953a5a1b3Sopenharmony_ci} 15053a5a1b3Sopenharmony_ci 15153a5a1b3Sopenharmony_cistatic void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { 15253a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 15353a5a1b3Sopenharmony_ci 15453a5a1b3Sopenharmony_ci pa_assert(conn); 15553a5a1b3Sopenharmony_ci pa_assert(msg); 15653a5a1b3Sopenharmony_ci pa_assert(s); 15753a5a1b3Sopenharmony_ci 15853a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &s->sample->name); 15953a5a1b3Sopenharmony_ci} 16053a5a1b3Sopenharmony_ci 16153a5a1b3Sopenharmony_cistatic void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) { 16253a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 16353a5a1b3Sopenharmony_ci dbus_uint32_t sample_format = 0; 16453a5a1b3Sopenharmony_ci 16553a5a1b3Sopenharmony_ci pa_assert(conn); 16653a5a1b3Sopenharmony_ci pa_assert(msg); 16753a5a1b3Sopenharmony_ci pa_assert(s); 16853a5a1b3Sopenharmony_ci 16953a5a1b3Sopenharmony_ci if (!s->sample->memchunk.memblock) { 17053a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 17153a5a1b3Sopenharmony_ci "Sample %s isn't loaded into memory yet, so its sample format is unknown.", s->sample->name); 17253a5a1b3Sopenharmony_ci return; 17353a5a1b3Sopenharmony_ci } 17453a5a1b3Sopenharmony_ci 17553a5a1b3Sopenharmony_ci sample_format = s->sample->sample_spec.format; 17653a5a1b3Sopenharmony_ci 17753a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_format); 17853a5a1b3Sopenharmony_ci} 17953a5a1b3Sopenharmony_ci 18053a5a1b3Sopenharmony_cistatic void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) { 18153a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 18253a5a1b3Sopenharmony_ci dbus_uint32_t sample_rate = 0; 18353a5a1b3Sopenharmony_ci 18453a5a1b3Sopenharmony_ci pa_assert(conn); 18553a5a1b3Sopenharmony_ci pa_assert(msg); 18653a5a1b3Sopenharmony_ci pa_assert(s); 18753a5a1b3Sopenharmony_ci 18853a5a1b3Sopenharmony_ci if (!s->sample->memchunk.memblock) { 18953a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 19053a5a1b3Sopenharmony_ci "Sample %s isn't loaded into memory yet, so its sample rate is unknown.", s->sample->name); 19153a5a1b3Sopenharmony_ci return; 19253a5a1b3Sopenharmony_ci } 19353a5a1b3Sopenharmony_ci 19453a5a1b3Sopenharmony_ci sample_rate = s->sample->sample_spec.rate; 19553a5a1b3Sopenharmony_ci 19653a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_rate); 19753a5a1b3Sopenharmony_ci} 19853a5a1b3Sopenharmony_ci 19953a5a1b3Sopenharmony_cistatic void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) { 20053a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 20153a5a1b3Sopenharmony_ci dbus_uint32_t channels[PA_CHANNELS_MAX]; 20253a5a1b3Sopenharmony_ci unsigned i = 0; 20353a5a1b3Sopenharmony_ci 20453a5a1b3Sopenharmony_ci pa_assert(conn); 20553a5a1b3Sopenharmony_ci pa_assert(msg); 20653a5a1b3Sopenharmony_ci pa_assert(s); 20753a5a1b3Sopenharmony_ci 20853a5a1b3Sopenharmony_ci if (!s->sample->memchunk.memblock) { 20953a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 21053a5a1b3Sopenharmony_ci "Sample %s isn't loaded into memory yet, so its channel map is unknown.", s->sample->name); 21153a5a1b3Sopenharmony_ci return; 21253a5a1b3Sopenharmony_ci } 21353a5a1b3Sopenharmony_ci 21453a5a1b3Sopenharmony_ci for (i = 0; i < s->sample->channel_map.channels; ++i) 21553a5a1b3Sopenharmony_ci channels[i] = s->sample->channel_map.map[i]; 21653a5a1b3Sopenharmony_ci 21753a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, channels, s->sample->channel_map.channels); 21853a5a1b3Sopenharmony_ci} 21953a5a1b3Sopenharmony_ci 22053a5a1b3Sopenharmony_cistatic void handle_get_default_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { 22153a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 22253a5a1b3Sopenharmony_ci dbus_uint32_t default_volume[PA_CHANNELS_MAX]; 22353a5a1b3Sopenharmony_ci unsigned i = 0; 22453a5a1b3Sopenharmony_ci 22553a5a1b3Sopenharmony_ci pa_assert(conn); 22653a5a1b3Sopenharmony_ci pa_assert(msg); 22753a5a1b3Sopenharmony_ci pa_assert(s); 22853a5a1b3Sopenharmony_ci 22953a5a1b3Sopenharmony_ci if (!s->sample->volume_is_set) { 23053a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 23153a5a1b3Sopenharmony_ci "Sample %s doesn't have default volume stored.", s->sample->name); 23253a5a1b3Sopenharmony_ci return; 23353a5a1b3Sopenharmony_ci } 23453a5a1b3Sopenharmony_ci 23553a5a1b3Sopenharmony_ci for (i = 0; i < s->sample->volume.channels; ++i) 23653a5a1b3Sopenharmony_ci default_volume[i] = s->sample->volume.values[i]; 23753a5a1b3Sopenharmony_ci 23853a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, default_volume, s->sample->volume.channels); 23953a5a1b3Sopenharmony_ci} 24053a5a1b3Sopenharmony_ci 24153a5a1b3Sopenharmony_cistatic void handle_get_duration(DBusConnection *conn, DBusMessage *msg, void *userdata) { 24253a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 24353a5a1b3Sopenharmony_ci dbus_uint64_t duration = 0; 24453a5a1b3Sopenharmony_ci 24553a5a1b3Sopenharmony_ci pa_assert(conn); 24653a5a1b3Sopenharmony_ci pa_assert(msg); 24753a5a1b3Sopenharmony_ci pa_assert(s); 24853a5a1b3Sopenharmony_ci 24953a5a1b3Sopenharmony_ci if (!s->sample->memchunk.memblock) { 25053a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 25153a5a1b3Sopenharmony_ci "Sample %s isn't loaded into memory yet, so its duration is unknown.", s->sample->name); 25253a5a1b3Sopenharmony_ci return; 25353a5a1b3Sopenharmony_ci } 25453a5a1b3Sopenharmony_ci 25553a5a1b3Sopenharmony_ci duration = pa_bytes_to_usec(s->sample->memchunk.length, &s->sample->sample_spec); 25653a5a1b3Sopenharmony_ci 25753a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &duration); 25853a5a1b3Sopenharmony_ci} 25953a5a1b3Sopenharmony_ci 26053a5a1b3Sopenharmony_cistatic void handle_get_bytes(DBusConnection *conn, DBusMessage *msg, void *userdata) { 26153a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 26253a5a1b3Sopenharmony_ci dbus_uint32_t bytes = 0; 26353a5a1b3Sopenharmony_ci 26453a5a1b3Sopenharmony_ci pa_assert(conn); 26553a5a1b3Sopenharmony_ci pa_assert(msg); 26653a5a1b3Sopenharmony_ci pa_assert(s); 26753a5a1b3Sopenharmony_ci 26853a5a1b3Sopenharmony_ci if (!s->sample->memchunk.memblock) { 26953a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 27053a5a1b3Sopenharmony_ci "Sample %s isn't loaded into memory yet, so its size is unknown.", s->sample->name); 27153a5a1b3Sopenharmony_ci return; 27253a5a1b3Sopenharmony_ci } 27353a5a1b3Sopenharmony_ci 27453a5a1b3Sopenharmony_ci bytes = s->sample->memchunk.length; 27553a5a1b3Sopenharmony_ci 27653a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &bytes); 27753a5a1b3Sopenharmony_ci} 27853a5a1b3Sopenharmony_ci 27953a5a1b3Sopenharmony_cistatic void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { 28053a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 28153a5a1b3Sopenharmony_ci 28253a5a1b3Sopenharmony_ci pa_assert(conn); 28353a5a1b3Sopenharmony_ci pa_assert(msg); 28453a5a1b3Sopenharmony_ci pa_assert(s); 28553a5a1b3Sopenharmony_ci 28653a5a1b3Sopenharmony_ci pa_dbus_send_proplist_variant_reply(conn, msg, s->proplist); 28753a5a1b3Sopenharmony_ci} 28853a5a1b3Sopenharmony_ci 28953a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { 29053a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 29153a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 29253a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 29353a5a1b3Sopenharmony_ci DBusMessageIter dict_iter; 29453a5a1b3Sopenharmony_ci dbus_uint32_t idx = 0; 29553a5a1b3Sopenharmony_ci dbus_uint32_t sample_format = 0; 29653a5a1b3Sopenharmony_ci dbus_uint32_t sample_rate = 0; 29753a5a1b3Sopenharmony_ci dbus_uint32_t channels[PA_CHANNELS_MAX]; 29853a5a1b3Sopenharmony_ci dbus_uint32_t default_volume[PA_CHANNELS_MAX]; 29953a5a1b3Sopenharmony_ci dbus_uint64_t duration = 0; 30053a5a1b3Sopenharmony_ci dbus_uint32_t bytes = 0; 30153a5a1b3Sopenharmony_ci unsigned i = 0; 30253a5a1b3Sopenharmony_ci 30353a5a1b3Sopenharmony_ci pa_assert(conn); 30453a5a1b3Sopenharmony_ci pa_assert(msg); 30553a5a1b3Sopenharmony_ci pa_assert(s); 30653a5a1b3Sopenharmony_ci 30753a5a1b3Sopenharmony_ci idx = s->sample->index; 30853a5a1b3Sopenharmony_ci if (s->sample->memchunk.memblock) { 30953a5a1b3Sopenharmony_ci sample_format = s->sample->sample_spec.format; 31053a5a1b3Sopenharmony_ci sample_rate = s->sample->sample_spec.rate; 31153a5a1b3Sopenharmony_ci for (i = 0; i < s->sample->channel_map.channels; ++i) 31253a5a1b3Sopenharmony_ci channels[i] = s->sample->channel_map.map[i]; 31353a5a1b3Sopenharmony_ci duration = pa_bytes_to_usec(s->sample->memchunk.length, &s->sample->sample_spec); 31453a5a1b3Sopenharmony_ci bytes = s->sample->memchunk.length; 31553a5a1b3Sopenharmony_ci } 31653a5a1b3Sopenharmony_ci if (s->sample->volume_is_set) { 31753a5a1b3Sopenharmony_ci for (i = 0; i < s->sample->volume.channels; ++i) 31853a5a1b3Sopenharmony_ci default_volume[i] = s->sample->volume.values[i]; 31953a5a1b3Sopenharmony_ci } 32053a5a1b3Sopenharmony_ci 32153a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(msg))); 32253a5a1b3Sopenharmony_ci 32353a5a1b3Sopenharmony_ci dbus_message_iter_init_append(reply, &msg_iter); 32453a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); 32553a5a1b3Sopenharmony_ci 32653a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); 32753a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &s->sample->name); 32853a5a1b3Sopenharmony_ci 32953a5a1b3Sopenharmony_ci if (s->sample->memchunk.memblock) { 33053a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format); 33153a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &sample_rate); 33253a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, s->sample->channel_map.channels); 33353a5a1b3Sopenharmony_ci } 33453a5a1b3Sopenharmony_ci 33553a5a1b3Sopenharmony_ci if (s->sample->volume_is_set) 33653a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEFAULT_VOLUME].property_name, DBUS_TYPE_UINT32, default_volume, s->sample->volume.channels); 33753a5a1b3Sopenharmony_ci 33853a5a1b3Sopenharmony_ci if (s->sample->memchunk.memblock) { 33953a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DURATION].property_name, DBUS_TYPE_UINT64, &duration); 34053a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BYTES].property_name, DBUS_TYPE_UINT32, &bytes); 34153a5a1b3Sopenharmony_ci } 34253a5a1b3Sopenharmony_ci 34353a5a1b3Sopenharmony_ci pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, s->proplist); 34453a5a1b3Sopenharmony_ci 34553a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); 34653a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(conn, reply, NULL)); 34753a5a1b3Sopenharmony_ci dbus_message_unref(reply); 34853a5a1b3Sopenharmony_ci} 34953a5a1b3Sopenharmony_ci 35053a5a1b3Sopenharmony_cistatic void handle_play(DBusConnection *conn, DBusMessage *msg, void *userdata) { 35153a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 35253a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 35353a5a1b3Sopenharmony_ci dbus_uint32_t volume = 0; 35453a5a1b3Sopenharmony_ci pa_proplist *property_list = NULL; 35553a5a1b3Sopenharmony_ci 35653a5a1b3Sopenharmony_ci pa_assert(conn); 35753a5a1b3Sopenharmony_ci pa_assert(msg); 35853a5a1b3Sopenharmony_ci pa_assert(s); 35953a5a1b3Sopenharmony_ci 36053a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_init(msg, &msg_iter)); 36153a5a1b3Sopenharmony_ci dbus_message_iter_get_basic(&msg_iter, &volume); 36253a5a1b3Sopenharmony_ci 36353a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_next(&msg_iter)); 36453a5a1b3Sopenharmony_ci if (!(property_list = pa_dbus_get_proplist_arg(conn, msg, &msg_iter))) 36553a5a1b3Sopenharmony_ci return; 36653a5a1b3Sopenharmony_ci 36753a5a1b3Sopenharmony_ci if (!PA_VOLUME_IS_VALID(volume)) { 36853a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume."); 36953a5a1b3Sopenharmony_ci goto finish; 37053a5a1b3Sopenharmony_ci } 37153a5a1b3Sopenharmony_ci 37253a5a1b3Sopenharmony_ci if (!s->sample->core->default_sink) { 37353a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, 37453a5a1b3Sopenharmony_ci "Can't play sample %s, because there are no sinks available.", s->sample->name); 37553a5a1b3Sopenharmony_ci goto finish; 37653a5a1b3Sopenharmony_ci } 37753a5a1b3Sopenharmony_ci 37853a5a1b3Sopenharmony_ci if (pa_scache_play_item(s->sample->core, 37953a5a1b3Sopenharmony_ci s->sample->name, 38053a5a1b3Sopenharmony_ci s->sample->core->default_sink, 38153a5a1b3Sopenharmony_ci volume, 38253a5a1b3Sopenharmony_ci property_list, 38353a5a1b3Sopenharmony_ci NULL) < 0) { 38453a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Playing sample %s failed.", s->sample->name); 38553a5a1b3Sopenharmony_ci goto finish; 38653a5a1b3Sopenharmony_ci } 38753a5a1b3Sopenharmony_ci 38853a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 38953a5a1b3Sopenharmony_ci 39053a5a1b3Sopenharmony_cifinish: 39153a5a1b3Sopenharmony_ci if (property_list) 39253a5a1b3Sopenharmony_ci pa_proplist_free(property_list); 39353a5a1b3Sopenharmony_ci} 39453a5a1b3Sopenharmony_ci 39553a5a1b3Sopenharmony_cistatic void handle_play_to_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) { 39653a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 39753a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 39853a5a1b3Sopenharmony_ci const char *sink_path = NULL; 39953a5a1b3Sopenharmony_ci dbus_uint32_t volume = 0; 40053a5a1b3Sopenharmony_ci pa_proplist *property_list = NULL; 40153a5a1b3Sopenharmony_ci pa_sink *sink = NULL; 40253a5a1b3Sopenharmony_ci 40353a5a1b3Sopenharmony_ci pa_assert(conn); 40453a5a1b3Sopenharmony_ci pa_assert(msg); 40553a5a1b3Sopenharmony_ci pa_assert(s); 40653a5a1b3Sopenharmony_ci 40753a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_init(msg, &msg_iter)); 40853a5a1b3Sopenharmony_ci dbus_message_iter_get_basic(&msg_iter, &sink_path); 40953a5a1b3Sopenharmony_ci 41053a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_next(&msg_iter)); 41153a5a1b3Sopenharmony_ci dbus_message_iter_get_basic(&msg_iter, &volume); 41253a5a1b3Sopenharmony_ci 41353a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_next(&msg_iter)); 41453a5a1b3Sopenharmony_ci if (!(property_list = pa_dbus_get_proplist_arg(conn, msg, &msg_iter))) 41553a5a1b3Sopenharmony_ci return; 41653a5a1b3Sopenharmony_ci 41753a5a1b3Sopenharmony_ci if (!(sink = pa_dbusiface_core_get_sink(s->core, sink_path))) { 41853a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", sink_path); 41953a5a1b3Sopenharmony_ci goto finish; 42053a5a1b3Sopenharmony_ci } 42153a5a1b3Sopenharmony_ci 42253a5a1b3Sopenharmony_ci if (!PA_VOLUME_IS_VALID(volume)) { 42353a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume."); 42453a5a1b3Sopenharmony_ci goto finish; 42553a5a1b3Sopenharmony_ci } 42653a5a1b3Sopenharmony_ci 42753a5a1b3Sopenharmony_ci if (pa_scache_play_item(s->sample->core, s->sample->name, sink, volume, property_list, NULL) < 0) { 42853a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Playing sample %s failed.", s->sample->name); 42953a5a1b3Sopenharmony_ci goto finish; 43053a5a1b3Sopenharmony_ci } 43153a5a1b3Sopenharmony_ci 43253a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 43353a5a1b3Sopenharmony_ci 43453a5a1b3Sopenharmony_cifinish: 43553a5a1b3Sopenharmony_ci if (property_list) 43653a5a1b3Sopenharmony_ci pa_proplist_free(property_list); 43753a5a1b3Sopenharmony_ci} 43853a5a1b3Sopenharmony_ci 43953a5a1b3Sopenharmony_cistatic void handle_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) { 44053a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = userdata; 44153a5a1b3Sopenharmony_ci 44253a5a1b3Sopenharmony_ci pa_assert(conn); 44353a5a1b3Sopenharmony_ci pa_assert(msg); 44453a5a1b3Sopenharmony_ci pa_assert(s); 44553a5a1b3Sopenharmony_ci 44653a5a1b3Sopenharmony_ci if (pa_scache_remove_item(s->sample->core, s->sample->name) < 0) { 44753a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Removing sample %s failed.", s->sample->name); 44853a5a1b3Sopenharmony_ci return; 44953a5a1b3Sopenharmony_ci } 45053a5a1b3Sopenharmony_ci 45153a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 45253a5a1b3Sopenharmony_ci} 45353a5a1b3Sopenharmony_ci 45453a5a1b3Sopenharmony_cistatic pa_hook_result_t sample_cache_changed_cb(void *hook_data, void *call_data, void *slot_data) { 45553a5a1b3Sopenharmony_ci pa_dbusiface_sample *sample_iface = slot_data; 45653a5a1b3Sopenharmony_ci pa_scache_entry *sample = call_data; 45753a5a1b3Sopenharmony_ci DBusMessage *signal_msg; 45853a5a1b3Sopenharmony_ci 45953a5a1b3Sopenharmony_ci pa_assert(sample); 46053a5a1b3Sopenharmony_ci pa_assert(sample_iface); 46153a5a1b3Sopenharmony_ci 46253a5a1b3Sopenharmony_ci if (sample_iface->sample != sample) 46353a5a1b3Sopenharmony_ci return PA_HOOK_OK; 46453a5a1b3Sopenharmony_ci 46553a5a1b3Sopenharmony_ci if (!pa_proplist_equal(sample_iface->proplist, sample_iface->sample->proplist)) { 46653a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 46753a5a1b3Sopenharmony_ci 46853a5a1b3Sopenharmony_ci pa_proplist_update(sample_iface->proplist, PA_UPDATE_SET, sample_iface->sample->proplist); 46953a5a1b3Sopenharmony_ci 47053a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(sample_iface->path, 47153a5a1b3Sopenharmony_ci PA_DBUSIFACE_SAMPLE_INTERFACE, 47253a5a1b3Sopenharmony_ci signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); 47353a5a1b3Sopenharmony_ci dbus_message_iter_init_append(signal_msg, &msg_iter); 47453a5a1b3Sopenharmony_ci pa_dbus_append_proplist(&msg_iter, sample_iface->proplist); 47553a5a1b3Sopenharmony_ci 47653a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(sample_iface->dbus_protocol, signal_msg); 47753a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 47853a5a1b3Sopenharmony_ci } 47953a5a1b3Sopenharmony_ci 48053a5a1b3Sopenharmony_ci return PA_HOOK_OK; 48153a5a1b3Sopenharmony_ci} 48253a5a1b3Sopenharmony_ci 48353a5a1b3Sopenharmony_cipa_dbusiface_sample *pa_dbusiface_sample_new(pa_dbusiface_core *core, pa_scache_entry *sample) { 48453a5a1b3Sopenharmony_ci pa_dbusiface_sample *s = NULL; 48553a5a1b3Sopenharmony_ci 48653a5a1b3Sopenharmony_ci pa_assert(core); 48753a5a1b3Sopenharmony_ci pa_assert(sample); 48853a5a1b3Sopenharmony_ci 48953a5a1b3Sopenharmony_ci s = pa_xnew0(pa_dbusiface_sample, 1); 49053a5a1b3Sopenharmony_ci s->core = core; 49153a5a1b3Sopenharmony_ci s->sample = sample; 49253a5a1b3Sopenharmony_ci s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, OBJECT_NAME, sample->index); 49353a5a1b3Sopenharmony_ci s->proplist = pa_proplist_copy(sample->proplist); 49453a5a1b3Sopenharmony_ci s->dbus_protocol = pa_dbus_protocol_get(sample->core); 49553a5a1b3Sopenharmony_ci s->sample_cache_changed_slot = pa_hook_connect(&sample->core->hooks[PA_CORE_HOOK_SAMPLE_CACHE_CHANGED], 49653a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, sample_cache_changed_cb, s); 49753a5a1b3Sopenharmony_ci 49853a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &sample_interface_info, s) >= 0); 49953a5a1b3Sopenharmony_ci 50053a5a1b3Sopenharmony_ci return s; 50153a5a1b3Sopenharmony_ci} 50253a5a1b3Sopenharmony_ci 50353a5a1b3Sopenharmony_civoid pa_dbusiface_sample_free(pa_dbusiface_sample *s) { 50453a5a1b3Sopenharmony_ci pa_assert(s); 50553a5a1b3Sopenharmony_ci 50653a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_remove_interface(s->dbus_protocol, s->path, sample_interface_info.name) >= 0); 50753a5a1b3Sopenharmony_ci 50853a5a1b3Sopenharmony_ci pa_hook_slot_free(s->sample_cache_changed_slot); 50953a5a1b3Sopenharmony_ci pa_proplist_free(s->proplist); 51053a5a1b3Sopenharmony_ci pa_dbus_protocol_unref(s->dbus_protocol); 51153a5a1b3Sopenharmony_ci 51253a5a1b3Sopenharmony_ci pa_xfree(s->path); 51353a5a1b3Sopenharmony_ci pa_xfree(s); 51453a5a1b3Sopenharmony_ci} 51553a5a1b3Sopenharmony_ci 51653a5a1b3Sopenharmony_ciconst char *pa_dbusiface_sample_get_path(pa_dbusiface_sample *s) { 51753a5a1b3Sopenharmony_ci pa_assert(s); 51853a5a1b3Sopenharmony_ci 51953a5a1b3Sopenharmony_ci return s->path; 52053a5a1b3Sopenharmony_ci} 521