keysound: skip hard frequent request of keysound playback 98/301098/7 accepted/tizen/unified/20231114.041309
authorSeungbae Shin <seungbae.shin@samsung.com>
Wed, 8 Nov 2023 11:18:59 +0000 (20:18 +0900)
committerSeungbae Shin <seungbae.shin@samsung.com>
Fri, 10 Nov 2023 04:41:56 +0000 (13:41 +0900)
A frequent playing request for the same file path less than 30ms will be skipped with warning log.
This workaround solution will be affected except TV build.

[Version] 0.13.25
[Issue Type] Robustness

Change-Id: I4c73fe62710fe861f7854bb4b9349580ee6a04b8

mm_sound_keysound.c
packaging/libmm-sound.spec
testsuite/mm_sound_testsuite_simple.c

index 8196574..ee23fbc 100644 (file)
@@ -23,6 +23,7 @@
 #include <memory.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <stdint.h>
 
 #include <mm_error.h>
 #include <mm_debug.h>
@@ -56,6 +57,8 @@
 #define MAX_WRITE_RETRY 50
 #define WRITE_RETRY_INTERVAL_MS 20
 
+#define MIN_KEYTONE_INTERVAL_US 30000
+
 typedef struct ipc_data {
        char filename[FILENAME_LEN];
        char role[ROLE_LEN];
@@ -128,9 +131,45 @@ static const char* __convert_volume_gain_type_to_string(int volume_gain_type)
        }
 }
 
+static uint64_t __elapsed_time_us(struct timespec *start, struct timespec *end)
+{
+       uint64_t start_us = (uint64_t) start->tv_sec * 1000000 +
+                                               (uint64_t) start->tv_nsec / 1000;
+       uint64_t end_us = (uint64_t) end->tv_sec * 1000000 +
+                                         (uint64_t) end->tv_nsec / 1000;
+
+       return end_us - start_us;
+}
+
+static bool __is_interval_too_short(const char *filename)
+{
+       static struct timespec ts_last_played = { .tv_sec = 0, .tv_nsec = 0 };
+       static char file_last_played[FILENAME_LEN] = { '\0', };
+
+       struct timespec ts_now;
+       clock_gettime(CLOCK_MONOTONIC, &ts_now);
+
+       if (g_strcmp0(file_last_played, filename) == 0 &&
+               __elapsed_time_us(&ts_last_played, &ts_now) < MIN_KEYTONE_INTERVAL_US) {
+               return true;
+       }
+
+       g_strlcpy(file_last_played, filename, sizeof(file_last_played));
+       ts_last_played = ts_now;
+
+       return false;
+}
+
 EXPORT_API
 int mm_sound_play_keysound(const char *filename, int volume_config)
 {
+#ifndef TIZEN_TV
+       if (__is_interval_too_short(filename)) {
+               debug_warning("Too short time (< %u us) to play same file, try next time again...", MIN_KEYTONE_INTERVAL_US);
+               return MM_ERROR_NONE;
+       }
+#endif
+
 #ifdef USE_PIPE
        return __mm_sound_simple_pipe(filename, volume_config, PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY);
 #else
index 7adac59..bd648ab 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-sound
 Summary:    MMSound Package contains client lib and focus server binary
-Version:    0.13.24
+Version:    0.13.25
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index ac5f147..1509653 100755 (executable)
 #define POWERON_FILE   "/usr/share/keysound/poweron.ogg"
 #define KEYTONE_FILE   "/usr/share/sounds/mm-sound/Tizen_HW_Touch.ogg"
 #define KEYTONE_NOTI_FILE      "/usr/share/sounds/alsa/Front_Center.wav"
-#define MM_SOUND_KEYTONE "MM_SOUND_KEYTONE"
+
+#define MM_SOUND_KEYTONE_PATH "MM_SOUND_KEYTONE_PATH"
+
+#define MM_SOUND_KEYTONE_COUNT "MM_SOUND_KEYTONE_COUNT"
+#define MM_SOUND_KEYTONE_COUNT_MAX 10000
+
+#define MM_SOUND_KEYTONE_INTERVAL "MM_SOUND_KEYTONE_INTERVAL"
+#define MM_SOUND_KEYTONE_INTERVAL_MAX 10000 /* 10 sec. */
 
 enum {
        CURRENT_STATUS_MAINMENU = 0,
@@ -345,6 +352,29 @@ mm_sound_device_flags_e select_device_flags(void)
        return (no2flag(input_string[0]) | no2flag(input_string[2]) | no2flag(input_string[4]));
 }
 
+static const char *env_get_str(const char *key, const char *default_str)
+{
+       char *env_str = getenv(key);
+
+       return env_str ? env_str : default_str;
+}
+
+static unsigned int env_get_uint(const char *key, unsigned int min, unsigned int max, unsigned int default_value)
+{
+       char *env_str = getenv(key);
+       unsigned int value = 0;
+
+       if (!env_str)
+               return default_value;
+
+       value = (unsigned int)atoi(env_str);
+
+       g_assert(value >= min);
+       g_assert(value <= max);
+
+       return value;
+}
+
 static void interpret(char *cmd)
 {
        int ret = 0;
@@ -558,10 +588,25 @@ static void interpret(char *cmd)
                        if (ret < 0)
                                debug_error("keysound stop failed with 0x%x", ret);
                } else if (strncmp(cmd, "k", 1) == 0) {
-                       char* env_keytone_path = getenv(MM_SOUND_KEYTONE);
-                       ret = mm_sound_play_keysound(env_keytone_path ? env_keytone_path : KEYTONE_FILE, 0);
-                       if (ret < 0)
-                               debug_error("keysound play failed with 0x%x", ret);
+                       const char* keytone_path =
+                               env_get_str(MM_SOUND_KEYTONE_PATH, KEYTONE_FILE);
+                       unsigned int count =
+                               env_get_uint(MM_SOUND_KEYTONE_COUNT, 0, MM_SOUND_KEYTONE_COUNT_MAX, 1);
+                       unsigned int interval_us =
+                               env_get_uint(MM_SOUND_KEYTONE_INTERVAL, 0, MM_SOUND_KEYTONE_INTERVAL_MAX, 0) * 1000;
+
+                       g_message("keytone path(%s), count(%u), interval(%u us)",
+                               keytone_path, count, interval_us);
+
+                       for (unsigned int i = 0; i < count; i++) {
+                               ret = mm_sound_play_keysound(keytone_path, 0);
+                               if (ret < 0)
+                                       debug_error("keysound play failed with 0x%x", ret);
+
+                               usleep(interval_us);
+                       }
+
+                       g_message("keytone play done");
                } else if (strncmp(cmd, "q", 1) == 0) {
                        unsigned int value = 100;
                        ret = mm_sound_volume_get_value(g_volume_type, &value);