From: Seungbae Shin Date: Wed, 20 Jul 2016 13:03:37 +0000 (+0900) Subject: Revise code X-Git-Tag: accepted/tizen/unified/20170406.055048~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9afd57c1770c3891a1dbc9515f92606a02306f83;p=platform%2Fcore%2Fmultimedia%2Flibmm-sound.git Revise code 1. fix stop sync & no callback when stop 2. remove ogg tremolo code 3. use sndfile on wav plugin (support both .wav and .ogg...) 4. fix for coding rule 5. enable focus_integration 6. remove unused mm_source 7. revise shutdown logic 8. fix invalid path handling Change-Id: Ia6bc8e167fd4f69ac6e68dda96633f37882ff530 --- diff --git a/common/Makefile.am b/common/Makefile.am index 73719c4..2b17948 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -2,8 +2,7 @@ lib_LTLIBRARIES = libmmfsoundcommon.la libmmfsoundcommon_la_SOURCES = mm_ipc.c \ mm_sound_utils.c \ - mm_sound_dbus.c \ - mm_source.c + mm_sound_dbus.c #libmmfsoundcommon_la_DEPENDENCIES = $(libdir)/libmmfcommon.la diff --git a/common/mm_source.c b/common/mm_source.c deleted file mode 100644 index 9931b9d..0000000 --- a/common/mm_source.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * libmm-sound - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Seungbae Shin - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mm_types.h" -#include "mm_debug.h" -#include "mm_error.h" -#include "mm_source.h" -#include "mm_sound_common.h" - -static bool _is_drm_file(const char *filePath) -{ - char *p = NULL; - - if(!filePath || filePath[0] == '\0') { - debug_error("invalid argument\n"); - return false; - } - - p = (char*) strrchr(filePath, '.'); - if( p && ((strncasecmp(p, ".odf", 4) == 0) || (strncasecmp(p, ".dcf", 4) == 0) || - (strncasecmp(p, ".o4a", 4) == 0) || (strncasecmp(p, ".o4v", 4) == 0))) { - return true; - } - return false; -} - -EXPORT_API -int mm_source_open_file(const char *filename, MMSourceType *source, int drmsupport) -{ - struct stat finfo = {0, }; - int fd = -1; - void *mmap_buf = NULL; - unsigned int mediaSize, offSet=0; - int readSize = 0; - char genStr[20]; - int i; - - if(filename == NULL) { - debug_error("filename is null\n"); - return MM_ERROR_SOUND_INVALID_FILE; - } - if(drmsupport) { - if(_is_drm_file(filename)) { - debug_error("%s is DRM contents\n", filename); - return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; - } - } - - fd = open(filename, O_RDONLY); - if (fd == -1) { - char str_error[256]; - strerror_r(errno, str_error, sizeof(str_error)); - debug_error("file [%s] open fail [%s]\n", filename, str_error); - return MM_ERROR_SOUND_INTERNAL; - } - if (fstat(fd, &finfo) == -1) { - debug_error("file [%s] get info fail\n", filename); - close(fd); - return MM_ERROR_SOUND_INTERNAL; - } - - mediaSize = (unsigned int)finfo.st_size; - - /* get the extension (3 characters from last including NULL)*/ - strncpy((void *)genStr,(void *)(filename+(strlen(filename)-2)),3); - -#if defined(_DEBUG_VERBOS_) - debug_log("Open file [%s] ext[%s]\n", filename, genStr); -#endif - - if(strcasecmp (genStr, "dm") == 0) { - debug_msg("It is DM file going ahead with special decoding\n"); - - /* Vlidation of the DM file */ - readSize = read(fd,(void*)genStr,0x8); - if(readSize != 0x8) { - debug_error("Error in Reading the file Header %x/0x8\n",readSize); - close(fd); - return MM_ERROR_SOUND_INTERNAL; - } - - genStr[readSize] ='\0'; - - debug_msg("Header details of DM file %s\n",genStr); - - if(strcasecmp (genStr, "--random") != 0) { - debug_error("It is not a valied DM file"); - close(fd); - return MM_ERROR_SOUND_INTERNAL; - } - - /*checking the Media Type */ - readSize = lseek(fd, 0x32, SEEK_SET); - if(readSize != 0x32) { - debug_error("Error in Seeking the file to offset %x/0x32\n",readSize); - close(fd); - return MM_ERROR_SOUND_INTERNAL; - } - - readSize = read(fd,(void*)genStr,0xf); - if (readSize != 0xf) { - debug_error("Error in Reading the file Header %x/0xf\n",readSize); - close(fd); - return MM_ERROR_SOUND_INTERNAL; - } - for(i=0;i<0xf;i++) { - if(genStr[i] == (char)0xD) { - genStr[i] ='\0'; - break; - } - } - - debug_msg("Header details of DM file %s\n",genStr); - - /*Finding the Media Offset */ - - if(strcasecmp (genStr, "audio/mpeg") == 0) { - offSet = 0x63; - } else if(strcasecmp (genStr, "audio/wav") == 0) { - offSet = 0x62; - } else { - debug_error("It is not MP3/Wav DM file \n"); - close(fd); - return MM_ERROR_SOUND_INTERNAL; - } - - /*Finding the Media Size */ - mediaSize -= (offSet + 0x28); - - /*Seeking the file to start */ - readSize = lseek(fd, 0x0, SEEK_SET); - - if( readSize != 0x0) { - debug_error("Error in Seeking the file to offset %x/0x32\n",readSize); - close(fd); - return MM_ERROR_SOUND_INTERNAL; - } - } - - mmap_buf = mmap(0, finfo.st_size, PROT_READ, MAP_SHARED, fd,0); - if (mmap_buf == NULL) { - debug_error("MMAP fail\n"); - close(fd); - return MM_ERROR_SOUND_INTERNAL; - } - source->ptr = mmap_buf+offSet; - source->medOffset = offSet; -#if defined(_DEBUG_VERBOS_) - debug_log("source ptr[%p] med offset size[%d]\n", source->ptr, source->medOffset); -#endif - source->tot_size = finfo.st_size; - source->cur_size = mediaSize; - source->type = MM_SOURCE_FILE; - source->fd = fd; - - return MM_ERROR_NONE; -} - -EXPORT_API -int mm_source_open_full_memory(const void *ptr, int totsize, int alloc, MMSourceType *source) -{ - int err = MM_ERROR_NONE; - if (ptr == NULL) { - debug_error("PTR is NULL\n"); - return MM_ERROR_INVALID_ARGUMENT; - } - - if (alloc) { - err = mm_source_open_memory(ptr, totsize, totsize, source); - } else { - source->ptr = (void *)ptr; - source->tot_size = totsize; - source->cur_size = totsize; - source->type = MM_SOURCE_MEMORY_NOTALLOC; - source->fd = -1; - } - - return err; -} - -EXPORT_API -int mm_source_open_memory(const void *ptr, int totsize, int size, MMSourceType *source) -{ - source->ptr = (unsigned char*) malloc(totsize); - if (source->ptr == NULL) { - debug_error("memory alloc fail\n"); - return MM_ERROR_SOUND_NO_FREE_SPACE; - } - source->tot_size = totsize; - source->cur_size = 0; - source->type = MM_SOURCE_MEMORY; - source->fd = -1; - - return mm_source_append_memory(ptr, size, source); -} - -EXPORT_API -int mm_source_append_memory(const void *ptr, int size, MMSourceType *source) -{ - if (source->cur_size + size > source->tot_size) { - debug_error("memory too large\n"); - return MM_ERROR_SOUND_NO_FREE_SPACE; - } - - memcpy(source->ptr + source->cur_size, ptr, size); - source->cur_size += size; - return MM_ERROR_NONE; -} - -EXPORT_API -int mm_source_close(MMSourceType *source) -{ - if(source == NULL) { - debug_critical("source is null\n"); - return MM_ERROR_CLASS; - } - -#if defined(_DEBUG_VERBOS_) - debug_log("Source type = %d\n", source->type); -#endif - switch(source->type) - { - case MM_SOURCE_FILE: - if(source->ptr != NULL) { - source->ptr -= source->medOffset; -#if defined(_DEBUG_VERBOS_) - debug_log("Med Offset Size : %d/%d",source->medOffset,source->tot_size); -#endif - if (munmap(source->ptr, source->tot_size) == -1) { - debug_error("MEM UNMAP fail\n\n"); - } - } - close(source->fd); - break; - - case MM_SOURCE_MEMORY: - if(source->ptr != NULL) - free(source->ptr); - break; - - case MM_SOURCE_MEMORY_NOTALLOC: - break; - - default: - debug_critical("Unknown Source\n"); - break; - } - memset(source, 0, sizeof(MMSourceType)); - - return MM_ERROR_NONE; -} diff --git a/configure.ac b/configure.ac index f1f80bd..8dcc4f8 100644 --- a/configure.ac +++ b/configure.ac @@ -54,6 +54,10 @@ PKG_CHECK_MODULES(VCONF, vconf) AC_SUBST(VCONF_CFLAGS) AC_SUBST(VCONF_LIBS) +PKG_CHECK_MODULES(VCONF, sndfile) +AC_SUBST(SNDFILE_CFLAGS) +AC_SUBST(SNDFILE_LIBS) + AC_ARG_ENABLE(pulse, AC_HELP_STRING([--enable-pulse], [enable pulseaudio client]), [ case "${enableval}" in @@ -72,21 +76,6 @@ AC_SUBST(PA_LIBS) fi AM_CONDITIONAL([USE_PULSE], [test "x$USE_PULSE" = "xyes"]) -AC_ARG_ENABLE(ogg, AC_HELP_STRING([--enable-ogg], [enable ogg client]), -[ - case "${enableval}" in - yes) OGG_SUPPORT=yes ;; - no) OGG_SUPPORT=no ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-ogg) ;; - esac - ],[OGG_SUPPORT=no]) -if test "x$OGG_SUPPORT" = "xyes"; then -PKG_CHECK_MODULES(TREMOLO, libtremolo) -AC_SUBST(TREMOLO_CFLAGS) -AC_SUBST(TREMOLO_LIBS) -fi -AM_CONDITIONAL([OGG_SUPPORT], [test "x$OGG_SUPPORT" = "xyes"]) - AC_ARG_ENABLE(lwipc, AC_HELP_STRING([--enable-lwipc], [enable light weight ipc]), [ case "${enableval}" in @@ -154,7 +143,6 @@ Makefile server/Makefile server/plugin/Makefile server/plugin/wav/Makefile -server/plugin/ogg/Makefile server/plugin/tone/Makefile focus_server/Makefile pkgconfig/Makefile diff --git a/focus_server/mm_sound_focus_server.c b/focus_server/mm_sound_focus_server.c index 4a70e8a..b50063e 100644 --- a/focus_server/mm_sound_focus_server.c +++ b/focus_server/mm_sound_focus_server.c @@ -64,9 +64,9 @@ static void _mainloop_run() g_main_loop_run(g_mainloop); } -static sem_t* _sem_create_n_wait() +static sem_t * _sem_create_n_wait() { - sem_t* sem = NULL; + sem_t *sem = NULL; if ((sem = sem_open("booting-sound", O_CREAT, 0660, 0)) == SEM_FAILED) { debug_error("error creating sem : %d", errno); @@ -142,7 +142,7 @@ static void _generate_ready_file(const char *path) int main(int argc, char **argv) { - sem_t* sem = NULL; + sem_t *sem = NULL; server_arg serveropt; #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING) int pid; diff --git a/focus_server/mm_sound_mgr_focus_dbus.c b/focus_server/mm_sound_mgr_focus_dbus.c index 2a242c8..d14658c 100644 --- a/focus_server/mm_sound_mgr_focus_dbus.c +++ b/focus_server/mm_sound_mgr_focus_dbus.c @@ -511,7 +511,7 @@ static void handle_method_call(GDBusConnection *connection, debug_error("Parameter Null"); return; } - debug_log("Method Call, obj : %s, intf : %s, method : %s", object_path, interface_name, method_name); + debug_msg("Method Call, obj : %s, intf : %s, method : %s", object_path, interface_name, method_name); for (method_idx = AUDIO_METHOD_GET_UNIQUE_ID; method_idx < AUDIO_METHOD_MAX; method_idx++) { if (!g_strcmp0(method_name, methods[method_idx].info.name)) { diff --git a/include/mm_source.h b/include/mm_source.h deleted file mode 100644 index 1cf09db..0000000 --- a/include/mm_source.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * libmm-sound - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Seungbae Shin - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef __MM_SOURCE_H__ -#define __MM_SOURCE_H__ - -enum { - MM_SOURCE_NONE = 0, - MM_SOURCE_FILE, - MM_SOURCE_MEMORY, - MM_SOURCE_MEMORY_NOTALLOC, - MM_SOURCE_NUM, -}; - -enum { - MM_SOURCE_NOT_DRM_CONTENTS = 0, - MM_SOURCE_CHECK_DRM_CONTENTS -}; - -typedef struct { - int type; /**< source type (file or memory) */ - void *ptr; /**< pointer to buffer */ - unsigned int cur_size; /**< size of current memory */ - unsigned int tot_size; /**< size of current memory */ - int fd; /**< file descriptor for file */ - unsigned int medOffset; /**Media Offset */ -} MMSourceType; - -#define MMSourceIsUnUsed(psource) \ - ((psource)->type == MM_SOUND_SOURCE_NONE) - -#define MMSourceIsFile(psource) \ - ((psource)->type == MM_SOUND_SOURCE_FILE) - -#define MMSourceIsMemory(psource) \ - ((psource)->type == MM_SOUND_SOURCE_MEMORY) - -#define MMSourceGetPtr(psource) \ - ((psource)->ptr) - -#define MMSourceGetCurSize(psource) \ - ((psource)->cur_size) - -#define MMSourceGetTotSize(psource) \ - ((psource)->tot_size) - -int mm_source_open_file(const char *filename, MMSourceType* source, int drmsupport); -int mm_source_open_full_memory(const void *ptr, int totsize, int alloc, MMSourceType *source); -int mm_source_open_memory(const void *ptr, int totsize, int size, MMSourceType *source); -int mm_source_append_memory(const void *ptr, int size, MMSourceType *source); -int mm_source_close(MMSourceType *source); - -#endif /* __MM_SOURCE_H__ */ - diff --git a/packaging/libmm-sound.spec b/packaging/libmm-sound.spec index c50bd49..78cea47 100644 --- a/packaging/libmm-sound.spec +++ b/packaging/libmm-sound.spec @@ -23,12 +23,12 @@ BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(libpulse) +BuildRequires: pkgconfig(sndfile) %if "%{?TIZEN_PRODUCT_TV}" == "1" BuildRequires: pkgconfig(lwipc) %endif %ifarch %{arm} %endif -BuildRequires: pkgconfig(libtremolo) %description MMSound Package contains client lib and sound_server binary for sound system @@ -62,7 +62,6 @@ MMSound utility package - contians mm_sound_testsuite, sound_check for sound sys %setup -q %build -%define tizen_audio_feature_ogg_enable 1 CFLAGS="%{optflags} -fvisibility=hidden -D_TIZEN_PUBLIC_ -DMM_DEBUG_FLAG -DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\"" ;export CFLAGS @@ -72,10 +71,7 @@ CFLAGS="%{optflags} -fvisibility=hidden -D_TIZEN_PUBLIC_ -DMM_DEBUG_FLAG -DEXPOR ./autogen.sh %configure \ -%if 0%{?tizen_audio_feature_ogg_enable} - --enable-ogg \ --with-plugindir=%{_libdir}/soundplugins/ \ -%endif %if "%{?TIZEN_PRODUCT_TV}" == "1" --enable-prelink \ --enable-lwipc \ @@ -125,9 +121,6 @@ ln -sf ../focus-server.path %{buildroot}%{_unitdir}/multi-user.target.wants/focu %{_libdir}/libmmfbootsound.so.* %{_libdir}/libsoundplugintone.so* %{_libdir}/libsoundpluginwave.so* -%if 0%{?tizen_audio_feature_ogg_enable} -%{_libdir}/libsoundplugintremoloogg.so* -%endif %{_libdir}/soundplugins/libsoundplugintone.so %{_libdir}/soundplugins/libsoundpluginwave.so %if 0%{?tizen_audio_feature_ogg_enable} diff --git a/server/include/mm_sound_mgr_codec.h b/server/include/mm_sound_mgr_codec.h index ce7344a..e15062e 100644 --- a/server/include/mm_sound_mgr_codec.h +++ b/server/include/mm_sound_mgr_codec.h @@ -25,7 +25,6 @@ #include -#include #include #include "../../include/mm_sound.h" @@ -43,7 +42,7 @@ typedef struct { void *msgcallback; /* Client callback function */ void *msgdata; /* Client callback data */ void *param; - MMSourceType *source; /* Will free plugin */ + char *pfilename; int samplerate; int channels; int volume_config; @@ -58,7 +57,7 @@ enum MM_SOUND_CODEC_OP_SOUND, }; -int MMSoundMgrCodecInit(const char *targetdir); +int MMSoundMgrCodecInit(const char *targetdir, GSourceFunc _shutdown_cb); int MMSoundMgrCodecFini(void); int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param); diff --git a/server/include/mm_sound_plugin_codec.h b/server/include/mm_sound_plugin_codec.h index a419978..5c04a2c 100644 --- a/server/include/mm_sound_plugin_codec.h +++ b/server/include/mm_sound_plugin_codec.h @@ -23,17 +23,15 @@ #define __MM_SOUND_PLUGIN_CODEC_H__ #include "mm_sound_plugin.h" -#include #include #define MM_SOUND_STREAM_TYPE_LEN 64 +#define MM_SOUND_MAX_FILENAME 256 enum MMSoundSupportedCodec { MM_SOUND_SUPPORTED_CODEC_INVALID = -1, /**< Invalid codec type */ MM_SOUND_SUPPORTED_CODEC_WAVE, /**< WAVE codec */ - MM_SOUND_SUPPORTED_CODEC_OGG, /**< OGG codec */ MM_SOUND_SUPPORTED_CODEC_DTMF, /**< DTMF codec */ - MM_SOUND_SUPPORTED_CODEC_MP3, /**< MP3 codec */ MM_SOUND_SUPPORTED_CODEC_NUM, /**< Number of audio codec type */ }; @@ -56,7 +54,7 @@ typedef struct { double volume; int volume_config; int keytone; - MMSourceType *source; + char *pfilename; char stream_type[MM_SOUND_STREAM_TYPE_LEN]; int stream_index; pthread_mutex_t *codec_wave_mutex; @@ -65,9 +63,8 @@ typedef struct { typedef struct { int* (*GetSupportTypes)(void); int (*SetThreadPool) (int (*)(void*, void (*)(void*))); - int (*Parse)(MMSourceType*, mmsound_codec_info_t*); + int (*Parse)(const char*, mmsound_codec_info_t*); int (*Create)(mmsound_codec_param_t*, mmsound_codec_info_t*, MMHandleType*); - int (*Play_wav)(mmsound_codec_param_t *, mmsound_codec_info_t *, MMHandleType ); int (*Play)(MMHandleType); int (*Stop)(MMHandleType); int (*Destroy)(MMHandleType); diff --git a/server/include/mm_sound_thread_pool.h b/server/include/mm_sound_thread_pool.h index 8084040..69db759 100644 --- a/server/include/mm_sound_thread_pool.h +++ b/server/include/mm_sound_thread_pool.h @@ -26,7 +26,6 @@ int MMSoundThreadPoolDump(int fulldump); int MMSoundThreadPoolInit(void); -gboolean IsMMSoundThreadPoolRunning(void); int MMSoundThreadPoolRun(void *param, void (*func)(void*)); int MMSoundThreadPoolFini(void); diff --git a/server/mm_sound_mgr_codec.c b/server/mm_sound_mgr_codec.c index 5c50d97..c604cf3 100644 --- a/server/mm_sound_mgr_codec.c +++ b/server/mm_sound_mgr_codec.c @@ -24,14 +24,17 @@ #include #include #include +#include +#include -#include #include #include #include #include #include +#include + #include "include/mm_sound_mgr_common.h" #include "include/mm_sound_mgr_codec.h" #include "include/mm_sound_mgr_ipc.h" @@ -41,8 +44,10 @@ #include "../include/mm_sound_common.h" #include "../include/mm_sound_focus.h" -#define _ENABLE_KEYTONE /* Temporal test code */ - +#define SHUTDOWN_TIMEOUT_SEC 10 +#define STATUS_IDLE 0 +#define STATUS_SOUND 3 +#define SOUND_SLOT_START 0 #define FOCUS_INTEGRATION typedef struct { @@ -63,6 +68,7 @@ typedef struct { unsigned int subs_id; mm_sound_focus_type_e current_focus_type; #endif + bool stop_by_user; bool enable_session; } __mmsound_mgr_codec_handle_t; @@ -71,125 +77,191 @@ static MMSoundPluginType *g_codec_plugins = NULL; static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX]; static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM]; static pthread_mutex_t g_slot_mutex; -static pthread_mutex_t codec_wave_mutex; -static int _MMSoundMgrCodecStopCallback(int param); -static int _MMSoundMgrCodecGetEmptySlot(int *slotid); -static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin); +GSourceFunc g_shutdown_cb; +guint g_timer_id = 0; -#define STATUS_IDLE 0 -#define STATUS_SOUND 3 +#define SLOT_LOCK() do { pthread_mutex_lock(&g_slot_mutex); /* debug_msg("After Slot_mutex LOCK\n"); */ } while (0) +#define SLOT_UNLOCK() do { pthread_mutex_unlock(&g_slot_mutex); /* debug_msg("After Slot_mutex UNLOCK\n"); */ } while (0) + +static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin); +static int _MMSoundMgrCodecStopCallback(int param); -#define SOUND_SLOT_START 0 #ifdef FOCUS_INTEGRATION -void sound_codec_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, const char *reason_for_change, int option, const char *ext_info, void *user_data) +static void _handle_focus_event(int slotid, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, bool is_watch) { - - int slotid = (int)user_data; int result = MM_ERROR_NONE; - debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A"); - - if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){ - debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus"); + if (g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) { + debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus"); return; } + if (focus_state == FOCUS_IS_RELEASED) { - g_slots[slotid].current_focus_type = FOCUS_FOR_BOTH&(~focus_type); - debug_warning ("focus is released -> stop playing"); - result = MMSoundMgrCodecStop(slotid); - if (result != MM_ERROR_NONE) { - debug_log("result error %d\n", result); - } + if (!is_watch) + g_slots[slotid].current_focus_type = FOCUS_FOR_BOTH & (~focus_type); + debug_warning("focus is released -> stop playing"); + result = MMSoundMgrCodecStop(slotid); + if (result != MM_ERROR_NONE) + debug_error("result error 0x%X", result); } - return; } -void sound_codec_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, const char *reason_for_change, const char* ext_info, void *user_data) +static void _sound_codec_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, + const char *reason_for_change, int option, const char *ext_info, void *user_data) +{ + debug_warning("focus callback called -> focus_state(%d), reason_for_change(%s)", + focus_state, reason_for_change ? reason_for_change : "N/A"); + + _handle_focus_event((int)user_data, focus_type, focus_state, false); +} + +static void _sound_codec_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, + const char *reason_for_change, const char *ext_info, void *user_data) +{ + debug_warning("focus watch callback called -> focus_state(%d), reason_for_change(%s)", + focus_state, reason_for_change ? reason_for_change : "N/A"); + + _handle_focus_event((int)user_data, focus_type, focus_state, true); +} + +static void _sound_codec_device_connected_callback(MMSoundDevice_t device, bool is_connected, void *user_data) { int slotid = (int)user_data; int result = MM_ERROR_NONE; + mm_sound_device_type_e type; - debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A"); + debug_warning ("device_connected_callback called : handle[%p], connected[%d], slotid[%d]", device, is_connected, slotid); - if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){ - debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus"); + if (mm_sound_get_device_type (device, &type) != MM_ERROR_NONE) { + debug_error("getting device type failed"); return; } - if (focus_state == FOCUS_IS_ACQUIRED) { - debug_warning ("focus is released -> stop playing"); - result = MMSoundMgrCodecStop(slotid); - if (result != MM_ERROR_NONE) { - debug_log("result error %d\n", result); - } + switch (type) { + case MM_SOUND_DEVICE_TYPE_AUDIOJACK: + case MM_SOUND_DEVICE_TYPE_BLUETOOTH: + case MM_SOUND_DEVICE_TYPE_HDMI: + case MM_SOUND_DEVICE_TYPE_MIRRORING: + case MM_SOUND_DEVICE_TYPE_USB_AUDIO: + if (!is_connected) { + debug_warning("sound device unplugged"); + result = MMSoundMgrCodecStop(slotid); + if (result != MM_ERROR_NONE) + debug_error("MMSoundMgrCodecStop error %d\n", result); + + result = mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id); + if (result != MM_ERROR_NONE) + debug_error("mm_sound_remove_device_connected_callback error %d\n", result); + } + break; + + default: + break; } - return; } +#endif + +/* FIXME : critical section for g_timer_id? */ +static void _mm_sound_mgr_codec_shutdown_timer_start() +{ + if (g_timer_id > 0) { + debug_error("Already active timer [%d] exists", g_timer_id); + return; + } + if (g_shutdown_cb) { + g_timer_id = g_timeout_add_seconds(SHUTDOWN_TIMEOUT_SEC, g_shutdown_cb, NULL); + debug_error("TIMER : new timer [%d]", g_timer_id); + } else { + debug_warning("No Timer started due to invalid shutdown callback"); + } +} -void sound_codec_device_connected_callback(MMSoundDevice_t device, bool is_connected, void *user_data) +static void _mm_sound_mgr_codec_shutdown_timer_stop() { - int slotid = (int)user_data; - int result = MM_ERROR_NONE; - mm_sound_device_type_e type; + if (g_timer_id > 0) { + debug_error("TIMER : remove timer id [%d]", g_timer_id); + g_source_remove(g_timer_id); + g_timer_id = 0; + } else { + debug_log("No Timer to stop..."); + } +} - debug_warning ("device_connected_callback called"); +static int _mm_sound_mgr_codec_slot_get_empty(int *slot) +{ + int slotid = 0; + int err = MM_ERROR_NONE; + + SLOT_LOCK(); + + for (slotid = SOUND_SLOT_START; slotid < MANAGER_HANDLE_MAX ; slotid++) { + if (g_slots[slotid].status == STATUS_IDLE) { + g_slots[slotid].status = STATUS_SOUND; + break; + } + } + + if (slotid < MANAGER_HANDLE_MAX) { + debug_msg("New handle allocated (codec slot ID : [%d])\n", slotid); + *slot = slotid; + + _mm_sound_mgr_codec_shutdown_timer_stop(); - if (mm_sound_get_device_type (device, &type) != MM_ERROR_NONE) { - debug_error("getting device type failed"); } else { - switch (type) { - case MM_SOUND_DEVICE_TYPE_AUDIOJACK: - case MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP: - case MM_SOUND_DEVICE_TYPE_BLUETOOTH_SCO: - case MM_SOUND_DEVICE_TYPE_HDMI: - case MM_SOUND_DEVICE_TYPE_MIRRORING: - case MM_SOUND_DEVICE_TYPE_USB_AUDIO: - if (!is_connected) { - debug_warning("sound device unplugged"); - result = MMSoundMgrCodecStop(slotid); - if (result != MM_ERROR_NONE) { - debug_error("MMSoundMgrCodecStop error %d\n", result); - } - result = mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id); - if (result != MM_ERROR_NONE) { - debug_error("mm_sound_remove_device_connected_callback error %d\n", result); - } - } - break; - default: - break; + debug_warning("Handle is full handle : [%d]\n", slotid); + *slot = -1; + /* Temporal code for reset */ + while (slotid--) { + g_slots[slotid].status = STATUS_IDLE; } + err = MM_ERROR_SOUND_INTERNAL; } + + SLOT_UNLOCK(); + + return err; } -#endif -int MMSoundMgrCodecInit(const char *targetdir) +static gboolean _mm_sound_mgr_codec_slot_is_empty() { - int loop = 0; - int count = 0; + int slotid = 0; - debug_enter("\n"); + for (slotid = SOUND_SLOT_START; slotid < MANAGER_HANDLE_MAX ; slotid++) { + if (g_slots[slotid].status == STATUS_SOUND) + break; + } - memset (g_slots, 0, sizeof(g_slots)); + return (slotid == MANAGER_HANDLE_MAX) ? TRUE : FALSE; +} - if(pthread_mutex_init(&g_slot_mutex, NULL)) { - debug_error("pthread_mutex_init failed\n"); - return MM_ERROR_SOUND_INTERNAL; - } +static void _mm_sound_mgr_codec_slot_clear(int slotid) +{ + memset(&g_slots[slotid], 0, sizeof(__mmsound_mgr_codec_handle_t)); + g_slots[slotid].status = STATUS_IDLE; + + debug_error("SlotID [%d] cleared", slotid); +} + +int MMSoundMgrCodecInit(const char *targetdir, GSourceFunc _shutdown_cb) +{ + int loop = 0; + int slotid = 0; - if(pthread_mutex_init(&codec_wave_mutex, NULL)) { + debug_enter(); + + memset(g_slots, 0, sizeof(g_slots)); + + if (pthread_mutex_init(&g_slot_mutex, NULL)) { debug_error("pthread_mutex_init failed\n"); return MM_ERROR_SOUND_INTERNAL; } - for (count = 0; count < MANAGER_HANDLE_MAX; count++) { - g_slots[count].status = STATUS_IDLE; - g_slots[count].plughandle = 0; - } + for (slotid = 0; slotid < MANAGER_HANDLE_MAX; slotid++) + _mm_sound_mgr_codec_slot_clear(slotid); if (g_codec_plugins) { debug_warning("Please Check Init twice\n"); @@ -203,59 +275,78 @@ int MMSoundMgrCodecInit(const char *targetdir) } } - debug_leave("\n"); + if (_shutdown_cb) + g_shutdown_cb = _shutdown_cb; + else + debug_warning("shutdown callback is NULL"); + + debug_leave(); return MM_ERROR_NONE; } int MMSoundMgrCodecFini(void) { - debug_enter("\n"); + debug_enter(); memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM); MMSoundPluginRelease(g_codec_plugins); g_codec_plugins = NULL; pthread_mutex_destroy(&g_slot_mutex); - pthread_mutex_destroy(&codec_wave_mutex); - debug_leave("\n"); + + debug_leave(); return MM_ERROR_NONE; } +static int _MMSoundMgrCodecFindCodecPluginID(enum MMSoundSupportedCodec codec_to_find) +{ + int plugin_id = 0; + int *codec_type; + + for (plugin_id = 0; plugin_id < MM_SOUND_SUPPORTED_CODEC_NUM; plugin_id++) { + if (g_plugins[plugin_id].GetSupportTypes) { + codec_type = g_plugins[plugin_id].GetSupportTypes(); + if (codec_type[0] == codec_to_find) + return plugin_id; + } + } + + return -1; +} int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param) { - int count = 0; + int plugin_id = 0; mmsound_codec_info_t info; mmsound_codec_param_t codec_param; int err = MM_ERROR_NONE; + #ifdef FOCUS_INTEGRATION int need_focus_unregister = 0; #endif #ifdef DEBUG_DETAIL - debug_enter("\n"); + debug_enter(); #endif - - for (count = 0; g_plugins[count].GetSupportTypes; count++) { - /* Find codec */ - if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE) - break; + plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_WAVE); + if (plugin_id == -1) { + debug_error("Could not find proper codec plugin!!!"); + err = MM_ERROR_SOUND_INTERNAL; + goto cleanup; } - /*The count num means codec type WAV, MP3 */ - debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d], session(type[%d],option[%d])\n", - param->tone, param->repeat_count, param->volume, count, param->session_type, param->session_options); - - if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */ - debug_error("unsupported file type %d\n", count); - err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; + err = g_plugins[plugin_id].Parse(param->pfilename, &info); + if (err != MM_ERROR_NONE) { + debug_error("Could not parse file [%s] by plugin[%d]\n", param->pfilename, plugin_id); goto cleanup; } + debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, plugin_id); + #ifdef DEBUG_DETAIL debug_msg("Get New handle\n"); #endif - err = _MMSoundMgrCodecGetEmptySlot(slotid); + err = _mm_sound_mgr_codec_slot_get_empty(slotid); if (err != MM_ERROR_NONE || *slotid < 0) { debug_error("Empty g_slot is not found\n"); goto cleanup; @@ -265,17 +356,13 @@ int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param) codec_param.volume_config = param->volume_config; codec_param.repeat_count = param->repeat_count; codec_param.volume = param->volume; - codec_param.source = param->source; + codec_param.pfilename = param->pfilename; codec_param.stop_cb = _MMSoundMgrCodecStopCallback; codec_param.param = *slotid; codec_param.pid = (int)param->param; - codec_param.codec_wave_mutex = &codec_wave_mutex; codec_param.stream_index = param->stream_index; MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN); - pthread_mutex_lock(&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex LOCK\n"); -#endif + SLOT_LOCK(); #ifdef FOCUS_INTEGRATION /* @@ -290,28 +377,33 @@ int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param) unsigned int subs_id = 0; - err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, (mm_sound_device_connected_cb)sound_codec_device_connected_callback, (void*) *slotid, &subs_id); + err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, + (mm_sound_device_connected_cb)_sound_codec_device_connected_callback, + (void*) *slotid, &subs_id); if (err) { debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err); - pthread_mutex_unlock(&g_slot_mutex); + SLOT_UNLOCK(); return MM_ERROR_POLICY_INTERNAL; } g_slots[*slotid].subs_id = subs_id; - if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) { + if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || + param->session_type == MM_SESSION_TYPE_ALARM || + param->session_type == MM_SESSION_TYPE_NOTIFY || + param->session_type == MM_SESSION_TYPE_EMERGENCY) { debug_warning("session option is PAUSE_OTHERS -> acquire focus"); err = mm_sound_focus_get_id((int *)(¶m->focus_handle)); - err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid); + err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", _sound_codec_focus_callback, (void*)*slotid); if (err) { debug_error("mm_sound_register_focus_for_session failed [0x%x]", err); - pthread_mutex_unlock(&g_slot_mutex); + SLOT_UNLOCK(); return MM_ERROR_POLICY_INTERNAL; } err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL); if (err) { debug_error("mm_sound_acquire_focus failed [0x%x]", err); err = mm_sound_unregister_focus(param->focus_handle); - pthread_mutex_unlock(&g_slot_mutex); + SLOT_UNLOCK(); return MM_ERROR_POLICY_INTERNAL; } g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH; @@ -320,10 +412,11 @@ int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param) debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus"); } else { debug_warning("need to set focus watch callback"); - err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, sound_codec_focus_watch_callback, (void*)*slotid, (int *)(¶m->focus_wcb_id)); + err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, _sound_codec_focus_watch_callback, + (void*)*slotid, (int *)(¶m->focus_wcb_id)); if (err) { debug_error("mm_sound_set_focus_watch_callback_for_session failed [0x%x]", err); - pthread_mutex_unlock(&g_slot_mutex); + SLOT_UNLOCK(); return MM_ERROR_POLICY_INTERNAL; } } @@ -332,7 +425,7 @@ int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param) #endif /* Codec id WAV or MP3 */ - g_slots[*slotid].pluginid = count; + g_slots[*slotid].pluginid = plugin_id; g_slots[*slotid].param = param->param; /* This arg is used callback data */ g_slots[*slotid].session_type = param->session_type; g_slots[*slotid].session_options = param->session_options; @@ -351,8 +444,7 @@ int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param) if (err != MM_ERROR_NONE) { debug_error("Plugin create fail : 0x%08X\n", err); g_slots[*slotid].status = STATUS_IDLE; - pthread_mutex_unlock(&g_slot_mutex); - debug_warning("After Slot_mutex UNLOCK\n"); + SLOT_UNLOCK(); #ifdef FOCUS_INTEGRATION if (param->focus_handle) { need_focus_unregister = 1; @@ -372,23 +464,26 @@ int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param) #endif } - pthread_mutex_unlock(&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex UNLOCK\n"); -#endif + SLOT_UNLOCK(); cleanup: + if (_mm_sound_mgr_codec_slot_is_empty()) + _mm_sound_mgr_codec_shutdown_timer_start(); + #ifdef FOCUS_INTEGRATION - if(param->session_type != MM_SESSION_TYPE_CALL && + if (param->session_type != MM_SESSION_TYPE_CALL && param->session_type != MM_SESSION_TYPE_VIDEOCALL && param->session_type != MM_SESSION_TYPE_VOIP && param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION && param->enable_session && need_focus_unregister == 1) { - if (param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) { + if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || + param->session_type == MM_SESSION_TYPE_ALARM || + param->session_type == MM_SESSION_TYPE_NOTIFY || + param->session_type == MM_SESSION_TYPE_EMERGENCY) { err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL); - if(mm_sound_unregister_focus(param->focus_handle) || err) { + if (mm_sound_unregister_focus(param->focus_handle) || err) { debug_error("focus cleaning up failed[0x%x]", err); return MM_ERROR_POLICY_INTERNAL; } @@ -402,8 +497,9 @@ cleanup: } #endif + #ifdef DEBUG_DETAIL - debug_leave("\n"); + debug_leave(); #endif return err; @@ -411,31 +507,28 @@ cleanup: int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param) { - int count = 0; + int plugin_id = 0; mmsound_codec_info_t info; mmsound_codec_param_t codec_param; int err = MM_ERROR_NONE; #ifdef DEBUG_DETAIL - debug_enter("\n"); + debug_enter(); #endif - - for (count = 0; g_plugins[count].GetSupportTypes; count++) { - /* Find codec */ - if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE) - break; + plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_WAVE); + if (plugin_id == -1) { + debug_error("Could not find proper codec plugin!!!"); + err = MM_ERROR_SOUND_INTERNAL; + goto cleanup; } - /*The count num means codec type WAV, MP3 */ - debug_msg("Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->repeat_count, param->volume, count); - - if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */ - debug_error("unsupported file type %d\n", count); - err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; + err = g_plugins[plugin_id].Parse(param->pfilename, &info); + if (err != MM_ERROR_NONE) { + debug_error("Could not parse file [%s] by plugin[%d]\n", param->pfilename, plugin_id); goto cleanup; } - err = _MMSoundMgrCodecGetEmptySlot(slotid); + err = _mm_sound_mgr_codec_slot_get_empty(slotid); if (err != MM_ERROR_NONE || *slotid < 0) { debug_error("Empty g_slot is not found\n"); goto cleanup; @@ -444,31 +537,26 @@ int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type codec_param.repeat_count = param->repeat_count; codec_param.volume = param->volume; - codec_param.source = param->source; + codec_param.pfilename = param->pfilename; codec_param.stop_cb = _MMSoundMgrCodecStopCallback; codec_param.param = *slotid; codec_param.pid = (int)param->param; - codec_param.codec_wave_mutex = &codec_wave_mutex; codec_param.stream_index = param->stream_index; MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN); - pthread_mutex_lock(&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex LOCK\n"); -#endif + SLOT_LOCK(); /* Codec id WAV or MP3 */ - g_slots[*slotid].pluginid = count; + g_slots[*slotid].pluginid = plugin_id; g_slots[*slotid].param = param->param; /* This arg is used callback data */ debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status); err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle)); - debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle); + debug_msg("Created audio handle : [%p]\n", g_slots[*slotid].plughandle); if (err != MM_ERROR_NONE) { debug_error("Plugin create fail : 0x%08X\n", err); g_slots[*slotid].status = STATUS_IDLE; - pthread_mutex_unlock(&g_slot_mutex); - debug_warning("After Slot_mutex UNLOCK\n"); + SLOT_UNLOCK(); goto cleanup; } @@ -478,15 +566,14 @@ int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle); } - pthread_mutex_unlock(&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex UNLOCK\n"); -#endif + SLOT_UNLOCK(); cleanup: + if (_mm_sound_mgr_codec_slot_is_empty()) + _mm_sound_mgr_codec_shutdown_timer_start(); #ifdef DEBUG_DETAIL - debug_leave("\n"); + debug_leave(); #endif return err; @@ -496,7 +583,7 @@ cleanup: #define DTMF_PLUGIN_COUNT 2 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param) { - int count = 0; + int plugin_id = 0; int *codec_type; mmsound_codec_info_t info; mmsound_codec_param_t codec_param; @@ -506,22 +593,22 @@ int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param) #endif #ifdef DEBUG_DETAIL - debug_enter("\n"); + debug_enter(); #endif - for (count = 0; g_plugins[count].GetSupportTypes; count++) { + for (plugin_id = 0; g_plugins[plugin_id].GetSupportTypes; plugin_id++) { /* Find codec */ - codec_type = g_plugins[count].GetSupportTypes(); - if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0])) + codec_type = g_plugins[plugin_id].GetSupportTypes(); + if (codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0])) break; } /*The count num means codec type DTMF */ - debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count); + debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, plugin_id); - if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */ - debug_error("unsupported file type %d\n", count); - printf("unsupported file type %d\n", count); + if (g_plugins[plugin_id].GetSupportTypes == NULL) { /* Codec not found */ + debug_error("unsupported file type %d\n", plugin_id); + printf("unsupported file type %d\n", plugin_id); err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; goto cleanup; } @@ -530,9 +617,8 @@ int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param) debug_msg("Get New handle\n"); #endif - err = _MMSoundMgrCodecGetEmptySlot(slotid); - if(err != MM_ERROR_NONE || *slotid < 0) - { + err = _mm_sound_mgr_codec_slot_get_empty(slotid); + if (err != MM_ERROR_NONE || *slotid < 0) { debug_error("Empty g_slot is not found\n"); goto cleanup; } @@ -546,11 +632,7 @@ int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param) codec_param.pid = (int)param->param; codec_param.stream_index = param->stream_index; MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN); - - pthread_mutex_lock(&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex LOCK\n"); -#endif + SLOT_LOCK(); #ifdef FOCUS_INTEGRATION // @@ -566,28 +648,33 @@ int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param) unsigned int subs_id = 0; - err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, (mm_sound_device_connected_cb)sound_codec_device_connected_callback, (void*) *slotid, &subs_id); + err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, + (mm_sound_device_connected_cb)_sound_codec_device_connected_callback, + (void*) *slotid, &subs_id); if (err) { debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err); - pthread_mutex_unlock(&g_slot_mutex); + SLOT_UNLOCK(); return MM_ERROR_POLICY_INTERNAL; } g_slots[*slotid].subs_id = subs_id; - if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) { + if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || + param->session_type == MM_SESSION_TYPE_ALARM || + param->session_type == MM_SESSION_TYPE_NOTIFY || + param->session_type == MM_SESSION_TYPE_EMERGENCY) { debug_warning("session option is PAUSE_OTHERS -> acquire focus"); err = mm_sound_focus_get_id((int *)(¶m->focus_handle)); - err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid); + err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", _sound_codec_focus_callback, (void*)*slotid); if (err) { debug_error("mm_sound_register_focus failed [0x%x]", err); - pthread_mutex_unlock(&g_slot_mutex); + SLOT_UNLOCK(); return MM_ERROR_POLICY_INTERNAL; } err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL); if (err) { debug_error("mm_sound_acquire_focus failed [0x%x]", err); err = mm_sound_unregister_focus(param->focus_handle); - pthread_mutex_unlock(&g_slot_mutex); + SLOT_UNLOCK(); return MM_ERROR_POLICY_INTERNAL; } g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH; @@ -596,17 +683,18 @@ int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param) debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus"); } else { debug_warning("need to set focus watch callback"); - err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, sound_codec_focus_watch_callback, (void*)*slotid, (int *)(¶m->focus_wcb_id)); + err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, _sound_codec_focus_watch_callback, + (void*)*slotid, (int *)(¶m->focus_wcb_id)); if (err) { debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err); - pthread_mutex_unlock(&g_slot_mutex); + SLOT_UNLOCK(); return MM_ERROR_POLICY_INTERNAL; } } } #endif - g_slots[*slotid].pluginid = count; + g_slots[*slotid].pluginid = plugin_id; g_slots[*slotid].param = param->param; /* This arg is used callback data */ g_slots[*slotid].session_type = param->session_type; g_slots[*slotid].session_options = param->session_options; @@ -626,8 +714,7 @@ int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param) if (err != MM_ERROR_NONE) { debug_error("Plugin create fail : 0x%08X\n", err); g_slots[*slotid].status = STATUS_IDLE; - pthread_mutex_unlock(&g_slot_mutex); - debug_warning("After Slot_mutex UNLOCK\n"); + SLOT_UNLOCK(); #ifdef FOCUS_INTEGRATION need_focus_unregister = 1; #endif @@ -643,12 +730,8 @@ int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param) #endif } - pthread_mutex_unlock(&g_slot_mutex); - + SLOT_UNLOCK(); debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex UNLOCK\n") -#endif cleanup: #ifdef FOCUS_INTEGRATION @@ -659,9 +742,12 @@ cleanup: param->enable_session && need_focus_unregister == 1) { - if (param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) { + if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || + param->session_type == MM_SESSION_TYPE_ALARM || + param->session_type == MM_SESSION_TYPE_NOTIFY || + param->session_type == MM_SESSION_TYPE_EMERGENCY) { err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL); - if(mm_sound_unregister_focus(param->focus_handle) || err) { + if (mm_sound_unregister_focus(param->focus_handle) || err) { debug_error("focus cleaning up failed[0x%x]", err); return MM_ERROR_POLICY_INTERNAL; } @@ -676,7 +762,7 @@ cleanup: #endif #ifdef DEBUG_DETAIL - debug_leave("\n"); + debug_leave(); #endif return err; @@ -684,29 +770,29 @@ cleanup: int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param) { - int count = 0; + int plugin_id = 0; int *codec_type; mmsound_codec_info_t info; mmsound_codec_param_t codec_param; int err = MM_ERROR_NONE; #ifdef DEBUG_DETAIL - debug_enter("\n"); + debug_enter(); #endif - for (count = 0; g_plugins[count].GetSupportTypes; count++) { + for (plugin_id = 0; g_plugins[plugin_id].GetSupportTypes; plugin_id++) { /* Find codec */ - codec_type = g_plugins[count].GetSupportTypes(); - if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0])) + codec_type = g_plugins[plugin_id].GetSupportTypes(); + if (codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0])) break; } /*The count num means codec type DTMF */ - debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count); + debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, plugin_id); - if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */ - debug_error("unsupported file type %d\n", count); - printf("unsupported file type %d\n", count); + if (g_plugins[plugin_id].GetSupportTypes == NULL) { /* Codec not found */ + debug_error("unsupported file type %d\n", plugin_id); + printf("unsupported file type %d\n", plugin_id); err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; goto cleanup; } @@ -715,8 +801,8 @@ int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_p debug_msg("Get New handle\n"); #endif - err = _MMSoundMgrCodecGetEmptySlot(slotid); - if(err != MM_ERROR_NONE || *slotid < 0) + err = _mm_sound_mgr_codec_slot_get_empty(slotid); + if (err != MM_ERROR_NONE || *slotid < 0) { debug_error("Empty g_slot is not found\n"); goto cleanup; @@ -731,48 +817,40 @@ int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_p codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type codec_param.stream_index = param->stream_index; MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN); + SLOT_LOCK(); - pthread_mutex_lock(&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex LOCK\n"); -#endif - g_slots[*slotid].pluginid = count; - g_slots[*slotid].param = param->param; /* This arg is used callback data */ - g_slots[*slotid].enable_session = param->enable_session; + g_slots[*slotid].pluginid = plugin_id; + g_slots[*slotid].param = param->param; /* This arg is used callback data */ + g_slots[*slotid].enable_session = param->enable_session; #ifdef DEBUG_DETAIL - debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status); + debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status); #endif - err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle)); - debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle); - if (err != MM_ERROR_NONE) { - debug_error("Plugin create fail : 0x%08X\n", err); - g_slots[*slotid].status = STATUS_IDLE; - pthread_mutex_unlock(&g_slot_mutex); - debug_warning("After Slot_mutex UNLOCK\n"); - goto cleanup; - } - - err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle); - if (err != MM_ERROR_NONE) { - debug_error("Fail to play : 0x%08X\n", err); - g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle); - } + err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle)); + debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle); + if (err != MM_ERROR_NONE) { + debug_error("Plugin create fail : 0x%08X\n", err); + g_slots[*slotid].status = STATUS_IDLE; + SLOT_UNLOCK(); + goto cleanup; + } - pthread_mutex_unlock(&g_slot_mutex); + err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle); + if (err != MM_ERROR_NONE) { + debug_error("Fail to play : 0x%08X\n", err); + g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle); + } - debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex UNLOCK\n"); -#endif + SLOT_UNLOCK(); + debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status); - cleanup: +cleanup: #ifdef DEBUG_DETAIL - debug_leave("\n"); + debug_leave(); #endif - return err; + return err; } @@ -786,10 +864,7 @@ int MMSoundMgrCodecStop(const int slotid) return MM_ERROR_INVALID_ARGUMENT; } - pthread_mutex_lock (&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex LOCK\n"); -#endif + SLOT_LOCK(); if (g_slots[slotid].status == STATUS_IDLE) { err = MM_ERROR_SOUND_INVALID_STATE; debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid); @@ -799,16 +874,15 @@ int MMSoundMgrCodecStop(const int slotid) debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status); #endif + g_slots[slotid].stop_by_user = true; + err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle); if (err != MM_ERROR_NONE) { debug_error("Fail to STOP Code : 0x%08X\n", err); } - debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status); + cleanup: - pthread_mutex_unlock(&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex UNLOCK\n"); -#endif + SLOT_UNLOCK(); debug_leave("(err : 0x%08X)\n", err); return err; @@ -821,22 +895,25 @@ int MMSoundMgrCodecClearFocus(int pid) debug_enter("(pid : [%d])\n", pid); - pthread_mutex_lock (&g_slot_mutex); + SLOT_LOCK(); for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) { if (g_slots[slotid].pid == pid) { if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) { - if(g_slots[slotid].session_type != MM_SESSION_TYPE_CALL && + if (g_slots[slotid].session_type != MM_SESSION_TYPE_CALL && g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL && g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP && g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION && g_slots[slotid].enable_session ) { - if ((g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || g_slots[slotid].session_type == MM_SESSION_TYPE_ALARM || g_slots[slotid].session_type == MM_SESSION_TYPE_NOTIFY || g_slots[slotid].session_type == MM_SESSION_TYPE_EMERGENCY) { + if ((g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || + g_slots[slotid].session_type == MM_SESSION_TYPE_ALARM || + g_slots[slotid].session_type == MM_SESSION_TYPE_NOTIFY || + g_slots[slotid].session_type == MM_SESSION_TYPE_EMERGENCY) { err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL); if (err) { debug_error("mm_sound_release_focus failed [0x%x]", err); } - if(mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) { + if (mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) { debug_error("Focus clean up failed [0x%x]", err); err = MM_ERROR_POLICY_INTERNAL; goto cleanup; @@ -850,7 +927,7 @@ int MMSoundMgrCodecClearFocus(int pid) } } } - if(mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id) != MM_ERROR_NONE) + if (mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id) != MM_ERROR_NONE) debug_error("mm_sound_remove_device_connected_callback() failed"); g_slots[slotid].focus_handle = 0; g_slots[slotid].focus_wcb_id = 0; @@ -860,7 +937,7 @@ int MMSoundMgrCodecClearFocus(int pid) } cleanup: - pthread_mutex_unlock(&g_slot_mutex); + SLOT_UNLOCK(); debug_leave("(err : 0x%08X)\n", err); return err; @@ -878,8 +955,9 @@ static int _MMSoundMgrCodecStopCallback(int param) return MM_ERROR_INVALID_ARGUMENT; } - pthread_mutex_lock(&g_slot_mutex); - debug_msg("[CODEC MGR] Slot_mutex lock done\n"); + if (g_slots[param].stop_by_user == false) { + SLOT_LOCK(); + } #ifdef FOCUS_INTEGRATION /* @@ -888,116 +966,83 @@ static int _MMSoundMgrCodecStopCallback(int param) debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session); if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) { - if(g_slots[param].session_type != MM_SESSION_TYPE_CALL && + if (g_slots[param].session_type != MM_SESSION_TYPE_CALL && g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL && g_slots[param].session_type != MM_SESSION_TYPE_VOIP && g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION && g_slots[param].enable_session ) { - if ((g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || g_slots[param].session_type == MM_SESSION_TYPE_ALARM || g_slots[param].session_type == MM_SESSION_TYPE_NOTIFY || g_slots[param].session_type == MM_SESSION_TYPE_EMERGENCY) { - if(g_slots[param].current_focus_type != FOCUS_NONE) { + if ((g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || + g_slots[param].session_type == MM_SESSION_TYPE_ALARM || + g_slots[param].session_type == MM_SESSION_TYPE_NOTIFY || + g_slots[param].session_type == MM_SESSION_TYPE_EMERGENCY) { + if (g_slots[param].current_focus_type != FOCUS_NONE) { err = mm_sound_release_focus(g_slots[param].focus_handle, g_slots[param].current_focus_type, NULL); if (err) { debug_error("mm_sound_release_focus failed [0x%x]", err); } } - if(mm_sound_unregister_focus(g_slots[param].focus_handle) || err) { + if (mm_sound_unregister_focus(g_slots[param].focus_handle) || err) { debug_error("Focus clean up failed [0x%x]", err); - pthread_mutex_unlock(&g_slot_mutex); - return MM_ERROR_POLICY_INTERNAL; + err = MM_ERROR_POLICY_INTERNAL; + goto finish; } } else if (~(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) { err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id); if (err) { debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err); - pthread_mutex_unlock(&g_slot_mutex); - return MM_ERROR_POLICY_INTERNAL; + err = MM_ERROR_POLICY_INTERNAL; + goto finish; } } } - if(mm_sound_remove_device_connected_callback(g_slots[param].subs_id) != MM_ERROR_NONE) + if (mm_sound_remove_device_connected_callback(g_slots[param].subs_id) != MM_ERROR_NONE) debug_error("mm_sound_remove_device_connected_callback() failed"); } #endif - __mm_sound_mgr_ipc_notify_play_file_end(param); + if (g_slots[param].stop_by_user == false) { + __mm_sound_mgr_ipc_notify_play_file_end(param); + debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param); + } - debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param); debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle); err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle); - if (err < 0 ) { + if (err < 0) debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err); - } - memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t)); - g_slots[param].status = STATUS_IDLE; - pthread_mutex_unlock(&g_slot_mutex); - debug_msg("[CODEC MGR] Slot_mutex done\n"); - return err; -} - -static int _MMSoundMgrCodecGetEmptySlot(int *slot) -{ - int count = 0; - int err = MM_ERROR_NONE; - -#ifdef DEBUG_DETAIL - debug_enter("\n"); -#endif - debug_msg("Codec slot ID : [%d]\n", *slot); - pthread_mutex_lock(&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex LOCK\n"); -#endif + _mm_sound_mgr_codec_slot_clear(param); + if (_mm_sound_mgr_codec_slot_is_empty()) + _mm_sound_mgr_codec_shutdown_timer_start(); - for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) { - if (g_slots[count].status == STATUS_IDLE) { - g_slots[count].status = STATUS_SOUND; - break; - } +finish: + if (g_slots[param].stop_by_user == false) { + SLOT_UNLOCK(); } - pthread_mutex_unlock(&g_slot_mutex); -#ifdef DEBUG_DETAIL - debug_msg("After Slot_mutex UNLOCK\n"); -#endif - if (count < MANAGER_HANDLE_MAX) { - debug_msg("New handle allocated (codec slot ID : [%d])\n", count); - *slot = count; - err = MM_ERROR_NONE; - } else { - debug_warning("Handle is full handle : [%d]\n", count); - *slot = -1; - /* Temporal code for reset */ - while(count--) { - g_slots[count].status = STATUS_IDLE; - } - err = MM_ERROR_SOUND_INTERNAL; - } - -#ifdef DEBUG_DETAIL - debug_leave("\n"); -#endif + debug_fleave(); return err; } + + static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin) { int err = MM_ERROR_NONE; - int count = 0; + int plugin_id = 0; void *getinterface = NULL; #ifdef DEBUG_DETAIL - debug_enter("\n"); + debug_enter(); #endif /* find emptry slot */ - for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) { - if (g_plugins[count].GetSupportTypes == NULL) + for (plugin_id = 0; plugin_id < MM_SOUND_SUPPORTED_CODEC_NUM; plugin_id++) { + if (g_plugins[plugin_id].GetSupportTypes == NULL) break; } - if (count == MM_SOUND_SUPPORTED_CODEC_NUM) { + if (plugin_id == MM_SOUND_SUPPORTED_CODEC_NUM) { debug_critical("The plugin support type is not valid\n"); return MM_ERROR_COMMON_OUT_OF_RANGE; } @@ -1007,22 +1052,22 @@ static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin) debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err); goto cleanup; } - debug_msg("interface[%p] empty_slot[%d]\n", getinterface, count); + debug_msg("interface[%p] empty_slot[%d]\n", getinterface, plugin_id); - err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]); + err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[plugin_id]); if (err != MM_ERROR_NONE) { debug_error("Get interface fail : %x\n", err); cleanup: /* If error occur, clean interface */ - memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t)); + memset(&g_plugins[plugin_id], 0, sizeof(mmsound_codec_interface_t)); } else { - if (g_plugins[count].SetThreadPool) - g_plugins[count].SetThreadPool(MMSoundThreadPoolRun); + if (g_plugins[plugin_id].SetThreadPool) + g_plugins[plugin_id].SetThreadPool(MMSoundThreadPoolRun); } #ifdef DEBUG_DETAIL - debug_leave("\n"); + debug_leave(); #endif return err; diff --git a/server/mm_sound_mgr_ipc.c b/server/mm_sound_mgr_ipc.c index 89017fe..ec7ac6c 100644 --- a/server/mm_sound_mgr_ipc.c +++ b/server/mm_sound_mgr_ipc.c @@ -49,25 +49,8 @@ int _MMSoundMgrIpcPlayFile(char* filename,int tone, int repeat, int volume, int int *codechandle, char *stream_type, int stream_index) { mmsound_mgr_codec_param_t param = {0,}; - MMSourceType *source = NULL; int ret = MM_ERROR_NONE; - /* Set source */ - source = (MMSourceType*)malloc(sizeof(MMSourceType)); - if (!source) { - debug_error("malloc fail!!\n"); - return MM_ERROR_OUT_OF_MEMORY; - } - - ret = mm_source_open_file(filename, source, MM_SOURCE_CHECK_DRM_CONTENTS); - if(ret != MM_ERROR_NONE) { - debug_error("Fail to open file\n"); - if (source) { - free(source); - } - return ret; - } - /* Set sound player parameter */ param.tone = tone; param.repeat_count = repeat; @@ -76,7 +59,7 @@ int _MMSoundMgrIpcPlayFile(char* filename,int tone, int repeat, int volume, int param.session_type = session_type; param.session_options = session_options; param.param = (void*)client_pid; - param.source = source; + param.pfilename = filename; param.enable_session = enable_session; param.stream_index = stream_index; MMSOUND_STRNCPY(param.stream_type, stream_type, MM_SOUND_STREAM_TYPE_LEN); @@ -91,11 +74,6 @@ int _MMSoundMgrIpcPlayFile(char* filename,int tone, int repeat, int volume, int ret = MMSoundMgrCodecPlay(codechandle, ¶m); if (ret != MM_ERROR_NONE) { debug_error("Will be closed a sources, codechandle : 0x%08X\n", *codechandle); - mm_source_close(source); - if (source) { - free(source); - source = NULL; - } return ret; } @@ -132,45 +110,23 @@ int _MMSoundMgrIpcClearFocus(int pid) } #endif -int _MMSoundMgrIpcPlayFileWithStreamInfo(char* filename, int repeat, int volume, +int _MMSoundMgrIpcPlayFileWithStreamInfo(char *filename, int repeat, int volume, int client_pid, int *codechandle, char *stream_type, int stream_index) { mmsound_mgr_codec_param_t param = {0,}; - MMSourceType *source = NULL; int ret = MM_ERROR_NONE; - /* Set source */ - source = (MMSourceType*)malloc(sizeof(MMSourceType)); - if (!source) { - debug_error("malloc fail!!\n"); - return MM_ERROR_OUT_OF_MEMORY; - } - - ret = mm_source_open_file(filename, source, MM_SOURCE_CHECK_DRM_CONTENTS); - if(ret != MM_ERROR_NONE) { - debug_error("Fail to open file\n"); - if (source) { - free(source); - } - return ret; - } - /* Set sound player parameter */ param.repeat_count = repeat; param.volume = volume; param.param = (void*)client_pid; - param.source = source; + param.pfilename = filename; param.stream_index = stream_index; MMSOUND_STRNCPY(param.stream_type, stream_type, MM_SOUND_STREAM_TYPE_LEN); ret = MMSoundMgrCodecPlayWithStreamInfo(codechandle, ¶m); if (ret != MM_ERROR_NONE) { debug_error("Will be closed a sources, codechandle : 0x%08X\n", *codechandle); - mm_source_close(source); - if (source) { - free(source); - source = NULL; - } return ret; } diff --git a/server/mm_sound_mgr_ipc_dbus.c b/server/mm_sound_mgr_ipc_dbus.c index 145e85e..7bf2242 100644 --- a/server/mm_sound_mgr_ipc_dbus.c +++ b/server/mm_sound_mgr_ipc_dbus.c @@ -226,14 +226,14 @@ static int _get_sender_pid(GDBusMethodInvocation* invocation) connection = g_dbus_method_invocation_get_connection(invocation); sender = g_dbus_method_invocation_get_sender(invocation); - debug_error("connection = %p, sender = %s", connection, sender); + debug_log("connection = %p, sender = %s", connection, sender); value = g_dbus_connection_call_sync(connection, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetConnectionUnixProcessID", g_variant_new("(s)", sender, NULL), NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err); if (value) { g_variant_get(value, "(u)", &pid); - debug_msg("Sender PID = [%d]", pid); + debug_log("Sender PID = [%d]", pid); g_variant_unref(value); } else { debug_error("err code = %d, err msg = %s", err->code, err->message); diff --git a/server/mm_sound_server.c b/server/mm_sound_server.c index 8b15095..615d399 100644 --- a/server/mm_sound_server.c +++ b/server/mm_sound_server.c @@ -29,6 +29,8 @@ #include #include +#include + #include "../include/mm_sound_common.h" #include "include/mm_sound_thread_pool.h" #include "include/mm_sound_mgr_run.h" @@ -40,7 +42,6 @@ #define PLUGIN_ENV "MM_SOUND_PLUGIN_PATH" #define PLUGIN_MAX 30 #define MAX_PLUGIN_DIR_PATH_LEN 256 -#define SHUTDOWN_TIMEOUT_SEC 10 #define USE_SYSTEM_SERVER_PROCESS_MONITORING @@ -63,16 +64,12 @@ static void _exit_handler(int sig); GMainLoop *g_mainloop; -static gboolean _shutdown_timer_cb(gpointer user_data) +static gboolean _shutdown_cb(gpointer user_data) { - if (!IsMMSoundThreadPoolRunning()) { - debug_warning("Thread pool is not running..quit mainloop now!"); - g_main_loop_quit(g_mainloop); - return FALSE; - } + debug_warning("TIMER : quit mainloop now!"); + g_main_loop_quit(g_mainloop); - debug_warning("still running......keep timer..."); - return TRUE; + return FALSE; } static void _mainloop_run() @@ -80,10 +77,9 @@ static void _mainloop_run() g_mainloop = g_main_loop_new(NULL, TRUE); if (g_mainloop == NULL) { debug_error("g_main_loop_new() failed\n"); + return; } - g_timeout_add_seconds(SHUTDOWN_TIMEOUT_SEC, _shutdown_timer_cb, NULL); - g_main_loop_run(g_mainloop); } @@ -217,9 +213,9 @@ int main(int argc, char **argv) if ((pid = fork()) < 0) { fprintf(stderr, "Sub Fork Error\n"); return 2; - } else if(pid == 0) { + } else if (pid == 0) { break; - } else if(pid > 0) { + } else if (pid > 0) { wait(&ret); fprintf(stderr, "Killed by signal [%05X]\n", ret); fprintf(stderr, "Daemon is run againg\n"); @@ -235,7 +231,7 @@ int main(int argc, char **argv) MMSoundMgrDbusInit(); MMSoundThreadPoolInit(); MMSoundMgrRunInit(serveropt.plugdir); - MMSoundMgrCodecInit(serveropt.plugdir); + MMSoundMgrCodecInit(serveropt.plugdir, _shutdown_cb); } debug_warning("sound_server [%d] initialization complete...now, start running!!\n", getpid()); diff --git a/server/mm_sound_thread_pool.c b/server/mm_sound_thread_pool.c index 5b5df31..7434a2c 100644 --- a/server/mm_sound_thread_pool.c +++ b/server/mm_sound_thread_pool.c @@ -27,14 +27,11 @@ #include #include -#define USE_G_THREAD_POOL -#ifdef USE_G_THREAD_POOL #include -GThreadPool* g_pool; -#define MAX_UNUSED_THREADS_IN_THREADPOOL 10 +GThreadPool *g_pool; -#define MIN_RUNNING_THREAD 0 +#define MAX_UNUSED_THREADS_IN_THREADPOOL 10 typedef struct __THREAD_INFO { @@ -42,68 +39,62 @@ typedef struct __THREAD_INFO void *param; } THREAD_INFO; -static void __DummyWork (void* param) +static void __DummyWork(void *param) { - debug_msg ("thread index = %d\n", (int)param); - sleep (1); + debug_msg("thread index = %d\n", (int)param); + sleep(1); } static void __ThreadWork(gpointer data, gpointer user_data) { - THREAD_INFO* info = (THREAD_INFO*)data; + THREAD_INFO *info = (THREAD_INFO *)data; if (info) { - if (info->func) { - debug_log ("Calling [%p] with param [%p]\n", info->func, info->param); - info->func (info->param); - } else { - debug_warning ("No func to call....\n"); - } + if (info->func) { + debug_log("Calling [%p] with param [%p]\n", info->func, info->param); + info->func(info->param); + } else { + debug_warning("No func to call....\n"); + } - /* Info was allocated by MMSoundThreadPoolRun(). + /* Info was allocated by MMSoundThreadPoolRun(). The actual content of info should be freed whether inside func or outside (if handle) */ - debug_log ("free [%p]\n", info); - free (info); - info = NULL; + debug_log ("free [%p]\n", info); + free(info); + info = NULL; } else { - debug_warning ("No valid thread info...Nothing to do...\n"); + debug_warning("No valid thread info...Nothing to do...\n"); } } int MMSoundThreadPoolDump(int fulldump) { if (g_pool == NULL) { - debug_error ("No thread pool initialized....\n"); + debug_error("No thread pool initialized....\n"); return MM_ERROR_SOUND_INTERNAL; } if (fulldump) { - debug_log ("##### [ThreadPool] max threads=[%d], max unused=[%d], max idle time=[%d]\n", + debug_log("##### [ThreadPool] max threads=[%d], max unused=[%d], max idle time=[%d]\n", g_thread_pool_get_max_threads (g_pool), g_thread_pool_get_max_unused_threads(), - g_thread_pool_get_max_idle_time() ); + g_thread_pool_get_max_idle_time()); } - debug_log ("***** [ThreadPool] running=[%d], unused=[%d]\n", + debug_log("***** [ThreadPool] running=[%d], unused=[%d]\n", g_thread_pool_get_num_threads (g_pool), - g_thread_pool_get_num_unused_threads() ); + g_thread_pool_get_num_unused_threads()); return MM_ERROR_NONE; } -gboolean IsMMSoundThreadPoolRunning(void) -{ - MMSoundThreadPoolDump(FALSE); - return (g_thread_pool_get_num_threads(g_pool) > MIN_RUNNING_THREAD); -} - int MMSoundThreadPoolInit() { int i=0; - GError* error = NULL; + GError *error = NULL; /* Create thread pool (non-exclude mode with infinite max threads) */ - g_pool = g_thread_pool_new (__ThreadWork, NULL, -1, FALSE, &error); + g_pool = g_thread_pool_new(__ThreadWork, NULL, -1, FALSE, &error); if (g_pool == NULL && error != NULL) { - debug_error ("thread pool created failed : %s\n", error->message); + debug_error("thread pool created failed : %s\n", error->message); g_error_free (error); return MM_ERROR_SOUND_INTERNAL; } @@ -114,40 +105,40 @@ int MMSoundThreadPoolInit() /* Thread pool setting : this will maintain at least 10 unused threads and this will be reused. */ /* If no unused thread left, new thread will be created, but always maintain 10 unused thread */ debug_msg ("thread pool set max unused threads to %d\n", MAX_UNUSED_THREADS_IN_THREADPOOL); - g_thread_pool_set_max_unused_threads (MAX_UNUSED_THREADS_IN_THREADPOOL); + g_thread_pool_set_max_unused_threads(MAX_UNUSED_THREADS_IN_THREADPOOL); - /* To reserve unused threads, let's start some threads for beggining - This dummy thread will be remained unused as soon as it started */ - debug_msg ("run threads to reserve minimum thread\n"); - for (i=0; ifunc = func; thread_info->param = param; - debug_log ("alloc thread_info = %p\n", thread_info); + debug_log("alloc thread_info = %p\n", thread_info); /* Add thread to queue of thread pool */ - g_thread_pool_push (g_pool, thread_info, &error); + g_thread_pool_push(g_pool, thread_info, &error); if (error) { - debug_error ("g_thread_pool_push failed : %s\n", error->message); - g_error_free (error); + debug_error("g_thread_pool_push failed : %s\n", error->message); + g_error_free(error); free(thread_info); return MM_ERROR_SOUND_INTERNAL; } @@ -168,200 +159,9 @@ int MMSoundThreadPoolFini(void) If wait_ is TRUE, the functions does not return before all tasks to be processed (dependent on immediate, whether all or only the currently running) are ready. - Otherwise the function returns immediately. */ - debug_msg ("thread pool will be free\n"); - g_thread_pool_free (g_pool, TRUE, FALSE); + Otherwise the function returns immediately. */ + debug_msg("thread pool will be free\n"); + g_thread_pool_free(g_pool, TRUE, FALSE); return MM_ERROR_NONE; } - -#else // USE_G_THREAD_POOL - -#define THREAD_POOL_MAX 10 - -struct __control_t -{ - pthread_t threadid; - pthread_cond_t condition; - int stopflag; - void *param; - void (*func)(void *); -}; - -static int threadmap[THREAD_POOL_MAX]; -static struct __control_t control[THREAD_POOL_MAX]; - -static pthread_cond_t startcond = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t startsync = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t controlsync = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t funcsync = PTHREAD_MUTEX_INITIALIZER; - -static int __GetEmptyPool(void) -{ - int count = 0; - while ((count < THREAD_POOL_MAX) && threadmap[count] == 1) - ++count; - return count == THREAD_POOL_MAX ? -1 : count; -} - -static void __SetPool(int n) -{ - threadmap[n] = 1; -} - -static void __ResetPool(int n) -{ - threadmap[n] = 0; -} - -static void __InitPool(void) -{ - int count = 0; - for (count = 0; count < THREAD_POOL_MAX; count++) - { - threadmap[count] = 0; - if (pthread_cond_init(&control[count].condition, NULL) != 0) - perror("Make Thread Condition"); - } -} - -static void __DestroyPool(void) -{ - int count = 0; - for (count = 0; count < THREAD_POOL_MAX; count++) - { - if (pthread_cond_destroy(&control[count].condition) != 0) - { - perror("Remove Thread Condition"); - exit(0); - } - } -} - -static void* __ThreadWork(void *param) -{ - int myid = -1; - - myid = (int)param; - - pthread_mutex_lock(&startsync); - pthread_cond_signal(&startcond); - pthread_mutex_unlock(&startsync); - - while(1) - { - pthread_mutex_lock(&controlsync); - pthread_cond_wait(&control[myid].condition, &controlsync); - pthread_mutex_unlock(&controlsync); - - if (control[myid].func != NULL) - control[myid].func(control[myid].param); -/* if (control[myid].param != NULL) - free(control[myid].param);*/ - - control[myid].func = NULL; - control[myid].param = NULL; - pthread_mutex_lock(&startsync); - __ResetPool(myid); - pthread_mutex_unlock(&startsync); - - if (control[myid].stopflag) { - pthread_exit(0); - } - } -} - -int MMSoundThreadPoolDump(void) -{ - int count = 0; - int ret = MM_ERROR_NONE; - - fprintf(stdout, "================================================================================\n"); - fprintf(stdout, " Thread States \n"); - fprintf(stdout, "--------------------------------------------------------------------------------\n"); - for (count = 0; count < THREAD_POOL_MAX; count ++) - { - fprintf(stdout, "Thread %d\n", control[count].threadid); - fprintf(stdout, "Current State is \"%s\"\n", threadmap[count] ? "Running" : "Ready"); - if (threadmap[count]) - { - fprintf(stdout, "Running function address %p\n", control[count].func); - } - else - { - fprintf(stdout, "Threadmap is NULL\n"); - ret = MM_ERROR_SOUND_INTERNAL; - } - } - fprintf(stdout, "================================================================================\n"); - return ret; -} - -int MMSoundThreadPoolInit(void) -{ - volatile int count = 0; - pthread_mutex_lock(&funcsync); - - __InitPool(); - - for (count = 0; count < THREAD_POOL_MAX; count++) - { - control[count].stopflag = 0; - pthread_mutex_lock(&startsync); - if (pthread_create(&control[count].threadid, NULL, __ThreadWork, (void*)count) < 0) - { - perror("Make Thread Fail"); - exit(0); - } - pthread_cond_wait(&startcond, &startsync); - pthread_mutex_unlock(&startsync); - usleep(100); /* Delay for thread init */ - } - pthread_mutex_unlock(&funcsync); - return MM_ERROR_NONE; -} - -int MMSoundThreadPoolRun(void *param, void (*func)(void*)) -{ - int poolnum = -1; - - pthread_mutex_lock(&funcsync); - pthread_mutex_lock(&startsync); - poolnum = __GetEmptyPool(); - if (poolnum < 0) { - pthread_mutex_unlock(&startsync); - pthread_mutex_unlock(&funcsync); - return MM_ERROR_COMMON_NO_FREE_SPACE; - } - __SetPool(poolnum); - pthread_mutex_unlock(&startsync); - control[poolnum].param = param; - control[poolnum].func = func; - pthread_cond_signal(&control[poolnum].condition); - pthread_mutex_unlock(&funcsync); - - return MM_ERROR_NONE; -} - -int MMSoundThreadPoolFini(void) -{ - int count = 0; - - pthread_mutex_lock(&funcsync); - for (count = 0; count < THREAD_POOL_MAX; count++) - { - control[count].stopflag = 1; - pthread_cond_signal(&control[count].condition); - if (pthread_join(control[count].threadid, NULL) < 0) - { - perror("Join Fail"); - exit(0); - } - } - __DestroyPool(); - pthread_mutex_unlock(&funcsync); - - return MM_ERROR_NONE; -} -#endif // USE_G_THREAD_POOL - diff --git a/server/plugin/Makefile.am b/server/plugin/Makefile.am index f6a7133..f8bb216 100644 --- a/server/plugin/Makefile.am +++ b/server/plugin/Makefile.am @@ -1,6 +1 @@ -if OGG_SUPPORT -SUBDIRS = wav tone ogg -else SUBDIRS = wav tone -endif - diff --git a/server/plugin/ogg/Makefile.am b/server/plugin/ogg/Makefile.am deleted file mode 100644 index f478fac..0000000 --- a/server/plugin/ogg/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -lib_LTLIBRARIES = libsoundplugintremoloogg.la - -libsoundplugintremoloogg_la_SOURCES = \ - mm_sound_plugin_codec_ogg.c - -libsoundplugintremoloogg_la_CFLAGS = \ - $(MMCOMMON_CFLAGS) \ - $(TREMOLO_CFLAGS) \ - -I$(srcdir)/ \ - -I$(srcdir)/../../include \ - -I$(srcdir)/../../../include \ - $(PA_CFLAGS) \ - $(MMLOGSVR_CFLAGS) -DMMF_LOG_OWNER=0x002 -DMMF_DEBUG_PREFIX=\"MMF-SOUND\" - -libsoundplugintremoloogg_la_LIBADD = $(MMCOMMON_LIBS) \ - $(MMLOGSVR_LIBS) \ - $(TREMOLO_LIBS) \ - $(PA_LIBS) \ - $(srcdir)/../../../libmmfsound.la \ - $(srcdir)/../../../common/libmmfsoundcommon.la - -install-exec-hook: - mkdir -p $(DESTDIR)$(libdir)/soundplugins - ln -sf ../libsoundplugintremoloogg.so $(DESTDIR)$(libdir)/soundplugins/libsoundplugintremoloogg.so diff --git a/server/plugin/ogg/mm_sound_plugin_codec_ogg.c b/server/plugin/ogg/mm_sound_plugin_codec_ogg.c deleted file mode 100644 index 805c7a6..0000000 --- a/server/plugin/ogg/mm_sound_plugin_codec_ogg.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * libmm-sound - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Seungbae Shin - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "../../include/mm_sound.h" -#include "../../include/mm_sound_plugin_codec.h" -#include "../../../include/mm_sound_pa_client.h" - -#define OGG_DEC_BUF_SIZE 4096 -#define OGG_FILE_SAMPLE_PLAY_DURATION 290 - -#define TIME_MSEC (1000) -#define SILENT_SND_MIN_VALUE (90) -#define CODEC_OGG_LOCK(LOCK) do { pthread_mutex_lock(LOCK); } while (0) -#define CODEC_OGG_UNLOCK(LOCK) do { pthread_mutex_unlock(LOCK); } while (0) - -int MMSoundPlugCodecOggStop(MMHandleType handle); - -enum { - STATE_NONE = 0, - STATE_READY, - STATE_BEGIN, - STATE_PLAY, - STATE_ENDOFDECORD, - STATE_STOP, -}; - -typedef struct { - /* thread controls */ - sem_t start_wave_signal; /* control start of pcm write thread */ - sem_t start_ogg_signal; /* control start of ogg decord thread*/ - pthread_mutex_t mutex; - - /* Codec infomations */ - void *decoder; - char* pcm_out_buf; - int offset; - int period; - int gain, out, in, option; - mm_sound_device_in device_in; - mm_sound_device_out device_out; - unsigned int volume_value; - - /* Audio Infomations */ - int transper_size; /* audio open return */ - int handle; - - /* control Informations */ - int repeat_count; - int (*stop_cb)(int); - int cb_param; - int state; - MMSourceType *source; - int codec; - int NumberOfChannels; - int SamplingFrequency; - int format; - int Duration; - int BitRate; - int BufferSize; -} ogg_info_t; - -static int (*g_thread_pool_func)(void*, void (*)(void*)) = NULL; - -static void _reset_ogg_decoder(ogg_info_t *p) -{ - int err, used_size, skipsize; - OGG_DEC_INFO ogg_info; - - err = OGGDEC_ResetDecode(p->decoder); - if (err != OGGDEC_SUCCESS) { - debug_error("Failed to RESET decoder!"); - return; - } - - err = OGGDEC_InitDecode(p->decoder, (unsigned char*)p->source->ptr, p->BufferSize, &skipsize); - if (err != OGGDEC_SUCCESS) { - debug_error("Failed to INIT decoder!"); - return; - } - - err = OGGDEC_InfoDecode(p->decoder, p->source->ptr + skipsize, &used_size, &ogg_info); - if (err != OGGDEC_SUCCESS) { - debug_error("Failed to INFO decoder!"); - return; - } -} - -void _pcm_out_func(void *data) -{ - ogg_info_t *p = (ogg_info_t *)data; - int used_size = 0; - int decoded_len = 0; - unsigned char* ogg_buf = NULL; - int err = 0; - - debug_enter(); - - if (!p) { - debug_error("Invalid ogg_info_t..."); - return; - } - - sem_wait(&p->start_wave_signal); - - while (((p->repeat_count == -1) ? (1) : (p->repeat_count--)) && p->state == STATE_PLAY) { - ogg_buf = MMSourceGetPtr(p->source) + p->offset; - - while (p->state == STATE_PLAY) { - decoded_len = 0; - err = OGGDEC_FrameDecode(p->decoder, ogg_buf, &used_size, p->pcm_out_buf, &decoded_len); - if (decoded_len <= 0) { - debug_error("decoded len = %d", decoded_len); - break; - } - - mm_sound_pa_write(p->handle, p->pcm_out_buf, decoded_len); - ogg_buf += used_size; - - if (err != OGGDEC_SUCCESS) - break; - } - - debug_error("decode done = [%d], repeat_count = [%d]", err, p->repeat_count); - if (err == OGGDEC_FAIL || p->repeat_count == 0) - MMSoundPlugCodecOggStop((MMHandleType)p); - else - _reset_ogg_decoder(p); - } - - mm_sound_pa_drain(p->handle); - mm_sound_pa_close(p->handle); - - /* Notice */ - /* OggDestory is called by stop_cb func */ - /* INDEED the stop_cb must be called, after end of all progress */ - if (p->stop_cb) - p->stop_cb(p->cb_param); - - debug_leave(); -} - -int MMSoundPlugCodecOggSetThreadPool(int (*func)(void*, void (*)(void*))) -{ - debug_enter("(func : %p)\n", func); - g_thread_pool_func = func; - debug_leave("\n"); - return MM_ERROR_NONE; -} - -int* MMSoundPlugCodecOggGetSupportTypes(void) -{ - debug_enter("\n"); - static int suported[2] = {MM_SOUND_SUPPORTED_CODEC_OGG, 0}; - debug_leave("\n"); - return suported; -} - -int MMSoundPlugCodecOggParse(MMSourceType *source, mmsound_codec_info_t *info) -{ - unsigned char *ptr = NULL; - unsigned int size = 0; - int err; - OGG_DEC_INFO ogg_info; - - debug_enter("\n"); - - ptr = (unsigned char*)MMSourceGetPtr(source); - size = MMSourceGetCurSize(source); - debug_msg("[CODEC OGG] source ptr :[0x%08X] ::: source size :[0x%d]\n", ptr, size); - - err = OGGDEC_PreparseDecode(ptr, size, &ogg_info); - if (err != OGGDEC_SUCCESS) { - debug_error("Not valid Ogg data format"); - return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; - } - - info->format = 16; - info->channels = ogg_info.channels; - info->samplerate = ogg_info.samplerate; - info->duration = ogg_info.duration; - info->codec = MM_AUDIO_CODEC_OGG; - debug_msg("[CODEC OGG]Channels %d Samplerate %d\n", ogg_info.channels, ogg_info.samplerate); - debug_leave("\n"); - - return MM_ERROR_NONE; -} - -int MMSoundPlugCodecOggCreate(mmsound_codec_param_t *param, mmsound_codec_info_t *info, MMHandleType *handle) -{ - ogg_info_t* p = NULL; - MMSourceType *source = NULL; - OGG_DEC_INFO ogg_info; - int err, used_size, skipsize; - int ret = MM_ERROR_NONE; - - pa_sample_spec ss; - int size = 0; - int mode = HANDLE_MODE_OUTPUT_LOW_LATENCY; - - debug_enter("\n"); - - if (g_thread_pool_func == NULL) { - debug_error("Need thread pool!\n"); - return MM_ERROR_SOUND_INTERNAL; - } - - source = param->source; - debug_msg("[CODEC OGG]Param source p 0x08%X\n", param->source); - - p = (ogg_info_t *) malloc(sizeof(ogg_info_t)); - if (p == NULL) { - debug_error("[CODEC OGG]Memory allocation Fail\n"); - return MM_ERROR_OUT_OF_MEMORY; - } - - memset(p, 0, sizeof(ogg_info_t)); - p->source = param->source; - p->BufferSize = MMSourceGetCurSize(source); - - pthread_mutex_init(&p->mutex, NULL); - - err = sem_init(&p->start_ogg_signal, 0, 0); - if (err == -1) { - debug_error("[CODEC OGG]Semaphore init fail\n"); - ret = MM_ERROR_SOUND_INTERNAL; - goto error_before_create; - } - - err = sem_init(&p->start_wave_signal, 0, 0); - if (err == -1) { - debug_error("[CODEC OGG]Semaphore init fail\n"); - sem_destroy(&p->start_ogg_signal); - ret = MM_ERROR_SOUND_INTERNAL; - goto error_before_create; - } - - err = OGGDEC_CreateDecode(&p->decoder); - if (err != OGGDEC_SUCCESS) { - debug_error("[CODEC OGG]Fail to Create ogg decoder\n"); - ret = MM_ERROR_SOUND_INTERNAL; - goto error_before_create; - } - p->pcm_out_buf = (char *)malloc(sizeof(char)*OGG_DEC_BUF_SIZE); - if (p->pcm_out_buf == NULL) { - debug_error("[CODEC OGG]Memory allocation fail\n"); - ret = MM_ERROR_SOUND_NO_FREE_SPACE; - goto error_after_create; - } - err = OGGDEC_InitDecode(p->decoder, (unsigned char*)p->source->ptr, p->BufferSize, &skipsize); - if (err != OGGDEC_SUCCESS) { - debug_error("Fail to init ogg decoder\n"); - ret = MM_ERROR_SOUND_INTERNAL; - goto error_after_buffer; - } - p->offset = skipsize; - - err = OGGDEC_InfoDecode(p->decoder, p->source->ptr+p->offset, &used_size, &ogg_info); - if (err != OGGDEC_SUCCESS) { - debug_error("[CODEC OGG]Fail to get ogg info\n"); - ret = MM_ERROR_SOUND_INTERNAL; - goto error_after_buffer; - } - p->offset += used_size; - p->Duration = info->duration; - p->format = info->format = 16; - info->channels = ogg_info.channels; - info->samplerate = ogg_info.samplerate; - - /* Temporal code for debug */ - /* - debug_msg("([CODEC OGG]handle %x)\n", p); - debug_msg("[CODEC OGG]Type %s\n", info->codec == MM_AUDIO_CODEC_OGG ? "OGG" : "Unknown"); - debug_msg("[CODEC OGG]channels : %d\n", info->channels); - debug_msg("[CODEC OGG]format : %d\n", info->format); - debug_msg("[CODEC OGG]samplerate : %d\n", info->samplerate); - debug_msg("[CODEC OGG]doffset : %d\n", info->doffset); - debug_msg("[CODEC OGG]repeat : %d\n", param->repeat_count); - debug_msg("[CODEC OGG]volume : %d\n", param->volume); - debug_msg("[CODEC OGG]callback : %08x\n", param->stop_cb); - */ - debug_msg("Audio duration [%d]", info->duration); - p->repeat_count = param ->repeat_count; - p->stop_cb = param->stop_cb; - p->cb_param = param->param; - - if(info->duration < OGG_FILE_SAMPLE_PLAY_DURATION) { - mode = HANDLE_MODE_OUTPUT_LOW_LATENCY; - } else { - mode = HANDLE_MODE_OUTPUT; - } - - switch(info->format) - { - case 8: - ss.format = PA_SAMPLE_U8; - break; - case 16: - ss.format = PA_SAMPLE_S16LE; - break; - default: - ss.format = PA_SAMPLE_S16LE; - break; - } - ss.channels = info->channels; - ss.rate = info->samplerate; - - debug_msg("[CODEC OGG] PARAM mode:[%d] channels:[%d] samplerate:[%d] format:[%d] volume type:[%x]\n", - mode, ss.channels, ss.rate, ss.format, param->volume_config); - - p->handle = mm_sound_pa_open(HANDLE_MODE_OUTPUT_LOW_LATENCY, param->volume_config, &ss, NULL, &size, param->stream_type, param->stream_index); - if(!p->handle) { - debug_error("[CODEC OGG] Can not open audio handle\n"); - ret = MM_ERROR_SOUND_INTERNAL; - goto error_after_buffer; - } - - pthread_mutex_lock(&p->mutex); - p->state = STATE_READY; - pthread_mutex_unlock(&p->mutex); - *handle = p; - - err = g_thread_pool_func(p, _pcm_out_func); - if (err) { - debug_error("[CODEC OGG]pthread_create() fail in pcm thread\n"); - ret = MM_ERROR_SOUND_INTERNAL; - goto error_after_buffer; - } - - debug_leave("\n"); - return MM_ERROR_NONE; - -error_after_buffer: - free(p->pcm_out_buf); - -error_after_create: - sem_destroy(&p->start_ogg_signal); - sem_destroy(&p->start_wave_signal); - OGGDEC_ResetDecode(p->decoder); - OGGDEC_DeleteDecode(p->decoder); - -error_before_create: - free(p); - return ret; -} - -int MMSoundPlugCodecOggPlay(MMHandleType handle) -{ - ogg_info_t *p = (ogg_info_t *) handle; - debug_enter("(handle %x)\n", handle); - - if (p->BufferSize <= 0) { - debug_error("[CODEC OGG]End of file\n"); - return MM_ERROR_END_OF_FILE; - } - pthread_mutex_lock(&p->mutex); - p->state = STATE_PLAY; - pthread_mutex_unlock(&p->mutex); - sem_post(&p->start_wave_signal); - - debug_leave("\n"); - return MM_ERROR_NONE; -} - -int MMSoundPlugCodecOggStop(MMHandleType handle) -{ - ogg_info_t *p = (ogg_info_t *) handle; - debug_enter("(handle %x)\n", handle); - pthread_mutex_lock(&p->mutex); - p->state = STATE_STOP; - pthread_mutex_unlock(&p->mutex); - debug_leave("\n"); - - return MM_ERROR_NONE; -} - -int MMSoundPlugCodecOggDestroy(MMHandleType handle) -{ - ogg_info_t *p = (ogg_info_t*) handle; - int err; - - debug_enter("(handle %x)\n", handle); - - if (!p) { - debug_critical("Confirm the hadle (is NULL)\n"); - err = MM_ERROR_SOUND_INTERNAL; - return err; - } - - if(p->source) { - mm_source_close(p->source); - free(p->source); p->source = NULL; - } - - err = OGGDEC_ResetDecode(p->decoder); - if (err != OGGDEC_SUCCESS) { - debug_error("[CODEC OGG]Codec Reset fail\n"); - err = MM_ERROR_SOUND_INTERNAL; - } - - err = OGGDEC_DeleteDecode(p->decoder); - if (err != OGGDEC_SUCCESS) { - debug_error("[CODEC OGG]Delete Decode fail\n"); - err = MM_ERROR_SOUND_INTERNAL; - } - - sem_destroy(&p->start_wave_signal); - sem_destroy(&p->start_ogg_signal); - - if(p->pcm_out_buf) { - free(p->pcm_out_buf); - p->pcm_out_buf = NULL; - } - - if (p) { - free (p); - p = NULL; - } - - debug_leave("\n"); - return err; -} - -EXPORT_API -int MMSoundGetPluginType(void) -{ - debug_enter("\n"); - debug_leave("\n"); - return MM_SOUND_PLUGIN_TYPE_CODEC; -} - -EXPORT_API -int MMSoundPlugCodecGetInterface(mmsound_codec_interface_t *intf) -{ - debug_enter("\n"); - if (!intf) { - debug_critical("Confirm the codec interface struct (is NULL)\n"); - return MM_ERROR_SOUND_INTERNAL; - } - - intf->GetSupportTypes = MMSoundPlugCodecOggGetSupportTypes; - intf->Parse = MMSoundPlugCodecOggParse; - intf->Create = MMSoundPlugCodecOggCreate; - intf->Destroy = MMSoundPlugCodecOggDestroy; - intf->Play = MMSoundPlugCodecOggPlay; - intf->Stop = MMSoundPlugCodecOggStop; - intf->SetThreadPool = MMSoundPlugCodecOggSetThreadPool; - - debug_leave("\n"); - return MM_ERROR_NONE; -} diff --git a/server/plugin/tone/mm_sound_plugin_codec_tone.c b/server/plugin/tone/mm_sound_plugin_codec_tone.c index 856cbbd..dd427f5 100644 --- a/server/plugin/tone/mm_sound_plugin_codec_tone.c +++ b/server/plugin/tone/mm_sound_plugin_codec_tone.c @@ -756,14 +756,6 @@ int* MMSoundPlugCodecToneGetSupportTypes(void) return suported; } -int MMSoundPlugCodecToneParse(MMSourceType *source, mmsound_codec_info_t *info) -{ - debug_enter("\n"); - // do nothing - debug_leave("\n"); - return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; -} - int MMSoundPlugCodecToneCreate(mmsound_codec_param_t *param, mmsound_codec_info_t *info, MMHandleType *handle) { tone_info_t *toneInfo; @@ -1235,7 +1227,6 @@ int MMSoundPlugCodecGetInterface(mmsound_codec_interface_t *intf) debug_enter("\n"); intf->GetSupportTypes = MMSoundPlugCodecToneGetSupportTypes; - intf->Parse = MMSoundPlugCodecToneParse; intf->Create = MMSoundPlugCodecToneCreate; intf->Destroy = MMSoundPlugCodecToneDestroy; intf->Play = MMSoundPlugCodecTonePlay; diff --git a/server/plugin/wav/Makefile.am b/server/plugin/wav/Makefile.am index 435778b..859d085 100644 --- a/server/plugin/wav/Makefile.am +++ b/server/plugin/wav/Makefile.am @@ -1,19 +1,21 @@ lib_LTLIBRARIES = libsoundpluginwave.la -libsoundpluginwave_la_SOURCES = mm_sound_plugin_codec_wave.c +libsoundpluginwave_la_SOURCES = mm_sound_plugin_codec_wave.c libsoundpluginwave_la_CFLAGS = \ $(MMCOMMON_CFLAGS) \ - -I$(srcdir)/../../../include \ - -I$(srcdir)/../../include \ + -I$(srcdir)/../../../include \ + -I$(srcdir)/../../include \ $(PA_CFLAGS) \ + $(SNDFILE_CFLAGS) \ $(MMLOGSVR_CFLAGS) -DMMF_LOG_OWNER=0x002 -DMMF_DEBUG_PREFIX=\"MMF-SOUND\" libsoundpluginwave_la_LIBADD = $(MMCOMMON_LIBS) \ $(MMLOGSVR_LIBS) \ $(PA_LIBS) \ + $(SNDFILE_LIBS) \ $(srcdir)/../../../libmmfsound.la \ - $(srcdir)/../../../common/libmmfsoundcommon.la + $(srcdir)/../../../common/libmmfsoundcommon.la install-exec-hook: mkdir -p $(DESTDIR)$(libdir)/soundplugins diff --git a/server/plugin/wav/mm_sound_plugin_codec_wave.c b/server/plugin/wav/mm_sound_plugin_codec_wave.c index 7fd61b0..2b67cef 100644 --- a/server/plugin/wav/mm_sound_plugin_codec_wave.c +++ b/server/plugin/wav/mm_sound_plugin_codec_wave.c @@ -24,500 +24,553 @@ #include #include -#include #include #include -#include #include #include "../../include/mm_sound_plugin_codec.h" #include "../../../include/mm_sound_common.h" #include -#define SAMPLE_COUNT 128 -#define WAV_FILE_SAMPLE_PLAY_DURATION 350 /*Unit: ms*/ -enum { - WAVE_CODE_UNKNOWN = 0, - WAVE_CODE_PCM = 1, - WAVE_CODE_ADPCM = 2, - WAVE_CODE_G711 = 3, - WAVE_CODE_IMA_ADPCM = 17, - WAVE_CODE_G723_ADPCM = 20, - WAVE_CODE_GSM = 49, - WAVE_CODE_G721_ADPCM = 64, - WAVE_CODE_MPEG = 80, -}; - -#define MAKE_FOURCC(a, b, c, d) ((a) | (b) << 8) | ((c) << 16 | ((d) << 24)) -#define RIFF_CHUNK_ID ((uint32_t) MAKE_FOURCC('R', 'I', 'F', 'F')) -#define RIFF_CHUNK_TYPE ((uint32_t) MAKE_FOURCC('W', 'A', 'V', 'E')) -#define FMT_CHUNK_ID ((uint32_t) MAKE_FOURCC('f', 'm', 't', ' ')) -#define DATA_CHUNK_ID ((uint32_t) MAKE_FOURCC('d', 'a', 't', 'a')) - -#define CODEC_WAVE_LOCK(LOCK) do { pthread_mutex_lock(LOCK); } while (0) -#define CODEC_WAVE_UNLOCK(LOCK) do { pthread_mutex_unlock(LOCK); } while (0) - -enum { - STATE_NONE = 0, - STATE_READY, - STATE_BEGIN, - STATE_PLAY, - STATE_STOP, -}; +#include +#include typedef struct { - char *ptr_current; - int size; - int transper_size; int handle; - int period; - int tone; - int keytone; int repeat_count; int (*stop_cb)(int); - int cb_param; // slotid - int state; - pthread_mutex_t mutex; - pthread_mutex_t *codec_wave_mutex; - int mode; - int volume_config; - int channels; - int samplerate; - int format; - MMSourceType *source; - char buffer[48000 / 1000 * SAMPLE_COUNT * 2 *2];//segmentation fault when above 22.05KHz stereo - int gain, out, in, option; + char filename[MM_SOUND_MAX_FILENAME]; + int cb_param; char stream_type[MM_SOUND_STREAM_TYPE_LEN]; int stream_index; + + pa_threaded_mainloop *m; + pa_context *c; + pa_stream* s; + pa_sample_spec spec; + SNDFILE* sf; + SF_INFO si; } wave_info_t; -static void _runing(void *param); +static int _sound_prepare(wave_info_t *h) +{ + memset(&h->si, 0, sizeof(SF_INFO)); + + h->sf = sf_open(h->filename, SFM_READ, &h->si); + if (!h->sf) { + debug_error("sf_open error. path(%s), error(%d,%s)", h->filename, sf_error(h->sf), sf_strerror(h->sf)); + return (sf_error(h->sf) == SF_ERR_SYSTEM) ? MM_ERROR_SOUND_INTERNAL : MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; + } + + h->spec.rate = h->si.samplerate; + h->spec.channels = h->si.channels; + h->spec.format = PA_SAMPLE_S16LE; -static int (*g_thread_pool_func)(void*, void (*)(void*)) = NULL; + debug_msg("SF_INFO : frames = %lld, samplerate = %d, channels = %d, format = 0x%X, sections = %d, seekable = %d", + h->si.frames, h->si.samplerate, h->si.channels, h->si.format, h->si.sections, h->si.seekable); -int MMSoundPlugCodecWaveSetThreadPool(int (*func)(void*, void (*)(void*))) + return 0; +} + +static int _sound_rewind(wave_info_t *h) { - debug_enter("(func : %p)\n", func); - g_thread_pool_func = func; - debug_leave("\n"); - return MM_ERROR_NONE; + return (sf_seek(h->sf, 0, SEEK_SET) != -1) ? 0 : -1; } -int* MMSoundPlugCodecWaveGetSupportTypes(void) +static int _sound_is_rewind_needed(wave_info_t *h) { - debug_enter("\n"); - static int suported[2] = {MM_SOUND_SUPPORTED_CODEC_WAVE, 0}; - debug_leave("\n"); - return suported; + return (h->repeat_count == -1 || h->repeat_count > 1); } -int MMSoundPlugCodecWaveParse(MMSourceType *source, mmsound_codec_info_t *info) +static void _sound_unprepare(wave_info_t *h) { - struct __riff_chunk - { - uint32_t chunkid; - uint32_t chunksize; - uint32_t rifftype; - }; - - struct __wave_chunk - { - uint32_t chunkid; - uint32_t chunksize; - uint16_t compression; - uint16_t channels; - uint32_t samplerate; - uint32_t avgbytepersec; - uint16_t blockkalign; - uint16_t bitspersample; - }; - - struct __data_chunk - { - uint32_t chunkid; - uint32_t chunkSize; - }; - - struct __riff_chunk *priff = NULL; - struct __wave_chunk *pwav = NULL; - struct __data_chunk *pdata = NULL; -// struct __fmt_chunk *pfmt = NULL; - - int datalen = -1; - char *data = NULL; - unsigned int tSize; - - debug_enter("\n"); - - data = MMSourceGetPtr(source); - debug_msg("[CODEC WAV] source ptr :[%p]\n", data); - - datalen = MMSourceGetCurSize(source); - debug_msg("[CODEC WAV] source size :[0x%08X]\n", datalen); - - priff = (struct __riff_chunk *) data; - - /* Must be checked, Just for wav or not */ - if (priff->chunkid != RIFF_CHUNK_ID ||priff->rifftype != RIFF_CHUNK_TYPE) - return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; - - if(priff->chunksize != datalen -8) - priff->chunksize = (datalen-8); - - if (priff->chunkid != RIFF_CHUNK_ID ||priff->chunksize != datalen -8 ||priff->rifftype != RIFF_CHUNK_TYPE) { - debug_msg("[CODEC WAV] This contents is not RIFF file\n"); - debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %ld, rifftype : 0x%lx\n", priff->chunkid, priff->chunksize, priff->rifftype); - //debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %d, rifftype : 0x%lx\n", RIFF_CHUNK_ID, datalen-8, RIFF_CHUNK_TYPE); - return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; + if (h->sf) { + sf_close(h->sf); + h->sf = NULL; } +} - debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %ld, rifftype : 0x%lx\n", priff->chunkid, priff->chunksize, priff->rifftype); - //debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %d, rifftype : 0x%lx\n", RIFF_CHUNK_ID, datalen-8, RIFF_CHUNK_TYPE); - - tSize = sizeof(struct __riff_chunk); - pdata = (struct __data_chunk*)(data+tSize); +/* Context Callbacks */ +static void _pa_context_state_callback(pa_context *c, void *userdata) { + pa_threaded_mainloop *m = (pa_threaded_mainloop *)userdata; + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + debug_log("context(%p), state(%d)", c, pa_context_get_state(c)); + break; + + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + debug_warning("context(%p), state(%d)", c, pa_context_get_state(c)); + pa_threaded_mainloop_signal(m, 0); + break; + + default: + break; + } +} - while (pdata->chunkid != FMT_CHUNK_ID && tSize < datalen) { - tSize += (pdata->chunkSize+8); +static void _pa_context_drain_complete_callback(pa_context *c, void *userdata) +{ + pa_context_disconnect(c); +} - if (tSize >= datalen) { - debug_warning("[CODEC WAV] Parsing finished : unable to find the Wave Format chunk\n"); - return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; - } else { - pdata = (struct __data_chunk*)(data+tSize); - } - } - pwav = (struct __wave_chunk*)(data+tSize); - - if (pwav->chunkid != FMT_CHUNK_ID || - pwav->compression != WAVE_CODE_PCM || /* Only supported PCM */ - pwav->avgbytepersec != pwav->samplerate * pwav->blockkalign || - pwav->blockkalign != (pwav->bitspersample >> 3)*pwav->channels) { - debug_msg("[CODEC WAV] This contents is not supported wave file\n"); - debug_msg("[CODEC WAV] chunkid : 0x%lx, comp : 0x%x, av byte/sec : %lu, blockalign : %d\n", pwav->chunkid, pwav->compression, pwav->avgbytepersec, pwav->blockkalign); - return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; +/* Stream Callbacks */ +static void _pa_stream_state_callback(pa_stream *s, void *userdata) +{ + pa_threaded_mainloop *m = (pa_threaded_mainloop *)userdata; + + assert(s); + + switch (pa_stream_get_state(s)) { + case PA_STREAM_CREATING: + debug_log("stream(%p), state(%d)", s, pa_stream_get_state(s)); + break; + case PA_STREAM_READY: + case PA_STREAM_FAILED: + case PA_STREAM_TERMINATED: + debug_warning("stream(%p), state(%d)", s, pa_stream_get_state(s)); + pa_threaded_mainloop_signal(m, 0); + break; + default: + break; } +} - /* Only One data chunk support */ +static void _pa_stream_drain_complete_callback(pa_stream* s, int success, void *userdata) +{ + pa_operation *o = NULL; + wave_info_t *h = (wave_info_t *)userdata; - tSize += (pwav->chunksize+8); - pdata = (struct __data_chunk *)(data+tSize); + debug_msg("drain complete : %p, %d", s, success); - while (pdata->chunkid != DATA_CHUNK_ID && tSize < datalen) { - tSize += (pdata->chunkSize+8); - if (tSize >= datalen) { - debug_warning("[CODEC WAV] Parsing finished : unable to find the data chunk\n"); - return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; - } else { - pdata = (struct __data_chunk*)(data+tSize); - } + if (!success) { + debug_error("drain failed. s(%p), success(%d)", s, success); + //pa_threaded_mainloop_signal(h->m, 0); } - info->codec = MM_SOUND_SUPPORTED_CODEC_WAVE; - info->channels = pwav->channels; - info->format = pwav->bitspersample; - info->samplerate = pwav->samplerate; - info->doffset = (tSize+8); - info->size = pdata->chunkSize; - info->duration = ((info->size)*1000)/pwav->avgbytepersec; - debug_msg("info->size:%d info->duration: %d\n", info->size, info->duration); - - debug_leave("\n"); - return MM_ERROR_NONE; + pa_stream_disconnect(h->s); + pa_stream_unref(h->s); + h->s = NULL; + + if (!(o = pa_context_drain(h->c, _pa_context_drain_complete_callback, h))) + pa_context_disconnect(h->c); + else + pa_operation_unref(o); + + debug_msg("Call stop callback(%p, %p) of mgr_codec", h->stop_cb, h->cb_param); + if (h->stop_cb) + h->stop_cb(h->cb_param); } +static void _pa_stream_moved_callback(pa_stream *s, void *userdata) +{ + assert(s); + debug_msg("stream moved callback : %p", s); +} +static void _pa_stream_underflow_callback(pa_stream *s, void *userdata) +{ + wave_info_t *h = (wave_info_t *)userdata; + assert(s); + + debug_msg("stream underflow callback : %p, file(%s)", s, h->filename); +} -int MMSoundPlugCodecWaveCreate(mmsound_codec_param_t *param, mmsound_codec_info_t *info, MMHandleType *handle) +static void _pa_stream_buffer_attr_callback(pa_stream *s, void *userdata) { - wave_info_t* p = NULL; - MMSourceType *source; - static int keytone_period = 0; + assert(s); + debug_msg("stream underflow callback : %p", s); +} -#ifdef DEBUG_DETAIL - debug_enter("\n"); -#endif +static void _pa_stream_write_callback(pa_stream *s, size_t length, void *userdata) +{ + sf_count_t bytes = 0; + void *data = NULL; + size_t data_length = 0; + size_t frame_size; + pa_operation *o = NULL; + wave_info_t *h = (wave_info_t *)userdata; + + if (!s || length <= 0) { + debug_error("write error. stream(%p), length(%d)", s, length); + return; + } - debug_msg("period[%d] type[%s] ch[%d] format[%d] rate[%d] doffset[%d] repeat[%d] volume[%f] callback[%p]\n", - keytone_period, (info->codec == MM_SOUND_SUPPORTED_CODEC_WAVE) ? "Wave" : "Unknown", - info->channels, info->format, info->samplerate, info->doffset, param->repeat_count, - param->volume, param->stop_cb); - source = param->source; + frame_size = pa_frame_size(&h->spec); + data_length = length; - if (g_thread_pool_func == NULL) { - debug_error("[CODEC WAV] Need thread pool!\n"); - return MM_ERROR_SOUND_INTERNAL; + if (pa_stream_begin_write(s, &data, &data_length) < 0) { + debug_error("failed to pa_stream_begin_write()"); + return; } - p = (wave_info_t *) malloc(sizeof(wave_info_t)); + if ((bytes = sf_readf_short(h->sf, data, (sf_count_t)(data_length / frame_size))) > 0) + bytes *= (sf_count_t)frame_size; - if (p == NULL) { - debug_error("[CODEC WAV] memory allocation failed\n"); - return MM_ERROR_OUT_OF_MEMORY; + debug_log("=== %lld / %d ===",bytes, data_length); + + if (bytes > 0) + pa_stream_write(s, data, (size_t)bytes, NULL, 0, PA_SEEK_RELATIVE); + else + pa_stream_cancel_write(s); + + /* If No more data, drain stream */ + if (bytes < (sf_count_t)data_length) { + debug_msg("EOS!!!!! %lld/%d", bytes, data_length); + + /* Handle loop */ + if (_sound_is_rewind_needed(h)) { + debug_msg("repeat count = %d", h->repeat_count); + h->repeat_count--; + + if (_sound_rewind(h) == 0) + return; + + debug_error("REWIND failed...."); + /* can't loop anymore, fallback and do drain */ + } + + /* EOS callback will be notified after drain is completed */ + pa_stream_set_write_callback(s, NULL, NULL); + o = pa_stream_drain(s, _pa_stream_drain_complete_callback, h); + if (o) + pa_operation_unref(o); } +} - memset(p, 0, sizeof(wave_info_t)); - p->handle = 0; +static int _pa_context_connect(wave_info_t *h) +{ + pa_threaded_mainloop *m = NULL; + pa_context *c = NULL; - p->ptr_current = MMSourceGetPtr(source) + info->doffset; + /* Mainloop */ + if (!(m = pa_threaded_mainloop_new())) { + debug_error("mainloop create failed"); + goto error; + } - p->size = info->size; - p->transper_size = info->samplerate / 1000 * SAMPLE_COUNT * (info->format >> 3) * info->channels; + /* Context */ + if (!(c = pa_context_new(pa_threaded_mainloop_get_api(m), NULL))) { + debug_error("context create failed"); + goto error; + } - p->tone = param->tone; - p->repeat_count = param ->repeat_count; - p->stop_cb = param->stop_cb; - p->cb_param = param->param; - p->source = source; - p->codec_wave_mutex = param->codec_wave_mutex; - p->stream_index = param->stream_index; - MMSOUND_STRNCPY(p->stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN); - // pthread_mutex_init(&p->mutex, NULL); + pa_context_set_state_callback(c, _pa_context_state_callback, m); - debug_msg("[CODEC WAV] transper_size : %d\n", p->transper_size); - debug_msg("[CODEC WAV] size : %d\n", p->size); + pa_threaded_mainloop_lock(m); - if(info->duration < WAV_FILE_SAMPLE_PLAY_DURATION) { - p->mode = HANDLE_MODE_OUTPUT_LOW_LATENCY; - } else { - p->mode = HANDLE_MODE_OUTPUT; + if (pa_threaded_mainloop_start(m) < 0) { + debug_error("mainloop start failed"); + goto error; } - p->volume_config = param->volume_config; - p->channels = info->channels; - p->samplerate = info->samplerate; - - switch(info->format) - { - case 8: - p->format = PA_SAMPLE_U8; - break; - case 16: - p->format = PA_SAMPLE_S16LE; - break; - default: - p->format = PA_SAMPLE_S16LE; - break; + if (pa_context_connect(c, NULL, 0, NULL) < 0) { + debug_error("context connect failed"); + goto error; } - debug_msg("[CODEC WAV] PARAM mode : [%d]\n", p->mode); - debug_msg("[CODEC WAV] PARAM channels : [%d]\n", p->channels); - debug_msg("[CODEC WAV] PARAM samplerate : [%d]\n", p->samplerate); - debug_msg("[CODEC WAV] PARAM format : [%d]\n", p->format); - debug_msg("[CODEC WAV] PARAM volume type : [%x]\n", p->volume_config); + for (;;) { + pa_context_state_t state = pa_context_get_state(c); + if (state == PA_CONTEXT_READY) + break; - p->state = STATE_READY; + if (!PA_CONTEXT_IS_GOOD(state)) { + debug_error("Context error!!!! %d", pa_context_errno(c)); + goto error; + } - g_thread_pool_func(p, _runing); - debug_msg("[CODEC WAV] Thread pool start\n"); - *handle = (MMHandleType)p; + pa_threaded_mainloop_wait(m); + } -#ifdef DEBUG_DETAIL - debug_leave("\n"); -#endif + h->m = m; + h->c = c; - return MM_ERROR_NONE; -} + pa_threaded_mainloop_unlock(m); + + return 0; +error: + if (c) + pa_context_unref(c); -int MMSoundPlugCodecWavePlay(MMHandleType handle) + pa_threaded_mainloop_unlock(m); + + if (m) + pa_threaded_mainloop_free(m); + + return -1; +} + +static int _pa_stream_connect(wave_info_t *h) { - wave_info_t *p = (wave_info_t *) handle; + pa_stream *s = NULL; + pa_proplist *proplist = NULL; + pa_stream_state_t state; + + proplist = pa_proplist_new(); + if (!proplist) + return -1; + if (h->stream_type) + pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, h->stream_type); + if (h->stream_index != -1) + pa_proplist_setf(proplist, PA_PROP_MEDIA_PARENT_ID, "%d", h->stream_index); + + pa_threaded_mainloop_lock(h->m); + + s = pa_stream_new_with_proplist(h->c, "wav-player", &h->spec, NULL, proplist); + pa_proplist_free(proplist); + if (!s) { + debug_error("pa_stream_new failed. file(%s)", h->filename); + goto error; + } + + pa_stream_set_state_callback(s, _pa_stream_state_callback, h->m); + pa_stream_set_write_callback(s, _pa_stream_write_callback, h); + pa_stream_set_moved_callback(s, _pa_stream_moved_callback, h); + pa_stream_set_underflow_callback(s, _pa_stream_underflow_callback, h); + pa_stream_set_buffer_attr_callback(s, _pa_stream_buffer_attr_callback, h); - debug_enter("(handle %x)\n", handle); + pa_stream_connect_playback(s, NULL, NULL, + PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE, + NULL, NULL); + for (;;) { + state = pa_stream_get_state(s); - if (p->size <= 0) { - debug_error("[CODEC WAV] end of file\n"); - return MM_ERROR_END_OF_FILE; + if (state == PA_STREAM_READY) + break; + + if (!PA_STREAM_IS_GOOD(state)) { + debug_error("Stream error!!!! %d", state); + goto error; + } + + /* Wait until the stream is ready */ + pa_threaded_mainloop_wait(h->m); } - debug_msg("[CODEC WAV] send start signal\n"); - p->state = STATE_BEGIN; - debug_leave("\n"); + h->s = s; - return MM_ERROR_NONE; + pa_threaded_mainloop_unlock(h->m); + + return 0; + +error: + if (s) + pa_stream_unref(s); + + pa_threaded_mainloop_unlock(h->m); + + return -1; } -static void _runing(void *param) +static void _pa_stream_uncork(wave_info_t *h) { - wave_info_t *p = (wave_info_t*) param; - int nread = 0; - char *org_cur = NULL; - int org_size = 0; - char *dummy = NULL; - int size; + pa_operation *o = NULL; - pa_sample_spec ss; + assert(h); + assert(h->m); + assert(h->s); - if (p == NULL) { - debug_error("[CODEC WAV] param is null\n"); - return; + pa_threaded_mainloop_lock(h->m); + + if ((o = pa_stream_cork(h->s, 0, NULL, NULL))) + pa_operation_unref(o); + else + debug_error("stream uncork failed"); + + pa_threaded_mainloop_unlock(h->m); +} + +static int _pa_stream_stop_disconnect(wave_info_t *h) +{ + assert(h); + assert(h->m); + + pa_threaded_mainloop_lock(h->m); + if (h->s) { + pa_stream_disconnect(h->s); + pa_stream_unref(h->s); + h->s = NULL; } + if (h->c) { + pa_context_unref(h->c); + h->c = NULL; + } + pa_threaded_mainloop_unlock(h->m); - debug_enter("[CODEC WAV] (Slot ID %d)\n", p->cb_param); - CODEC_WAVE_LOCK(p->codec_wave_mutex); - - ss.rate = p->samplerate; - ss.channels = p->channels; - ss.format = p->format; - p->period = pa_sample_size(&ss) * ((ss.rate * 25) / 1000); - p->handle = mm_sound_pa_open(p->mode, p->volume_config, &ss, NULL, &size, p->stream_type, p->stream_index); - if(!p->handle) { - debug_critical("[CODEC WAV] Can not open audio handle\n"); - CODEC_WAVE_UNLOCK(p->codec_wave_mutex); - return; + pa_threaded_mainloop_free(h->m); + h->m = NULL; + + return 0; +} + +static int* _mm_sound_plug_codec_wave_get_supported_types(void) +{ + static int suported[2] = { MM_SOUND_SUPPORTED_CODEC_WAVE, 0 }; + return suported; +} + +static int _mm_sound_plug_codec_wave_parse(const char *filename, mmsound_codec_info_t *info) +{ + SNDFILE* sf = NULL; + SF_INFO si; + + if (!filename || !info) { + debug_error("filename(%p) or info(%p) is invalid...", filename, info); + return MM_ERROR_INVALID_ARGUMENT; } - if (p->handle == 0) { - debug_critical("[CODEC WAV] audio_handle is not created !! \n"); - CODEC_WAVE_UNLOCK(p->codec_wave_mutex); - free(p); - p = NULL; - return; + /* FIXME : following sndfile code should be encapsulated */ + memset(&si, 0, sizeof(SF_INFO)); + sf = sf_open(filename, SFM_READ, &si); + if (!sf) { + debug_error("sf_open error. path(%s), error(%d, %s)", filename, sf_error(sf), sf_strerror(sf)); + if (sf_error(sf) == SF_ERR_SYSTEM) + return MM_ERROR_SOUND_INTERNAL; + else + return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE; } - /* Set the thread schedule */ - org_cur = p->ptr_current; - org_size = p->size; + info->codec = MM_SOUND_SUPPORTED_CODEC_WAVE; + info->channels = si.channels; + info->samplerate = si.samplerate; - dummy = malloc(p->period); - if(!dummy) { - debug_error("[CODEC WAV] not enough memory"); - CODEC_WAVE_UNLOCK(p->codec_wave_mutex); - return; - } - memset(dummy, 0, p->period); - p->transper_size = p->period; - /* stop_size = org_size > p->period ? org_size : p->period; */ + debug_msg("filename = %s, frames[%lld], samplerate[%d], channels[%d], format[%x], sections[%d], seekable[%d]", + filename, si.frames, si.samplerate, si.channels, si.format, si.sections, si.seekable); + sf_close(sf); - debug_msg("[CODEC WAV] Wait start signal\n"); + return MM_ERROR_NONE; +} - while(p->state == STATE_READY) { - usleep(4); +static int _mm_sound_plug_codec_wave_create(mmsound_codec_param_t *param, mmsound_codec_info_t *info, MMHandleType *handle) +{ + wave_info_t* p = NULL; + int ret = 0; + +#ifdef DEBUG_DETAIL + debug_enter(); +#endif + + p = (wave_info_t *) malloc(sizeof(wave_info_t)); + if (p == NULL) { + debug_error("memory allocation failed"); + return MM_ERROR_OUT_OF_MEMORY; } - debug_msg("[CODEC WAV] Recv start signal\n"); - debug_msg("[CODEC WAV] repeat : %d\n", p->repeat_count); - debug_msg("[CODEC WAV] transper_size : %d\n", p->transper_size); + memset(p, 0, sizeof(wave_info_t)); + p->handle = 0; + p->repeat_count = param ->repeat_count; + p->stop_cb = param->stop_cb; + p->cb_param = param->param; + MMSOUND_STRNCPY(p->filename, param->pfilename, MM_SOUND_MAX_FILENAME); + p->stream_index = param->stream_index; + MMSOUND_STRNCPY(p->stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN); - if (p->state != STATE_STOP) { - debug_msg("[CODEC WAV] Play start\n"); - p->state = STATE_PLAY; - } else { - debug_warning ("[CODEC WAV] state is already STATE_STOP\n"); + ret = _sound_prepare(p); + if (ret < 0) { + debug_error("failed to prepare sound"); + goto error; } - while (((p->repeat_count == -1)?(1):(p->repeat_count--)) && p->state == STATE_PLAY) { - while (p->state == STATE_PLAY && p->size > 0) { - if (p->size >= p->transper_size) { - nread = p->transper_size; - memcpy(p->buffer, p->ptr_current, nread); - mm_sound_pa_write(p->handle, p->buffer, nread); - p->ptr_current += nread; - p->size -= nread; - debug_msg("[CODEC WAV] Playing, nRead_data : %d Size : %d \n", nread, p->size); - } else { - /* Write remain size */ - nread = p->size; - memcpy(p->buffer, p->ptr_current, nread); - mm_sound_pa_write(p->handle, p->buffer, nread); - mm_sound_pa_write(p->handle, dummy, (p->transper_size-nread)); - p->ptr_current += nread; - p->size = 0; - } - } - p->ptr_current = org_cur; - p->size = org_size; + ret = _pa_context_connect(p); + if (ret < 0) { + debug_error("failed to connect context..."); + goto error; } - debug_msg("[CODEC WAV] End playing\n"); - p->state = STATE_STOP; - - if (p->handle == 0) { - usleep(200000); - debug_warning("[CODEC WAV] audio already unrealize !!\n"); - } else { - /* usleep(75000); */ - if(MM_ERROR_NONE != mm_sound_pa_drain(p->handle)) - debug_error("mm_sound_pa_drain() failed\n"); - - if(MM_ERROR_NONE != mm_sound_pa_close(p->handle)) { - debug_error("[CODEC WAV] Can not close audio handle\n"); - } else { - p->handle = 0; - } + ret = _pa_stream_connect(p); + if (ret < 0) { + debug_error("failed to connect stream..."); + goto error; } - CODEC_WAVE_UNLOCK(p->codec_wave_mutex); - p->handle = 0; + *handle = (MMHandleType)p; - p->state = STATE_NONE; +#ifdef DEBUG_DETAIL + debug_leave("%p", p); +#endif + return MM_ERROR_NONE; - free(dummy); dummy = NULL; - if (p->stop_cb) - { - debug_msg("[CODEC WAV] Play is finished, Now start callback\n"); - p->stop_cb(p->cb_param); - } - debug_leave("\n"); +error: + free(p); + return MM_ERROR_SOUND_INTERNAL; } -int MMSoundPlugCodecWaveStop(MMHandleType handle) +static int _mm_sound_plug_codec_wave_play(MMHandleType handle) +{ + wave_info_t *p = (wave_info_t *) handle; + + debug_msg("Start handle %p", p); + _pa_stream_uncork(p); + + return MM_ERROR_NONE; +} + +static int _mm_sound_plug_codec_wave_stop(MMHandleType handle) { + int ret = 0; wave_info_t *p = (wave_info_t*) handle; if (!p) { - debug_error("The handle is null\n"); + debug_error("The handle is null"); return MM_ERROR_SOUND_INTERNAL; } - debug_msg("[CODEC WAV] Current state is state %d\n", p->state); - debug_msg("[CODEC WAV] Handle 0x%08X stop requested\n", handle); - p->state = STATE_STOP; + debug_msg("Handle %p stop requested", p); + + ret = _pa_stream_stop_disconnect(p); + + if (p->stop_cb) + p->stop_cb(p->cb_param); - return MM_ERROR_NONE; + return (ret == 0) ? MM_ERROR_NONE : MM_ERROR_SOUND_INTERNAL; } -int MMSoundPlugCodecWaveDestroy(MMHandleType handle) +static int _mm_sound_plug_codec_wave_destroy(MMHandleType handle) { - wave_info_t *p = (wave_info_t*) handle; + wave_info_t *p = (wave_info_t *)handle; if (!p) { - debug_warning("Can not destroy handle :: handle is invalid"); + debug_error("Can not destroy handle :: handle is invalid"); return MM_ERROR_SOUND_INVALID_POINTER; } - if(p->source) { - mm_source_close(p->source); - free(p->source); p->source = NULL; - } + _sound_unprepare(p); - free(p); p = NULL; + free(p); + p = NULL; return MM_ERROR_NONE; } EXPORT_API -int MMSoundGetPluginType(void) +int MMSoundPlugCodecGetInterface(mmsound_codec_interface_t *intf) { - return MM_SOUND_PLUGIN_TYPE_CODEC; + assert(intf); + + intf->GetSupportTypes = _mm_sound_plug_codec_wave_get_supported_types; + intf->Parse = _mm_sound_plug_codec_wave_parse; + intf->Create = _mm_sound_plug_codec_wave_create; + intf->Play = _mm_sound_plug_codec_wave_play; + intf->Stop = _mm_sound_plug_codec_wave_stop; + intf->Destroy = _mm_sound_plug_codec_wave_destroy; + intf->SetThreadPool = NULL; + + return MM_ERROR_NONE; } EXPORT_API -int MMSoundPlugCodecGetInterface(mmsound_codec_interface_t *intf) +int MMSoundGetPluginType(void) { - intf->GetSupportTypes = MMSoundPlugCodecWaveGetSupportTypes; - intf->Parse = MMSoundPlugCodecWaveParse; - intf->Create = MMSoundPlugCodecWaveCreate; - intf->Destroy = MMSoundPlugCodecWaveDestroy; - intf->Play = MMSoundPlugCodecWavePlay; - intf->Stop = MMSoundPlugCodecWaveStop; - intf->SetThreadPool = MMSoundPlugCodecWaveSetThreadPool; - - return MM_ERROR_NONE; + return MM_SOUND_PLUGIN_TYPE_CODEC; }