2 * Copyright (c) 2011-2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "TIZEN_N_WAV_PLAYER"
28 #include "wav_player_private.h"
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"
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"
38 typedef struct dbus_cb_data {
41 wav_player_playback_completed_cb cb;
45 static int __convert_dbus_error(const char *error_msg)
48 if (strstr(error_msg, "UnsupportedMediaType"))
49 return WAV_PLAYER_ERROR_FORMAT_NOT_SUPPORTED;
50 else if (strstr(error_msg, "InvalidArgument"))
51 return WAV_PLAYER_ERROR_INVALID_PARAMETER;
54 return WAV_PLAYER_ERROR_INVALID_OPERATION;
57 static void __weak_notify_cb(gpointer data, GObject *where_the_object_was)
59 LOGD("object(%p) destroyed, data(%p)", where_the_object_was, data);
62 static GDBusConnection *__get_dbus_connection(void)
64 GDBusConnection *conn = NULL;
65 g_autoptr(GError) err = NULL;
67 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
69 LOGE("g_bus_get_sync() error (%s)", err->message);
73 /* For Debugging Purpose */
74 g_object_weak_ref(G_OBJECT(conn), __weak_notify_cb, NULL);
79 static void __internal_complete_cb(GDBusConnection *connection,
80 const gchar *sender_name,
81 const gchar *object_path,
82 const gchar *interface_name,
83 const gchar *signal_name,
88 gboolean stopped_by_user = FALSE;
89 dbus_cb_data_s *dbus_data = (dbus_cb_data_s *)userdata;
92 LOGE("dbus data is null");
96 g_variant_get(params, "(ib)", &handle, &stopped_by_user);
97 LOGI("Incoming/expected handle(%d/%d), id(%u), callback(%p), stopped_by_user(%d)",
98 handle, dbus_data->handle, dbus_data->subs_id, dbus_data->cb, stopped_by_user);
100 if (handle != dbus_data->handle)
103 if (!stopped_by_user) {
104 LOGI("Invoking user callback(%p) for handle(%d)", dbus_data->cb, handle);
105 dbus_data->cb(handle, dbus_data->user_data);
108 LOGI("user callback returned");
110 g_dbus_connection_signal_unsubscribe(connection, dbus_data->subs_id);
111 g_object_unref(connection);
116 int _wav_play_sound(const char *path, sound_stream_info_h stream_info, unsigned loop_count,
117 wav_player_playback_completed_cb callback, void *user_data, bool stop_others, int *id)
119 int ret = WAV_PLAYER_ERROR_NONE;
120 char m_path[PATH_MAX];
121 char *stream_type = NULL;
126 g_autoptr(GDBusConnection) conn = NULL;
127 g_autoptr(GError) err = NULL;
128 g_autoptr(GVariant) reply = NULL;
129 dbus_cb_data_s *dbus_cb_data = NULL;
131 if (path == NULL || stream_info == NULL) {
132 LOGE("invalid params");
133 return WAV_PLAYER_ERROR_INVALID_PARAMETER;
136 LOGI("path(%s), loop(%u), cb(%p) user_data(%p)", path, loop_count, callback, user_data);
139 if (path[0] != '/' && getcwd(m_path, PATH_MAX) != NULL)
140 strncat(m_path, "/", PATH_MAX - strlen(m_path) - 1);
142 strncat(m_path, path, PATH_MAX - strlen(m_path) - 1);
143 if (access(m_path, R_OK) != 0) {
145 strerror_r(errno, str_error, sizeof(str_error));
146 LOGE("file [%s] doesn't exists : [%s][%d]", m_path, str_error, errno);
147 return WAV_PLAYER_ERROR_INVALID_OPERATION;
150 ret = sound_manager_is_available_stream_information(stream_info, NATIVE_API_WAV_PLAYER, &result);
151 if (!result || ret) {
152 LOGE("stream info is not available. ret(0x%x), result(%d)", ret, result);
153 return WAV_PLAYER_ERROR_NOT_SUPPORTED_TYPE;
156 ret = sound_manager_get_type_from_stream_information(stream_info, &stream_type);
158 LOGE("can't get stream type. ret(0x%x)", ret);
159 return WAV_PLAYER_ERROR_INVALID_OPERATION;
162 ret = sound_manager_get_index_from_stream_information(stream_info, &stream_id);
164 LOGE("can't get stream index. ret(0x%x)", ret);
165 return WAV_PLAYER_ERROR_INVALID_OPERATION;
168 if (!(conn = __get_dbus_connection()))
169 return WAV_PLAYER_ERROR_INVALID_OPERATION;
171 reply = g_dbus_connection_call_sync(conn, PA_BUS_NAME,
172 PA_SOUND_PLAYER_OBJECT_PATH,
173 PA_SOUND_PLAYER_INTERFACE,
174 PA_SOUND_PLAYER_METHOD_NAME_SOUND_PLAY,
175 g_variant_new("(siisib)", m_path, loop_count == 0 ? -1 : loop_count,
176 getpid(), stream_type, stream_id, (gboolean)stop_others),
177 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
179 LOGE("g_dbus_connection_call_sync error (%s)", err->message);
180 ret = __convert_dbus_error(err->message);
184 g_variant_get(reply, "(i)", &handle);
188 LOGI("handle : %d", handle);
191 dbus_cb_data = g_new0(dbus_cb_data_s, 1);
192 dbus_cb_data->handle = handle;
193 dbus_cb_data->cb = callback;
194 dbus_cb_data->user_data = user_data;
195 dbus_cb_data->subs_id = g_dbus_connection_signal_subscribe(
196 g_object_ref(conn), NULL,
197 PA_SOUND_PLAYER_INTERFACE,
198 PA_SOUND_PLAYER_SIGNAL_EOS,
199 PA_SOUND_PLAYER_OBJECT_PATH,
200 NULL, G_DBUS_SIGNAL_FLAGS_NONE,
201 __internal_complete_cb, dbus_cb_data, NULL);
202 if (dbus_cb_data->subs_id == 0) {
203 g_object_unref(conn);
204 g_free(dbus_cb_data);
205 LOGE("g_dbus_connection_signal_subscribe() failed");
206 return WAV_PLAYER_ERROR_INVALID_OPERATION;
210 return WAV_PLAYER_ERROR_NONE;
214 int _wav_play_sound_simple(const char *path, const char *stream_role)
216 char m_path[PATH_MAX];
218 g_autoptr(GDBusConnection) conn = NULL;
219 g_autoptr(GError) err = NULL;
220 g_autoptr(GVariant) reply = NULL;
222 if (!path || !stream_role) {
223 LOGE("invalid params path(%p), stream_role(%p)", path, stream_role);
224 return WAV_PLAYER_ERROR_INVALID_PARAMETER;
227 LOGI("path(%s), stream_role(%s)", path, stream_role);
229 /* FIXME : need extraction of duplicated path validation code */
231 if (path[0] != '/' && getcwd(m_path, PATH_MAX) != NULL)
232 strncat(m_path, "/", PATH_MAX - strlen(m_path) - 1);
234 strncat(m_path, path, PATH_MAX - strlen(m_path) - 1);
235 if (access(m_path, R_OK) != 0) {
237 strerror_r(errno, str_error, sizeof(str_error));
238 LOGE("file [%s] doesn't exists : [%s][%d]", m_path, str_error, errno);
239 return WAV_PLAYER_ERROR_INVALID_OPERATION;
242 if (!(conn = __get_dbus_connection()))
243 return WAV_PLAYER_ERROR_INVALID_OPERATION;
245 reply = g_dbus_connection_call_sync(conn, PA_BUS_NAME,
246 PA_SOUND_PLAYER_OBJECT_PATH,
247 PA_SOUND_PLAYER_INTERFACE,
248 PA_SOUND_PLAYER_METHOD_NAME_SOUND_PLAY,
249 g_variant_new("(siisib)", m_path, 1,
250 getpid(), stream_role, -1, FALSE),
251 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
254 LOGE("g_dbus_connection_call_sync error (%s)", err->message);
255 return __convert_dbus_error(err->message);
257 return WAV_PLAYER_ERROR_INVALID_OPERATION;
260 g_variant_get(reply, "(i)", &handle);
262 LOGI("handle : %d", handle);
264 return WAV_PLAYER_ERROR_NONE;
268 int _wav_stop_sound(int id)
270 g_autoptr(GDBusConnection) conn = NULL;
271 g_autoptr(GError) err = NULL;
272 g_autoptr(GVariant) reply = NULL;
274 LOGI("handle(%d)", id);
276 if (!(conn = __get_dbus_connection()))
277 return WAV_PLAYER_ERROR_INVALID_OPERATION;
279 reply = g_dbus_connection_call_sync(conn,
281 PA_SOUND_PLAYER_OBJECT_PATH,
282 PA_SOUND_PLAYER_INTERFACE,
283 PA_SOUND_PLAYER_METHOD_NAME_SOUND_STOP,
284 g_variant_new("(i)", id),
285 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
287 LOGE("g_dbus_connection_call_sync error (%s)", err->message);
288 return __convert_dbus_error(err->message);
291 LOGI("stop sound. handle(%d)", id);
293 return WAV_PLAYER_ERROR_NONE;