From 61ef35a084b0637dd3167aec76a0da32f71b26fa Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Wed, 11 Mar 2020 16:32:48 +0900 Subject: [PATCH] Add mm_sound_stop_keysound() [Version] 0.12.65 [Issue Type] Add / cherrypick Change-Id: I2e17159bcafabc4056fcae7cff62ec1a70403c95 --- include/mm_sound_private.h | 17 +- mm_sound_keysound.c | 313 +++++++++++++++++++++------------- packaging/libmm-sound.spec | 2 +- testsuite/mm_sound_testsuite_simple.c | 29 +++- 4 files changed, 240 insertions(+), 121 deletions(-) diff --git a/include/mm_sound_private.h b/include/mm_sound_private.h index de2deac..9258ce7 100644 --- a/include/mm_sound_private.h +++ b/include/mm_sound_private.h @@ -59,17 +59,30 @@ typedef struct { * This function is to play key sound. * * @param filename [in] keytone filename to play - * @param volume_config [in] Volume type & volume gain + * @param volume_config [in] volume type & volume gain * * @return This function returns MM_ERROR_NONE on success, or negative value * with error code. * * @remark This function provide low latency sound play (such as dialer keytone) * using fixed spec of wave file (44100Hz, mono channel) - * @see volume_type_t volume_gain_t mm_sound_volume_set_value + * @see mm_sound_stop_keysound() + * @see volume_type_t volume_gain_t */ int mm_sound_play_keysound(const char *filename, int volume_config); +/** + * This function is to stop key sound. + * + * @param filename [in] keytone filename to stop (can be null if whole exist keytones need stops) + * + * @return This function returns MM_ERROR_NONE on success, or negative value + * with error code. + * + * @see mm_sound_play_keysound() + */ +int mm_sound_stop_keysound(const char *filename); + int mm_sound_boot_ready(int timeout_sec); int mm_sound_boot_play_sound(char* path); diff --git a/mm_sound_keysound.c b/mm_sound_keysound.c index 3c6c95c..38f4a0b 100644 --- a/mm_sound_keysound.c +++ b/mm_sound_keysound.c @@ -38,15 +38,19 @@ #define PULSEAUDIO_READY "/tmp/.pulseaudio_ready" #endif -#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_SIMPLE_PLAY "SimplePlay" - -#define KEYTONE_PATH "/tmp/keytone" /* Keytone pipe path */ -#define FILE_FULL_PATH 1024 /* File path length */ -#define ROLE_NAME_LEN 64 /* Role name length */ -#define VOLUME_GAIN_TYPE_LEN 64 /* Volume gain type length */ +#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_SIMPLE_PLAY "SimplePlay" +#define PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP "SimpleStop" +#define PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP_ALL "SimpleStopAll" +#define PA_SOUND_RESPONSE_TIMEOUT 2000 + +#define KEYTONE_PATH "/tmp/keytone" +#define FILENAME_LEN 1024 +#define ROLE_LEN 64 +#define VOLUME_GAIN_TYPE_LEN 32 +#define METHOD_LEN 32 #define AUDIO_VOLUME_CONFIG_TYPE(vol) (vol & 0x00FF) #define AUDIO_VOLUME_CONFIG_GAIN(vol) (vol & 0xFF00) @@ -55,19 +59,16 @@ #define WRITE_RETRY_INTERVAL_MS 20 typedef struct ipc_data { - char filename[FILE_FULL_PATH]; - char role[ROLE_NAME_LEN]; + char filename[FILENAME_LEN]; + char role[ROLE_LEN]; char volume_gain_type[VOLUME_GAIN_TYPE_LEN]; + char method[METHOD_LEN]; } ipc_t; -typedef enum { - IPC_TYPE_PIPE, - IPC_TYPE_DBUS, -} ipc_type_t; - -static int _mm_sound_play_keysound(const char *filename, int volume_config, ipc_type_t ipc_type); +static int __mm_sound_simple_pipe(const char *filename, int volume_config, const char *method); +static int __mm_sound_simple_dbus(const char *filename, int volume_config, const char *method); -static const char* convert_volume_type_to_role(int volume_type) +static const char* __convert_volume_type_to_role(volume_type) { debug_log("volume_type(%d)", volume_type); switch (volume_type) { @@ -89,7 +90,7 @@ static const char* convert_volume_type_to_role(int volume_type) } } -static const char* convert_volume_gain_type_to_string(int volume_gain_type) +static const char* __convert_volume_gain_type_to_string(int volume_gain_type) { debug_log("volume_gain_type(0x%x)", volume_gain_type); switch (volume_gain_type) { @@ -123,7 +124,14 @@ static const char* convert_volume_gain_type_to_string(int volume_gain_type) EXPORT_API int mm_sound_play_keysound(const char *filename, int volume_config) { - return _mm_sound_play_keysound(filename, volume_config, IPC_TYPE_PIPE); + return __mm_sound_simple_pipe(filename, volume_config, PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY); +} + +EXPORT_API +int mm_sound_stop_keysound(const char *filename) +{ + return __mm_sound_simple_pipe(filename, 0, + (filename) ? PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP : PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP_ALL); } #ifdef USE_LWIPC @@ -145,12 +153,32 @@ static bool _mm_sound_check_pa_ready() } #endif -static int _mm_sound_play_keysound(const char *filename, int volume_config, ipc_type_t ipc_type) +static int __verify_input_file(const char *filename) +{ + if (!filename) + return MM_ERROR_SOUND_INVALID_FILE; + + /* Check whether file exists */ + if (access(filename, F_OK) == -1) { + char str_error[256]; + + strerror_r(errno, str_error, sizeof(str_error)); + debug_error("file [%s] doesn't exists : [%s][%d]", filename, str_error, errno); + + return MM_ERROR_SOUND_FILE_NOT_FOUND; + } + + return MM_ERROR_NONE; +} + +static int __mm_sound_simple_pipe(const char *filename, int volume_config, const char *method) { int ret = MM_ERROR_NONE; - const char *role = NULL; - const char *vol_gain_type = NULL; int retry_remaining = MAX_WRITE_RETRY; + size_t size_to_write = sizeof(ipc_t); + ssize_t written = 0; + int fd = -1; + ipc_t data = { { 0, }, { 0, }, { 0, } }; #ifdef USE_LWIPC if (!_mm_sound_check_pa_ready()) { @@ -159,114 +187,171 @@ static int _mm_sound_play_keysound(const char *filename, int volume_config, ipc_ } #endif - if (!filename) - return MM_ERROR_SOUND_INVALID_FILE; + if (!method) + return MM_ERROR_INVALID_ARGUMENT; - /* Check whether file exists */ - if (access(filename, F_OK) == -1) { - char str_error[256]; + /* Prepare data to be send */ + g_strlcpy(data.method, method, METHOD_LEN); - strerror_r(errno, str_error, sizeof(str_error)); - debug_error("file [%s] doesn't exists : [%s][%d]", filename, str_error, errno); + if (g_strcmp0(method, PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP_ALL) != 0) { + ret = __verify_input_file(filename); + if (ret != MM_ERROR_NONE) + return ret; - return MM_ERROR_SOUND_FILE_NOT_FOUND; + g_strlcpy(data.filename, filename, FILENAME_LEN); } - /* convert volume type to role/volume gain */ - role = convert_volume_type_to_role(AUDIO_VOLUME_CONFIG_TYPE(volume_config)); - if (role) - vol_gain_type = convert_volume_gain_type_to_string(AUDIO_VOLUME_CONFIG_GAIN(volume_config)); + if (g_strcmp0(method, PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY) == 0) { + g_strlcpy(data.role, + __convert_volume_type_to_role(AUDIO_VOLUME_CONFIG_TYPE(volume_config)), + ROLE_LEN); + g_strlcpy(data.volume_gain_type, + __convert_volume_gain_type_to_string(AUDIO_VOLUME_CONFIG_GAIN(volume_config)), + VOLUME_GAIN_TYPE_LEN); + } - if (ipc_type == IPC_TYPE_PIPE) { - size_t size_to_write = sizeof(ipc_t); - ssize_t written = 0; - int fd = -1; - ipc_t data = { { 0, }, { 0, }, { 0, } }; + debug_msg("filepath=[%s], role=[%s], volume_gain_type=[%s], method=[%s]", + data.filename, data.role, data.volume_gain_type, data.method); + + /* Open PIPE */ + fd = open(KEYTONE_PATH, O_WRONLY | O_NONBLOCK); + if (fd == -1) { + char str_error[256]; + + strerror_r(errno, str_error, sizeof(str_error)); + debug_error("Fail to open pipe: [%s][%d]", str_error, errno); - /* Open PIPE */ - fd = open(KEYTONE_PATH, O_WRONLY | O_NONBLOCK); - if (fd == -1) { + return MM_ERROR_SOUND_INTERNAL; + } + + /* Write to PIPE */ + do { + written = write(fd, &data, size_to_write); + if (written == -1) { char str_error[256]; + int errsv = errno; + + strerror_r(errsv, str_error, sizeof(str_error)); + debug_error("[%d] Fail to write, written = %zd, [%s][%d]", + MAX_WRITE_RETRY - retry_remaining, written, str_error, errsv); - strerror_r(errno, str_error, sizeof(str_error)); - debug_error("Fail to open pipe: [%s][%d]", str_error, errno); + if (errsv != EAGAIN || --retry_remaining == 0) { + ret = MM_ERROR_SOUND_INTERNAL; + break; + } - return MM_ERROR_SOUND_INTERNAL; + usleep(WRITE_RETRY_INTERVAL_MS * 1000); + } else if (retry_remaining != MAX_WRITE_RETRY) { + debug_msg("retry success!!"); } + } while (written != size_to_write); - /* convert volume type to role/volume gain */ - if (role) - MMSOUND_STRNCPY(data.role, role, ROLE_NAME_LEN); - if (vol_gain_type) - MMSOUND_STRNCPY(data.volume_gain_type, vol_gain_type, VOLUME_GAIN_TYPE_LEN); - MMSOUND_STRNCPY(data.filename, filename, FILE_FULL_PATH); - - debug_msg("filepath=[%s], role=[%s], volume_gain_type=[%s]", data.filename, data.role, data.volume_gain_type); - - /* Write to PIPE */ - do { - written = write(fd, &data, size_to_write); - if (written == -1) { - char str_error[256]; - int errsv = errno; - - strerror_r(errsv, str_error, sizeof(str_error)); - debug_error("[%d] Fail to write, written = %zd, [%s][%d]", - MAX_WRITE_RETRY - retry_remaining, written, str_error, errsv); - - if (errsv != EAGAIN || --retry_remaining == 0) { - ret = MM_ERROR_SOUND_INTERNAL; - break; - } - - usleep(WRITE_RETRY_INTERVAL_MS * 1000); - } else if (retry_remaining != MAX_WRITE_RETRY) { - debug_msg("retry success!!"); - } - } while (written != size_to_write); + /* Close PIPE */ + close(fd); + + return ret; + } + +static int __mm_sound_simple_dbus(const char *filename, int volume_config, const char *method) +{ + int ret = MM_ERROR_NONE; + const char *role = NULL; + const char *vol_gain_type = NULL; + GVariant *result = NULL; + GDBusConnection *conn = NULL; + GError *err = NULL; + int idx = 0; + +#ifdef USE_LWIPC + if (!_mm_sound_check_pa_ready()) { + debug_error("Pulseaudio is not ready!"); + return MM_ERROR_SOUND_INVALID_STATE; + } +#endif + if (!method) + return MM_ERROR_INVALID_ARGUMENT; - /* Close PIPE */ - close(fd); + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (!conn || err) { + debug_error("g_bus_get_sync() error (%s)", err ? err->message : NULL); + g_error_free(err); + return MM_ERROR_SOUND_INTERNAL; + } - } else if (ipc_type == IPC_TYPE_DBUS) { - GVariant *result = NULL; - GDBusConnection *conn = NULL; - GError *err = NULL; - int idx = 0; + if (g_strcmp0(method, PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY) == 0) { + ret = __verify_input_file(filename); + if (ret != MM_ERROR_NONE) + goto END; + + role = __convert_volume_type_to_role(AUDIO_VOLUME_CONFIG_TYPE(volume_config)); + vol_gain_type = __convert_volume_gain_type_to_string(AUDIO_VOLUME_CONFIG_GAIN(volume_config)); + + result = g_dbus_connection_call_sync(conn, PA_BUS_NAME, + PA_SOUND_PLAYER_OBJECT_PATH, + PA_SOUND_PLAYER_INTERFACE, + PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY, + g_variant_new("(sss)", filename, role, vol_gain_type), + NULL, G_DBUS_CALL_FLAGS_NONE, PA_SOUND_RESPONSE_TIMEOUT, NULL, &err); + if (!result || err) { + debug_error("g_dbus_connection_call_sync() for %s error (%s)", method, err ? err->message : NULL); + ret = MM_ERROR_SOUND_INTERNAL; + goto END; + } - conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); - if (!conn || err) { - debug_error("g_bus_get_sync() error (%s)", err ? err->message : NULL); + g_variant_get(result, "(i)", &idx); + if (idx == -1) { + debug_error("[%s] failure, filename(%s)/role(%s)/gain(%s)/stream idx(%d)", + method, filename, role, vol_gain_type, idx); ret = MM_ERROR_SOUND_INTERNAL; - } else { - result = g_dbus_connection_call_sync(conn, - PA_BUS_NAME, - PA_SOUND_PLAYER_OBJECT_PATH, - PA_SOUND_PLAYER_INTERFACE, - PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY, - g_variant_new("(sss)", filename, role, vol_gain_type), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 2000, - NULL, - &err); - if (!result || err) { - debug_error("g_dbus_connection_call_sync() for SIMPLE_PLAY error (%s)", err ? err->message : NULL); - ret = MM_ERROR_SOUND_INTERNAL; - } else { - g_variant_get(result, "(i)", &idx); - if (idx == -1) { - debug_error("SIMPLE_PLAY failure, filename(%s)/role(%s)/gain(%s)/stream idx(%d)", filename, role, vol_gain_type, idx); - ret = MM_ERROR_SOUND_INTERNAL; - } else { - debug_msg("SIMPLE_PLAY success, filename(%s)/role(%s)/gain(%s)/stream idx(%d)", filename, role, vol_gain_type, idx); - } - g_variant_unref(result); - } - g_object_unref(conn); + goto END; } - g_error_free(err); + debug_msg("[%s] success, filename(%s)/role(%s)/gain(%s)/stream idx(%d)", + method, filename, role, vol_gain_type, idx); + + } else if (g_strcmp0(method, PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP) == 0) { + ret = __verify_input_file(filename); + if (ret != MM_ERROR_NONE) + goto END; + + result = g_dbus_connection_call_sync(conn, PA_BUS_NAME, + PA_SOUND_PLAYER_OBJECT_PATH, + PA_SOUND_PLAYER_INTERFACE, + PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP, + g_variant_new("(s)", filename), + NULL, G_DBUS_CALL_FLAGS_NONE, PA_SOUND_RESPONSE_TIMEOUT, NULL, &err); + if (!result || err) { + debug_error("g_dbus_connection_call_sync() for %s error (%s)", method, err ? err->message : NULL); + ret = MM_ERROR_SOUND_INTERNAL; + goto END; + } + debug_msg("[%s] done, filename(%s)", method, filename); + + } else if (g_strcmp0(method, PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP_ALL) == 0) { + result = g_dbus_connection_call_sync(conn, PA_BUS_NAME, + PA_SOUND_PLAYER_OBJECT_PATH, + PA_SOUND_PLAYER_INTERFACE, + PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP_ALL, + NULL, + NULL, G_DBUS_CALL_FLAGS_NONE, PA_SOUND_RESPONSE_TIMEOUT, NULL, &err); + if (!result || err) { + debug_error("g_dbus_connection_call_sync() for %s error (%s)", method, err ? err->message : NULL); + ret = MM_ERROR_SOUND_INTERNAL; + goto END; + } + debug_msg("[%s] done", method); + + } else { + debug_error("Invalid Method : %s", method); + ret = MM_ERROR_INVALID_ARGUMENT; } +END: + if (err) + g_error_free(err); + if (result) + g_variant_unref(result); + if (conn) + g_object_unref(conn); + return ret; -} +} \ No newline at end of file diff --git a/packaging/libmm-sound.spec b/packaging/libmm-sound.spec index ab11251..9c5a536 100644 --- a/packaging/libmm-sound.spec +++ b/packaging/libmm-sound.spec @@ -1,6 +1,6 @@ Name: libmm-sound Summary: MMSound Package contains client lib and sound_server binary -Version: 0.12.64 +Version: 0.12.65 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/testsuite/mm_sound_testsuite_simple.c b/testsuite/mm_sound_testsuite_simple.c index f72e2fd..677c9ff 100755 --- a/testsuite/mm_sound_testsuite_simple.c +++ b/testsuite/mm_sound_testsuite_simple.c @@ -44,8 +44,9 @@ #include #include -#define POWERON_FILE "/usr/share/feedback/sound/operation/power_on.wav" -#define KEYTONE_FILE "/usr/share/feedback/sound/operation/operation.wav" +#define POWERON_FILE "/usr/share/keysound/poweron.ogg" +#define KEYTONE_FILE "/usr/share/sounds/sound-server/Tizen_HW_Touch.ogg" +#define KEYTONE_NOTI_FILE "/usr/share/sounds/alsa/Front_Center.wav" enum { CURRENT_STATUS_MAINMENU = 0, @@ -195,7 +196,11 @@ static void displaymenu() g_print("==================================================================\n"); g_print(" Sound Play APIs\n"); g_print("==================================================================\n"); - g_print("k : Key Sound \t"); + g_print("k : Play Keysound \t"); + g_print("ks : Stop Keysound \t"); + g_print("kn : Play Keysound (Notification) \t"); + g_print("ksn : Stop Keysound (Notification) \t"); + g_print("ksa : Stop Keysound (All) \n"); g_print("as : play sound with stream type\n"); g_print("FS : Play DTMF with stream type\t"); g_print("b : Play directory\n"); @@ -498,10 +503,26 @@ static void interpret(char *cmd) ret = mm_sound_unset_focus_watch_callback(g_focus_watch_index); if (ret) g_print("failed to mm_sound_unset_focus_watch_callback(), ret[0x%x]\n", ret); + } else if (strncmp(cmd, "ksn", 3) == 0) { + ret = mm_sound_stop_keysound(KEYTONE_NOTI_FILE); + if (ret < 0) + debug_error("keysound stop(noti) failed with 0x%x", ret); + } else if (strncmp(cmd, "ksa", 3) == 0) { + ret = mm_sound_stop_keysound(NULL); + if (ret < 0) + debug_error("keysound stop(all) failed with 0x%x", ret); + } else if (strncmp(cmd, "kn", 2) == 0) { + ret = mm_sound_play_keysound(KEYTONE_NOTI_FILE, VOLUME_TYPE_NOTIFICATION); + if (ret < 0) + debug_error("keysound play(noti) failed with 0x%x", ret); + } else if (strncmp(cmd, "ks", 2) == 0) { + ret = mm_sound_stop_keysound(KEYTONE_FILE); + if (ret < 0) + debug_error("keysound stop failed with 0x%x", ret); } else if (strncmp(cmd, "k", 1) == 0) { ret = mm_sound_play_keysound(KEYTONE_FILE, 0); if (ret < 0) - debug_log("keysound play failed with 0x%x", ret); + debug_error("keysound play failed with 0x%x", ret); } else if (strcmp(cmd, "dbus-m") == 0) { int ret = 0; int a = 3; -- 2.7.4