Send dbus IPC directly to SoundPlayer
[platform/core/api/wav-player.git] / src / wav_player_private.c
1 /*
2 * Copyright (c) 2011-2016 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "TIZEN_N_WAV_PLAYER"
18
19 #include <stdio.h>
20 #include <limits.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <dlog.h>
25 #include <stdlib.h>
26 #include <gio/gio.h>
27 #include <glib.h>
28 #include "wav_player_private.h"
29
30 #define PA_BUS_NAME "org.pulseaudio.Server"
31 #define PA_SOUND_PLAYER_OBJECT_PATH "/org/pulseaudio/SoundPlayer"
32 #define PA_SOUND_PLAYER_INTERFACE "org.pulseaudio.SoundPlayer"
33
34 #define PA_SOUND_PLAYER_METHOD_NAME_SOUND_PLAY          "SoundPlay"
35 #define PA_SOUND_PLAYER_METHOD_NAME_SOUND_STOP          "SoundStop"
36 #define PA_SOUND_PLAYER_SIGNAL_EOS                      "EOS"
37
38 struct dbus_cb_data {
39         GDBusConnection *conn;
40         int handle;
41         guint subs_id;
42         wav_player_playback_completed_cb cb;
43         void *user_data;
44 };
45
46 static int __convert_dbus_error(const char *error_msg)
47 {
48         if (error_msg) {
49                 if (strstr(error_msg, "UnsupportedMediaType"))
50                         return WAV_PLAYER_ERROR_FORMAT_NOT_SUPPORTED;
51                 else if (strstr(error_msg, "InvalidArgument"))
52                         return WAV_PLAYER_ERROR_INVALID_PARAMETER;
53         }
54
55         return WAV_PLAYER_ERROR_INVALID_OPERATION;
56 }
57
58 static GDBusConnection *__get_dbus_connection(void)
59 {
60         GDBusConnection *conn = NULL;
61         GError *err = NULL;
62
63         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
64         if (!conn) {
65                 LOGE("g_bus_get_sync() error (%s)", err->message);
66                 g_error_free(err);
67         }
68
69         return conn;
70 }
71
72 static void __internal_complete_cb(GDBusConnection *connection,
73                                         const gchar *sender_name,
74                                         const gchar *object_path,
75                                         const gchar *interface_name,
76                                         const gchar *signal_name,
77                                         GVariant *params,
78                                         gpointer userdata)
79 {
80         int handle;
81         struct dbus_cb_data *dbus_data = (struct dbus_cb_data *)userdata;
82
83         g_variant_get(params, "(i)", &handle);
84
85         if (!dbus_data) {
86                 LOGE("dbus data is null. handle(%d)", handle);
87                 return;
88         }
89
90         if (handle == dbus_data->handle) {
91                 g_dbus_connection_signal_unsubscribe(dbus_data->conn, dbus_data->subs_id);
92                 g_object_unref(dbus_data->conn);
93
94                 LOGD("user callback for handle(%d) cb(%p)", handle, dbus_data->cb);
95                 dbus_data->cb(handle, dbus_data->user_data);
96                 g_free(dbus_data);
97         }
98 }
99
100 int _wav_play_sound(const char *path, sound_stream_info_h stream_info, unsigned loop_count,
101                         wav_player_playback_completed_cb callback, void *user_data, int *id)
102 {
103         int ret = WAV_PLAYER_ERROR_NONE;
104         char m_path[PATH_MAX];
105         char *stream_type = NULL;
106         int stream_id;
107         bool result = false;
108
109         int handle;
110         GError *err = NULL;
111         GVariant *reply = NULL;
112         GDBusConnection *conn = NULL;
113         struct dbus_cb_data *dbus_cb_data = NULL;
114
115         if (path == NULL || stream_info == NULL) {
116                 LOGE("invalid params");
117                 return WAV_PLAYER_ERROR_INVALID_PARAMETER;
118         }
119
120         LOGI("path(%s), loop(%u), cb(%p) user_data(%p)", path, loop_count, callback, user_data);
121
122         m_path[0] = '\0';
123         if (path[0] != '/' && getcwd(m_path, PATH_MAX) != NULL)
124                 strncat(m_path, "/", PATH_MAX - strlen(m_path) - 1);
125
126         strncat(m_path, path, PATH_MAX - strlen(m_path) - 1);
127         if (access(m_path, R_OK) != 0) {
128                 char str_error[256];
129                 strerror_r(errno, str_error, sizeof(str_error));
130                 LOGE("file [%s] doesn't exists : [%s][%d]", m_path, str_error, errno);
131                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
132         }
133
134         ret = sound_manager_is_available_stream_information(stream_info, NATIVE_API_WAV_PLAYER, &result);
135         if (!result || ret) {
136                 LOGE("stream info is not available. ret(0x%x), result(%d)", ret, result);
137                 return WAV_PLAYER_ERROR_NOT_SUPPORTED_TYPE;
138         }
139
140         ret = sound_manager_get_type_from_stream_information(stream_info, &stream_type);
141         if (ret) {
142                 LOGE("can't get stream type. ret(0x%x)", ret);
143                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
144         }
145
146         ret = sound_manager_get_index_from_stream_information(stream_info, &stream_id);
147         if (ret) {
148                 LOGE("can't get stream index. ret(0x%x)", ret);
149                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
150         }
151
152         if (!(conn = __get_dbus_connection()))
153                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
154
155         reply = g_dbus_connection_call_sync(conn, PA_BUS_NAME,
156                         PA_SOUND_PLAYER_OBJECT_PATH,
157                         PA_SOUND_PLAYER_INTERFACE,
158                         PA_SOUND_PLAYER_METHOD_NAME_SOUND_PLAY,
159                         g_variant_new("(siisi)", m_path, loop_count == 0 ? -1 : loop_count,
160                                         getpid(), stream_type, stream_id),
161                         NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
162         if (!reply) {
163                 LOGE("g_dbus_connection_call_sync error (%s)", err->message);
164                 ret = __convert_dbus_error(err->message);
165                 g_error_free(err);
166                 g_object_unref(conn);
167                 return ret;
168         }
169
170         g_variant_get(reply, "(i)", &handle);
171         g_variant_unref(reply);
172         if (id)
173                 *id = handle;
174
175         LOGI("handle : %d", handle);
176
177         if (callback) {
178                 dbus_cb_data = g_new0(struct dbus_cb_data, 1);
179                 dbus_cb_data->conn = conn;
180                 dbus_cb_data->handle = handle;
181                 dbus_cb_data->cb = callback;
182                 dbus_cb_data->user_data = user_data;
183                 dbus_cb_data->subs_id = g_dbus_connection_signal_subscribe(conn, NULL,
184                                  PA_SOUND_PLAYER_INTERFACE,
185                                  PA_SOUND_PLAYER_SIGNAL_EOS,
186                                  PA_SOUND_PLAYER_OBJECT_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
187                                  __internal_complete_cb, dbus_cb_data, NULL);
188                 if (!dbus_cb_data->subs_id) {
189                         g_object_unref(conn);
190                         g_free(dbus_cb_data);
191                         LOGE("g_dbus_connection_signal_subscribe() failed");
192                         return WAV_PLAYER_ERROR_INVALID_OPERATION;
193                 }
194         } else {
195                 g_object_unref(conn);
196         }
197
198         return WAV_PLAYER_ERROR_NONE;
199 }
200
201 int _wav_stop_sound(int id)
202 {
203         GDBusConnection *conn = NULL;
204         GError *err = NULL;
205         GVariant *reply = NULL;
206
207         LOGI("handle(%d)", id);
208
209         if (!(conn = __get_dbus_connection()))
210                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
211
212         reply = g_dbus_connection_call_sync(conn,
213                                 PA_BUS_NAME,
214                                 PA_SOUND_PLAYER_OBJECT_PATH,
215                                 PA_SOUND_PLAYER_INTERFACE,
216                                 PA_SOUND_PLAYER_METHOD_NAME_SOUND_STOP,
217                                 g_variant_new("(i)", id),
218                                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
219
220         g_object_unref(conn);
221
222         if (!reply) {
223                 int ret;
224
225                 LOGE("g_dbus_connection_call_sync error (%s)", err->message);
226                 ret = __convert_dbus_error(err->message);
227                 g_error_free(err);
228                 return ret;
229         }
230
231         g_variant_unref(reply);
232
233         LOGI("stop sound. handle(%d)", id);
234
235         return WAV_PLAYER_ERROR_NONE;
236 }