#define LOG_TAG "TIZEN_N_WAV_PLAYER"
-#include <mm_sound.h>
-#include <mm_sound_private.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include <dlog.h>
#include <stdlib.h>
+#include <gio/gio.h>
+#include <glib.h>
#include "wav_player_private.h"
-int _convert_wav_player_error_code(const char *func, int code)
+#define PA_BUS_NAME "org.pulseaudio.Server"
+#define PA_SOUND_PLAYER_OBJECT_PATH "/org/pulseaudio/SoundPlayer"
+#define PA_SOUND_PLAYER_INTERFACE "org.pulseaudio.SoundPlayer"
+
+#define PA_SOUND_PLAYER_METHOD_NAME_SOUND_PLAY "SoundPlay"
+#define PA_SOUND_PLAYER_METHOD_NAME_SOUND_STOP "SoundStop"
+#define PA_SOUND_PLAYER_SIGNAL_EOS "EOS"
+
+struct dbus_cb_data {
+ GDBusConnection *conn;
+ int handle;
+ guint subs_id;
+ wav_player_playback_completed_cb cb;
+ void *user_data;
+};
+
+static int __convert_dbus_error(const char *error_msg)
{
- int ret = WAV_PLAYER_ERROR_INVALID_OPERATION;
- char *errorstr = NULL;
- switch (code) {
- case MM_ERROR_NONE:
- ret = WAV_PLAYER_ERROR_NONE;
- errorstr = "ERROR_NONE";
- break;
- case MM_ERROR_INVALID_ARGUMENT:
- case MM_ERROR_SOUND_INVALID_POINTER:
- case WAV_PLAYER_ERROR_INVALID_PARAMETER:
- ret = WAV_PLAYER_ERROR_INVALID_PARAMETER;
- errorstr = "INVALID_PARAMETER";
- break;
- case MM_ERROR_SOUND_INTERNAL:
- ret = WAV_PLAYER_ERROR_INVALID_OPERATION;
- errorstr = "INVALID_OPERATION";
- break;
- case MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE:
- ret = WAV_PLAYER_ERROR_FORMAT_NOT_SUPPORTED;
- errorstr = "FORMAT_NOT_SUPPORTED";
- break;
- case WAV_PLAYER_ERROR_NOT_SUPPORTED_TYPE:
- ret = WAV_PLAYER_ERROR_NOT_SUPPORTED_TYPE;
- errorstr = "NOT_SUPPORTED_TYPE";
- break;
- default:
- ret = WAV_PLAYER_ERROR_INVALID_OPERATION;
- errorstr = "INVALID_OPERATION";
- break;
+ if (error_msg) {
+ if (strstr(error_msg, "UnsupportedMediaType"))
+ return WAV_PLAYER_ERROR_FORMAT_NOT_SUPPORTED;
+ else if (strstr(error_msg, "InvalidArgument"))
+ return WAV_PLAYER_ERROR_INVALID_PARAMETER;
}
- LOGE("[%s] %s(0x%08x)", func, errorstr, ret);
- return ret;
+
+ return WAV_PLAYER_ERROR_INVALID_OPERATION;
}
-void _internal_complete_cb(void *user_data, int id)
+static GDBusConnection *__get_dbus_connection(void)
{
- _cb_data *cb_data = (_cb_data*)user_data;
- if (!cb_data)
+ GDBusConnection *conn = NULL;
+ GError *err = NULL;
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (!conn) {
+ LOGE("g_bus_get_sync() error (%s)", err->message);
+ g_error_free(err);
+ }
+
+ return conn;
+}
+
+static void __internal_complete_cb(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *params,
+ gpointer userdata)
+{
+ int handle;
+ struct dbus_cb_data *dbus_data = (struct dbus_cb_data *)userdata;
+
+ g_variant_get(params, "(i)", &handle);
+
+ if (!dbus_data) {
+ LOGE("dbus data is null. handle(%d)", handle);
return;
+ }
+
+ if (handle == dbus_data->handle) {
+ g_dbus_connection_signal_unsubscribe(dbus_data->conn, dbus_data->subs_id);
+ g_object_unref(dbus_data->conn);
- if (cb_data->cb) {
- LOGD("user callback for handle %d call %p", id, cb_data->cb);
- cb_data->cb(id, cb_data->user_data);
+ LOGD("user callback for handle(%d) cb(%p)", handle, dbus_data->cb);
+ dbus_data->cb(handle, dbus_data->user_data);
+ g_free(dbus_data);
}
- free(cb_data);
}
-int _start_with_stream_info(const char *path, sound_stream_info_h stream_info, unsigned loop_count, wav_player_playback_completed_cb callback, void *user_data, int *id)
+int _wav_play_sound(const char *path, sound_stream_info_h stream_info, unsigned loop_count,
+ wav_player_playback_completed_cb callback, void *user_data, int *id)
{
- int ret = MM_ERROR_NONE;
- int player = -1;
+ int ret = WAV_PLAYER_ERROR_NONE;
char m_path[PATH_MAX];
- void (*_completed_cb)(void *, int);
- _completed_cb = NULL;
- _cb_data *cb_data = NULL;
char *stream_type = NULL;
int stream_id;
bool result = false;
- if (path == NULL || stream_info == NULL)
- return _convert_wav_player_error_code(__func__, WAV_PLAYER_ERROR_INVALID_PARAMETER);
+ int handle;
+ GError *err = NULL;
+ GVariant *reply = NULL;
+ GDBusConnection *conn = NULL;
+ struct dbus_cb_data *dbus_cb_data = NULL;
+
+ if (path == NULL || stream_info == NULL) {
+ LOGE("invalid params");
+ return WAV_PLAYER_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGI("path(%s), loop(%u), cb(%p) user_data(%p)", path, loop_count, callback, user_data);
+
+ m_path[0] = '\0';
+ if (path[0] != '/' && getcwd(m_path, PATH_MAX) != NULL)
+ strncat(m_path, "/", PATH_MAX - strlen(m_path) - 1);
+
+ strncat(m_path, path, PATH_MAX - strlen(m_path) - 1);
+ if (access(m_path, R_OK) != 0) {
+ char str_error[256];
+ strerror_r(errno, str_error, sizeof(str_error));
+ LOGE("file [%s] doesn't exists : [%s][%d]", m_path, str_error, errno);
+ return WAV_PLAYER_ERROR_INVALID_OPERATION;
+ }
ret = sound_manager_is_available_stream_information(stream_info, NATIVE_API_WAV_PLAYER, &result);
- if (!result)
- return _convert_wav_player_error_code(__func__, WAV_PLAYER_ERROR_NOT_SUPPORTED_TYPE);
+ if (!result || ret) {
+ LOGE("stream info is not available. ret(0x%x), result(%d)", ret, result);
+ return WAV_PLAYER_ERROR_NOT_SUPPORTED_TYPE;
+ }
ret = sound_manager_get_type_from_stream_information(stream_info, &stream_type);
- if (ret)
- return _convert_wav_player_error_code(__func__, ret); //LCOV_EXCL_LINE
- ret = sound_manager_get_index_from_stream_information(stream_info, &stream_id);
- if (ret)
- return _convert_wav_player_error_code(__func__, ret); //LCOV_EXCL_LINE
+ if (ret) {
+ LOGE("can't get stream type. ret(0x%x)", ret);
+ return WAV_PLAYER_ERROR_INVALID_OPERATION;
+ }
- m_path[0] = '\0';
- if (path[0] != '/') {
+ ret = sound_manager_get_index_from_stream_information(stream_info, &stream_id);
+ if (ret) {
+ LOGE("can't get stream index. ret(0x%x)", ret);
+ return WAV_PLAYER_ERROR_INVALID_OPERATION;
+ }
- if (getcwd(m_path, PATH_MAX) != NULL)
- strncat(m_path, "/", PATH_MAX - strlen(m_path) - 1);
+ if (!(conn = __get_dbus_connection()))
+ return WAV_PLAYER_ERROR_INVALID_OPERATION;
+
+ reply = g_dbus_connection_call_sync(conn, PA_BUS_NAME,
+ PA_SOUND_PLAYER_OBJECT_PATH,
+ PA_SOUND_PLAYER_INTERFACE,
+ PA_SOUND_PLAYER_METHOD_NAME_SOUND_PLAY,
+ g_variant_new("(siisi)", m_path, loop_count == 0 ? -1 : loop_count,
+ getpid(), stream_type, stream_id),
+ NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+ if (!reply) {
+ LOGE("g_dbus_connection_call_sync error (%s)", err->message);
+ ret = __convert_dbus_error(err->message);
+ g_error_free(err);
+ g_object_unref(conn);
+ return ret;
}
- strncat(m_path, path, PATH_MAX - strlen(m_path) - 1);
+
+ g_variant_get(reply, "(i)", &handle);
+ g_variant_unref(reply);
+ if (id)
+ *id = handle;
+
+ LOGI("handle : %d", handle);
if (callback) {
- _completed_cb = _internal_complete_cb;
- cb_data = (_cb_data *)malloc(sizeof(_cb_data));
- if (cb_data == NULL)
- return _convert_wav_player_error_code(__func__, WAV_PLAYER_ERROR_INVALID_OPERATION); //LCOV_EXCL_LINE
- cb_data->cb = callback;
- cb_data->user_data = user_data;
+ dbus_cb_data = g_new0(struct dbus_cb_data, 1);
+ dbus_cb_data->conn = conn;
+ dbus_cb_data->handle = handle;
+ dbus_cb_data->cb = callback;
+ dbus_cb_data->user_data = user_data;
+ dbus_cb_data->subs_id = g_dbus_connection_signal_subscribe(conn, NULL,
+ PA_SOUND_PLAYER_INTERFACE,
+ PA_SOUND_PLAYER_SIGNAL_EOS,
+ PA_SOUND_PLAYER_OBJECT_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
+ __internal_complete_cb, dbus_cb_data, NULL);
+ if (!dbus_cb_data->subs_id) {
+ g_object_unref(conn);
+ g_free(dbus_cb_data);
+ LOGE("g_dbus_connection_signal_subscribe() failed");
+ return WAV_PLAYER_ERROR_INVALID_OPERATION;
+ }
+ } else {
+ g_object_unref(conn);
}
- ret = mm_sound_play_sound_with_stream_info(m_path, stream_type, stream_id, loop_count, _completed_cb , cb_data, &player);
+ return WAV_PLAYER_ERROR_NONE;
+}
+
+int _wav_stop_sound(int id)
+{
+ GDBusConnection *conn = NULL;
+ GError *err = NULL;
+ GVariant *reply = NULL;
+
+ LOGI("handle(%d)", id);
+
+ if (!(conn = __get_dbus_connection()))
+ return WAV_PLAYER_ERROR_INVALID_OPERATION;
+
+ reply = g_dbus_connection_call_sync(conn,
+ PA_BUS_NAME,
+ PA_SOUND_PLAYER_OBJECT_PATH,
+ PA_SOUND_PLAYER_INTERFACE,
+ PA_SOUND_PLAYER_METHOD_NAME_SOUND_STOP,
+ g_variant_new("(i)", id),
+ NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+
+ g_object_unref(conn);
+
+ if (!reply) {
+ int ret;
+
+ LOGE("g_dbus_connection_call_sync error (%s)", err->message);
+ ret = __convert_dbus_error(err->message);
+ g_error_free(err);
+ return ret;
+ }
- if (ret == 0 && id != NULL)
- *id = player;
+ g_variant_unref(reply);
- if (ret != 0 && cb_data != NULL)
- free(cb_data);
+ LOGI("stop sound. handle(%d)", id);
- return _convert_wav_player_error_code(__func__, ret);
+ return WAV_PLAYER_ERROR_NONE;
}