#define ARR_ARG_MAX 32
#define STREAM_MANAGER_OBJECT_PATH "/org/pulseaudio/StreamManager"
#define STREAM_MANAGER_INTERFACE "org.pulseaudio.StreamManager"
+/* method */
#define STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO "GetStreamInfo"
#define STREAM_MANAGER_METHOD_NAME_GET_STREAM_LIST "GetStreamList"
#define STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES "SetStreamRouteDevices"
#define STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MUTE "GetVolumeMute"
#define STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE "GetCurrentVolumeType" /* the type that belongs to the stream of the current max priority */
#define STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS "UpdateFocusStatus"
+/* signal */
+#define STREAM_MANAGER_SIGNAL_NAME_VOLUME_CHANGED "VolumeChanged"
+#define STREAM_MANAGER_SIGNAL_NAME_COMMAND "Command"
static DBusHandlerResult method_handler_for_vt(DBusConnection *c, DBusMessage *m, void *userdata);
static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata);
static void handle_get_volume_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
static void handle_get_current_volume_type(DBusConnection *conn, DBusMessage *msg, void *userdata);
static void handle_update_focus_status(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void send_volume_changed_signal(DBusConnection *conn, const char *direction, const char *volume_type, const uint32_t volume_level);
+static void send_command_signal(DBusConnection *conn, const char *name, int value);
enum method_handler_index {
METHOD_HANDLER_GET_STREAM_INFO,
" <arg name=\"focus_status\" direction=\"in\" type=\"u\"/>" \
" <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
" </method>" \
+ " <signal name=\"STREAM_MANAGER_SIGNAL_NAME_VOLUME_CHANGED\">" \
+ " <arg name=\"direction\" type=\"s\"/>" \
+ " <arg name=\"volume_type\" type=\"s\"/>" \
+ " <arg name=\"volume_level\" type=\"u\"/>" \
+ " </signal>" \
+ " <signal name=\"STREAM_MANAGER_SIGNAL_NAME_COMMAND\">" \
+ " <arg name=\"name\" type=\"s\"/>" \
+ " <arg name=\"value\" type=\"i\"/>" \
+ " </signal>" \
" </interface>" \
" <interface name=\"org.freedesktop.DBus.Introspectable\">" \
" <method name=\"Introspect\">" \
return;
}
-static void send_volume_changed_signal(DBusConnection *conn, const char *direction, const char *volume_type, const uint32_t volume_level) {
- DBusMessage *signal_msg;
- DBusMessageIter msg_iter;
-
- pa_assert(conn);
- pa_assert(volume_type);
-
- pa_log_debug("Send volume changed signal : direction %s, type %s, level %d", direction, volume_type, volume_level);
-
- pa_assert_se(signal_msg = dbus_message_new_signal(STREAM_MANAGER_OBJECT_PATH, STREAM_MANAGER_INTERFACE, "VolumeChanged"));
- dbus_message_iter_init_append(signal_msg, &msg_iter);
-
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &direction);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &volume_type);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_UINT32, &volume_level);
-
- pa_assert_se(dbus_connection_send(conn, signal_msg, NULL));
- dbus_message_unref(signal_msg);
- return;
-}
-
static void handle_set_volume_level(DBusConnection *conn, DBusMessage *msg, void *userdata) {
const char *direction = NULL;
const char *type = NULL;
stream_type = STREAM_SINK_INPUT;
else {
pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_INDEX_ERROR], DBUS_TYPE_INVALID));
+ ret = -1;
goto FAILURE;
}
if (!ret)
send_volume_changed_signal(conn, direction, type, level);
+
return;
}
return DBUS_HANDLER_RESULT_HANDLED;
}
+
+static void send_volume_changed_signal(DBusConnection *conn, const char *direction, const char *volume_type, const uint32_t volume_level) {
+ DBusMessage *signal_msg;
+ DBusMessageIter msg_iter;
+
+ pa_assert(conn);
+ pa_assert(direction);
+ pa_assert(volume_type);
+
+ pa_log_debug("Send volume changed signal: direction(%s), type(%s), level(%d)", direction, volume_type, volume_level);
+
+ pa_assert_se(signal_msg = dbus_message_new_signal(STREAM_MANAGER_OBJECT_PATH, STREAM_MANAGER_INTERFACE, STREAM_MANAGER_SIGNAL_NAME_VOLUME_CHANGED));
+ dbus_message_iter_init_append(signal_msg, &msg_iter);
+
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &direction);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &volume_type);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_UINT32, &volume_level);
+
+ pa_assert_se(dbus_connection_send(conn, signal_msg, NULL));
+ dbus_message_unref(signal_msg);
+ return;
+}
+
+static void send_command_signal(DBusConnection *conn, const char *name, int value) {
+ DBusMessage *signal_msg;
+ DBusMessageIter msg_iter;
+
+ pa_assert(conn);
+ pa_assert(name);
+
+ pa_log_debug("Send command signal: name(%s), value(%d)", name, value);
+
+ pa_assert_se(signal_msg = dbus_message_new_signal(STREAM_MANAGER_OBJECT_PATH, STREAM_MANAGER_INTERFACE, STREAM_MANAGER_SIGNAL_NAME_COMMAND));
+ dbus_message_iter_init_append(signal_msg, &msg_iter);
+
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &value);
+
+ pa_assert_se(dbus_connection_send(conn, signal_msg, NULL));
+ dbus_message_unref(signal_msg);
+}
#endif
static int convert_route_type(stream_route_type_t *route_type, const char *route_type_string) {
const char *name = NULL;
uint32_t *device_id = NULL;
uint32_t _idx = 0;
+
pa_core_assert_ref(core);
pa_assert(m);
}
}
-static int init_ipc(pa_stream_manager *m) {
+static void message_cb(const char *name, int value, void *user_data) {
+ pa_stream_manager *m;
+
+ pa_assert(user_data);
+
+ m = (pa_stream_manager*)user_data;
+
#ifdef HAVE_DBUS
-#ifdef USE_DBUS_PROTOCOL
+ send_command_signal(pa_dbus_connection_get(m->dbus_conn), name, value);
+#endif
+
+ return;
+}
+
+static int init_ipc(pa_stream_manager *m) {
pa_assert(m);
pa_log_info("Initialization for IPC");
+#ifdef HAVE_DBUS
+#ifdef USE_DBUS_PROTOCOL
m->dbus_protocol = pa_dbus_protocol_get(m->core);
pa_assert_se(pa_dbus_protocol_add_interface(m->dbus_protocol, STREAM_MANAGER_OBJECT_PATH, &stream_manager_interface_info, m) >= 0);
pa_assert_se(pa_dbus_protocol_register_extension(m->dbus_protocol, STREAM_MANAGER_INTERFACE) >= 0);
.message_function = method_handler_for_vt,
};
- pa_assert(m);
- pa_log_info("Initialization for IPC");
-
dbus_error_init(&err);
if (!(conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err)) || dbus_error_is_set(&err)) {
m->core = c;
m->hal = pa_hal_manager_get(c);
+ if (pa_hal_manager_set_messsage_callback(m->hal, message_cb, m))
+ pa_log_warn("skip setting message callback");
m->dm = pa_device_manager_get(c);
#ifdef HAVE_DBUS
AUDIO_ERR_RESOURCE = (int32_t)0x80001001,
AUDIO_ERR_PARAMETER = (int32_t)0x80001002,
AUDIO_ERR_IOCTL = (int32_t)0x80001003,
- AUDIO_ERR_NOT_IMPLEMENTED = (int32_t)0x80001004,
+ AUDIO_ERR_INVALID_STATE = (int32_t)0x80001004,
+ AUDIO_ERR_INTERNAL = (int32_t)0x80001005,
+
+ AUDIO_ERR_NOT_IMPLEMENTED = (int32_t)0x80001100,
} audio_return_t ;
typedef enum audio_direction {
uint32_t idx;
} audio_stream_info_t ;
+typedef void (*message_cb)(const char *name, int value, void *user_data);
+
/* Overall */
typedef struct audio_interface {
audio_return_t (*init)(void **audio_handle);
audio_return_t (*deinit)(void *audio_handle);
+ /* Volume */
audio_return_t (*get_volume_level_max)(void *audio_handle, audio_volume_info_t *info, uint32_t *level);
audio_return_t (*get_volume_level)(void *audio_handle, audio_volume_info_t *info, uint32_t *level);
audio_return_t (*set_volume_level)(void *audio_handle, audio_volume_info_t *info, uint32_t level);
audio_return_t (*get_volume_value)(void *audio_handle, audio_volume_info_t *info, uint32_t level, double *value);
audio_return_t (*get_volume_mute)(void *audio_handle, audio_volume_info_t *info, uint32_t *mute);
audio_return_t (*set_volume_mute)(void *audio_handle, audio_volume_info_t *info, uint32_t mute);
+ /* Routing */
audio_return_t (*do_route)(void *audio_handle, audio_route_info_t *info);
audio_return_t (*update_route_option)(void *audio_handle, audio_route_option_t *option);
audio_return_t (*update_stream_connection_info) (void *audio_handle, audio_stream_info_t *info, uint32_t is_connected);
+ /* Buffer Attribute */
audio_return_t (*get_buffer_attr)(void *audio_handle, uint32_t direction, const char *latency, uint32_t samplerate, int format, uint32_t channels,
uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
/* Interface of PCM device */
audio_return_t (*pcm_recover)(void *audio_handle, void *pcm_handle, int revents);
audio_return_t (*pcm_get_params)(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods);
audio_return_t (*pcm_set_params)(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
+ /* Message callback */
+ audio_return_t (*set_message_cb)(void *audio_handle, message_cb callback, void *user_data);
} audio_interface_t;
audio_return_t audio_init(void **audio_handle);
audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents);
audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods);
audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
+audio_return_t audio_set_message_cb(void *audio_handle, message_cb callback, void *user_data);
#endif