stream-manager/hal-manager: Support forwarding message from audio-hal 69/56469/6 accepted/tizen/mobile/20160111.230306 accepted/tizen/tv/20160111.230343 accepted/tizen/wearable/20160111.230400 submit/tizen/20160111.114534
authorSangchul Lee <sc11.lee@samsung.com>
Thu, 7 Jan 2016 04:43:01 +0000 (13:43 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Mon, 11 Jan 2016 10:32:51 +0000 (19:32 +0900)
Some audio-hal has to communicate with other frameworks/daemons.
If stream-manager gets the notification from hal-manager, it would send dbus signal.
Modify AUDIO_ERR_NOT_IMPLEMENTED value to 0x80001100.

[Version] 5.0.28
[Profile] Common
[Issue Type] Feature Enhancement

Change-Id: Icad17ed97fb3c31510be5257b4179fcaea162ae6

packaging/pulseaudio-modules-tizen.spec
src/hal-manager.c
src/hal-manager.h
src/stream-manager.c
src/tizen-audio.h

index 7828e1a..aa047ce 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          5.0.27
+Version:          5.0.28
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 64888d8..903d3c9 100644 (file)
@@ -79,6 +79,7 @@ pa_hal_manager* pa_hal_manager_get(pa_core *core) {
         h->intf.pcm_recover = dlsym(h->dl_handle, "audio_pcm_recover");
         h->intf.pcm_get_params = dlsym(h->dl_handle, "audio_pcm_get_params");
         h->intf.pcm_set_params = dlsym(h->dl_handle, "audio_pcm_set_params");
+        h->intf.set_message_cb = dlsym(h->dl_handle, "audio_set_message_cb");
         if (h->intf.init) {
             if (h->intf.init(&h->ah_handle) != AUDIO_RET_OK)
                 pa_log_error("hal_manager init failed");
@@ -469,3 +470,21 @@ int32_t pa_hal_manager_pcm_set_params(pa_hal_manager *h, pcm_handle pcm_h, uint3
     }
     return ret;
 }
+
+int32_t pa_hal_manager_set_messsage_callback(pa_hal_manager *h, hal_message_callback callback, void *user_data) {
+    int32_t ret = 0;
+    audio_return_t hal_ret = AUDIO_RET_OK;
+
+    pa_assert(h);
+    pa_assert(callback);
+
+    if (h->intf.set_message_cb == NULL) {
+        pa_log_error("there is no set_message_cb symbol in this audio hal");
+        ret = -1;
+    } else if (AUDIO_IS_ERROR((hal_ret = h->intf.set_message_cb(h->ah_handle, (message_cb)callback, user_data)))) {
+        pa_log_error("set_message_cb returns error:0x%x", hal_ret);
+        ret = -1;
+    }
+
+    return ret;
+}
index 5d445cc..583e6ca 100644 (file)
@@ -43,6 +43,8 @@ typedef struct _hal_stream_info {
 
 typedef void* pcm_handle;
 
+typedef void (*hal_message_callback)(const char *name, int value, void *user_data);
+
 pa_hal_manager* pa_hal_manager_get(pa_core *core);
 pa_hal_manager* pa_hal_manager_ref(pa_hal_manager *h);
 void pa_hal_manager_unref(pa_hal_manager *h);
@@ -67,5 +69,6 @@ int32_t pa_hal_manager_pcm_get_fd(pa_hal_manager *h, pcm_handle pcm_h, int *fd);
 int32_t pa_hal_manager_pcm_recover(pa_hal_manager *h, pcm_handle pcm_h, int err);
 int32_t pa_hal_manager_pcm_get_params(pa_hal_manager *h, pcm_handle pcm_h, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods);
 int32_t pa_hal_manager_pcm_set_params(pa_hal_manager *h, pcm_handle pcm_h, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
+int32_t pa_hal_manager_set_messsage_callback(pa_hal_manager *h, hal_message_callback callback, void *user_data);
 
 #endif
index fd8eb83..6f54f7c 100644 (file)
@@ -49,6 +49,7 @@
 #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"
@@ -60,6 +61,9 @@
 #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);
@@ -75,6 +79,8 @@ static void handle_set_volume_mute(DBusConnection *conn, DBusMessage *msg, void
 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,
@@ -286,6 +292,15 @@ static pa_dbus_interface_info stream_manager_interface_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\">"                                         \
@@ -797,27 +812,6 @@ static void handle_set_stream_route_option(DBusConnection *conn, DBusMessage *ms
     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;
@@ -846,6 +840,7 @@ static void handle_set_volume_level(DBusConnection *conn, DBusMessage *msg, void
         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;
     }
 
@@ -860,6 +855,7 @@ FAILURE:
 
     if (!ret)
         send_volume_changed_signal(conn, direction, type, level);
+
     return;
 }
 
@@ -1190,6 +1186,47 @@ static DBusHandlerResult method_handler_for_vt(DBusConnection *c, DBusMessage *m
 
     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) {
@@ -3128,6 +3165,7 @@ static void subscribe_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t
     const char *name = NULL;
     uint32_t *device_id = NULL;
     uint32_t _idx = 0;
+
     pa_core_assert_ref(core);
     pa_assert(m);
 
@@ -3176,11 +3214,25 @@ static void subscribe_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t
     }
 }
 
-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);
@@ -3191,9 +3243,6 @@ static int init_ipc(pa_stream_manager *m) {
         .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)) {
@@ -3276,6 +3325,8 @@ pa_stream_manager* pa_stream_manager_init(pa_core *c) {
     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
index ce95101..2c513c3 100644 (file)
@@ -30,7 +30,10 @@ typedef enum audio_return {
     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 {
@@ -68,19 +71,24 @@ typedef struct audio_stream_info {
     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 */
@@ -95,6 +103,8 @@ typedef struct audio_interface {
     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);
@@ -121,4 +131,5 @@ audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd);
 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