Add wav_player_play_simple internal function to support boot-animation case
[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_play_sound_simple(const char *path, const char *stream_role)
202 {
203         int ret = WAV_PLAYER_ERROR_NONE;
204         char m_path[PATH_MAX];
205         int handle;
206         GError *err = NULL;
207         GVariant *reply = NULL;
208         GDBusConnection *conn = NULL;
209
210         if (!path || !stream_role) {
211                 LOGE("invalid params path(%p), stream_role(%p)", path, stream_role);
212                 return WAV_PLAYER_ERROR_INVALID_PARAMETER;
213         }
214
215         LOGI("path(%s), stream_role(%s)", path, stream_role);
216
217         /* FIXME : need extraction of duplicated path validation code */
218         m_path[0] = '\0';
219         if (path[0] != '/' && getcwd(m_path, PATH_MAX) != NULL)
220                 strncat(m_path, "/", PATH_MAX - strlen(m_path) - 1);
221
222         strncat(m_path, path, PATH_MAX - strlen(m_path) - 1);
223         if (access(m_path, R_OK) != 0) {
224                 char str_error[256];
225                 strerror_r(errno, str_error, sizeof(str_error));
226                 LOGE("file [%s] doesn't exists : [%s][%d]", m_path, str_error, errno);
227                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
228         }
229
230         if (!(conn = __get_dbus_connection()))
231                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
232
233         reply = g_dbus_connection_call_sync(conn, PA_BUS_NAME,
234                                                                                 PA_SOUND_PLAYER_OBJECT_PATH,
235                                                                                 PA_SOUND_PLAYER_INTERFACE,
236                                                                                 PA_SOUND_PLAYER_METHOD_NAME_SOUND_PLAY,
237                                                                                 g_variant_new("(siisi)", m_path, 1,
238                                                                                                           getpid(), stream_role, -1),
239                                                                                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
240         if (!reply) {
241                 if (err) {
242                         LOGE("g_dbus_connection_call_sync error (%s)", err->message);
243                         ret = __convert_dbus_error(err->message);
244                         g_error_free(err);
245                 } else {
246                         ret = WAV_PLAYER_ERROR_INVALID_OPERATION;
247                 }
248                 goto finish;
249         }
250
251         g_variant_get(reply, "(i)", &handle);
252         g_variant_unref(reply);
253
254         LOGI("handle : %d", handle);
255
256 finish:
257         g_object_unref(conn);
258
259         return ret;
260 }
261
262 int _wav_stop_sound(int id)
263 {
264         GDBusConnection *conn = NULL;
265         GError *err = NULL;
266         GVariant *reply = NULL;
267
268         LOGI("handle(%d)", id);
269
270         if (!(conn = __get_dbus_connection()))
271                 return WAV_PLAYER_ERROR_INVALID_OPERATION;
272
273         reply = g_dbus_connection_call_sync(conn,
274                                 PA_BUS_NAME,
275                                 PA_SOUND_PLAYER_OBJECT_PATH,
276                                 PA_SOUND_PLAYER_INTERFACE,
277                                 PA_SOUND_PLAYER_METHOD_NAME_SOUND_STOP,
278                                 g_variant_new("(i)", id),
279                                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
280
281         g_object_unref(conn);
282
283         if (!reply) {
284                 int ret;
285
286                 LOGE("g_dbus_connection_call_sync error (%s)", err->message);
287                 ret = __convert_dbus_error(err->message);
288                 g_error_free(err);
289                 return ret;
290         }
291
292         g_variant_unref(reply);
293
294         LOGI("stop sound. handle(%d)", id);
295
296         return WAV_PLAYER_ERROR_NONE;
297 }