7b8e0487e51a607f341396d1e9368917091270e0
[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         gint handle = -1;
81         gboolean stopped_by_user = FALSE;
82         struct dbus_cb_data *dbus_data = (struct dbus_cb_data *)userdata;
83
84         if (!dbus_data) {
85                 LOGE("dbus data is null");
86                 return;
87         }
88
89         g_variant_get(params, "(ib)", &handle, &stopped_by_user);
90         LOGI("expected handle(%d) callback(%p), incoming handle(%d), stopped_by_user(%d)",
91                 dbus_data->handle, dbus_data->cb, handle, stopped_by_user);
92
93         if (handle != dbus_data->handle)
94                 return;
95
96         g_dbus_connection_signal_unsubscribe(dbus_data->conn, dbus_data->subs_id);
97         g_object_unref(dbus_data->conn);
98
99         if (!stopped_by_user) {
100                 LOGI("Invoking user callback for handle(%d) cb(%p)", handle, dbus_data->cb);
101                 dbus_data->cb(handle, dbus_data->user_data);
102         }
103
104         g_free(dbus_data);
105 }
106
107 int _wav_play_sound(const char *path, sound_stream_info_h stream_info, unsigned loop_count,
108                         wav_player_playback_completed_cb callback, void *user_data, bool stop_others, int *id)
109 {
110         int ret = WAV_PLAYER_ERROR_NONE;
111         char m_path[PATH_MAX];
112         char *stream_type = NULL;
113         int stream_id;
114         bool result = false;
115
116         int handle;
117         GError *err = NULL;
118         GVariant *reply = NULL;
119         GDBusConnection *conn = NULL;
120         struct dbus_cb_data *dbus_cb_data = NULL;
121
122         if (path == NULL || stream_info == NULL) {
123                 LOGE("invalid params");
124                 return WAV_PLAYER_ERROR_INVALID_PARAMETER;
125         }
126
127         LOGI("path(%s), loop(%u), cb(%p) user_data(%p)", path, loop_count, callback, user_data);
128
129         m_path[0] = '\0';
130         if (path[0] != '/' && getcwd(m_path, PATH_MAX) != NULL)
131                 strncat(m_path, "/", PATH_MAX - strlen(m_path) - 1);
132
133         strncat(m_path, path, PATH_MAX - strlen(m_path) - 1);
134         if (access(m_path, R_OK) != 0) {
135                 char str_error[256];
136                 strerror_r(errno, str_error, sizeof(str_error));
137                 LOGE("file [%s] doesn't exists : [%s][%d]", m_path, str_error, errno);
138                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
139         }
140
141         ret = sound_manager_is_available_stream_information(stream_info, NATIVE_API_WAV_PLAYER, &result);
142         if (!result || ret) {
143                 LOGE("stream info is not available. ret(0x%x), result(%d)", ret, result);
144                 return WAV_PLAYER_ERROR_NOT_SUPPORTED_TYPE;
145         }
146
147         ret = sound_manager_get_type_from_stream_information(stream_info, &stream_type);
148         if (ret) {
149                 LOGE("can't get stream type. ret(0x%x)", ret);
150                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
151         }
152
153         ret = sound_manager_get_index_from_stream_information(stream_info, &stream_id);
154         if (ret) {
155                 LOGE("can't get stream index. ret(0x%x)", ret);
156                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
157         }
158
159         if (!(conn = __get_dbus_connection()))
160                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
161
162         reply = g_dbus_connection_call_sync(conn, PA_BUS_NAME,
163                         PA_SOUND_PLAYER_OBJECT_PATH,
164                         PA_SOUND_PLAYER_INTERFACE,
165                         PA_SOUND_PLAYER_METHOD_NAME_SOUND_PLAY,
166                         g_variant_new("(siisib)", m_path, loop_count == 0 ? -1 : loop_count,
167                                         getpid(), stream_type, stream_id, (gboolean)stop_others),
168                         NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
169         if (!reply) {
170                 LOGE("g_dbus_connection_call_sync error (%s)", err->message);
171                 ret = __convert_dbus_error(err->message);
172                 g_error_free(err);
173                 g_object_unref(conn);
174                 return ret;
175         }
176
177         g_variant_get(reply, "(i)", &handle);
178         g_variant_unref(reply);
179         if (id)
180                 *id = handle;
181
182         LOGI("handle : %d", handle);
183
184         if (callback) {
185                 dbus_cb_data = g_new0(struct dbus_cb_data, 1);
186                 dbus_cb_data->conn = conn;
187                 dbus_cb_data->handle = handle;
188                 dbus_cb_data->cb = callback;
189                 dbus_cb_data->user_data = user_data;
190                 dbus_cb_data->subs_id = g_dbus_connection_signal_subscribe(conn, NULL,
191                                  PA_SOUND_PLAYER_INTERFACE,
192                                  PA_SOUND_PLAYER_SIGNAL_EOS,
193                                  PA_SOUND_PLAYER_OBJECT_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
194                                  __internal_complete_cb, dbus_cb_data, NULL);
195                 if (!dbus_cb_data->subs_id) {
196                         g_object_unref(conn);
197                         g_free(dbus_cb_data);
198                         LOGE("g_dbus_connection_signal_subscribe() failed");
199                         return WAV_PLAYER_ERROR_INVALID_OPERATION;
200                 }
201         } else {
202                 g_object_unref(conn);
203         }
204
205         return WAV_PLAYER_ERROR_NONE;
206 }
207
208 //LCOV_EXCL_START
209 int _wav_play_sound_simple(const char *path, const char *stream_role)
210 {
211         int ret = WAV_PLAYER_ERROR_NONE;
212         char m_path[PATH_MAX];
213         int handle;
214         GError *err = NULL;
215         GVariant *reply = NULL;
216         GDBusConnection *conn = NULL;
217
218         if (!path || !stream_role) {
219                 LOGE("invalid params path(%p), stream_role(%p)", path, stream_role);
220                 return WAV_PLAYER_ERROR_INVALID_PARAMETER;
221         }
222
223         LOGI("path(%s), stream_role(%s)", path, stream_role);
224
225         /* FIXME : need extraction of duplicated path validation code */
226         m_path[0] = '\0';
227         if (path[0] != '/' && getcwd(m_path, PATH_MAX) != NULL)
228                 strncat(m_path, "/", PATH_MAX - strlen(m_path) - 1);
229
230         strncat(m_path, path, PATH_MAX - strlen(m_path) - 1);
231         if (access(m_path, R_OK) != 0) {
232                 char str_error[256];
233                 strerror_r(errno, str_error, sizeof(str_error));
234                 LOGE("file [%s] doesn't exists : [%s][%d]", m_path, str_error, errno);
235                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
236         }
237
238         if (!(conn = __get_dbus_connection()))
239                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
240
241         reply = g_dbus_connection_call_sync(conn, PA_BUS_NAME,
242                                                                                 PA_SOUND_PLAYER_OBJECT_PATH,
243                                                                                 PA_SOUND_PLAYER_INTERFACE,
244                                                                                 PA_SOUND_PLAYER_METHOD_NAME_SOUND_PLAY,
245                                                                                 g_variant_new("(siisib)", m_path, 1,
246                                                                                                           getpid(), stream_role, -1, FALSE),
247                                                                                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
248         if (!reply) {
249                 if (err) {
250                         LOGE("g_dbus_connection_call_sync error (%s)", err->message);
251                         ret = __convert_dbus_error(err->message);
252                         g_error_free(err);
253                 } else {
254                         ret = WAV_PLAYER_ERROR_INVALID_OPERATION;
255                 }
256                 goto finish;
257         }
258
259         g_variant_get(reply, "(i)", &handle);
260         g_variant_unref(reply);
261
262         LOGI("handle : %d", handle);
263
264 finish:
265         g_object_unref(conn);
266
267         return ret;
268 }
269 //LCOV_EXCL_STOP
270
271 int _wav_stop_sound(int id)
272 {
273         GDBusConnection *conn = NULL;
274         GError *err = NULL;
275         GVariant *reply = NULL;
276
277         LOGI("handle(%d)", id);
278
279         if (!(conn = __get_dbus_connection()))
280                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
281
282         reply = g_dbus_connection_call_sync(conn,
283                                 PA_BUS_NAME,
284                                 PA_SOUND_PLAYER_OBJECT_PATH,
285                                 PA_SOUND_PLAYER_INTERFACE,
286                                 PA_SOUND_PLAYER_METHOD_NAME_SOUND_STOP,
287                                 g_variant_new("(i)", id),
288                                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
289
290         g_object_unref(conn);
291
292         if (!reply) {
293                 int ret;
294
295                 LOGE("g_dbus_connection_call_sync error (%s)", err->message);
296                 ret = __convert_dbus_error(err->message);
297                 g_error_free(err);
298                 return ret;
299         }
300
301         g_variant_unref(reply);
302
303         LOGI("stop sound. handle(%d)", id);
304
305         return WAV_PLAYER_ERROR_NONE;
306 }