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
+++ /dev/null
-/*
- * libmm-sound
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: Seungbae Shin <seungbae.shin@samsung.com>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#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;
-}
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
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
server/Makefile
server/plugin/Makefile
server/plugin/wav/Makefile
-server/plugin/ogg/Makefile
server/plugin/tone/Makefile
focus_server/Makefile
pkgconfig/Makefile
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);
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;
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)) {
+++ /dev/null
-/*
- * libmm-sound
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: Seungbae Shin <seungbae.shin@samsung.com>
- *
- * 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__ */
-
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
%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
./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 \
%{_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}
#include <stdbool.h>
-#include <mm_source.h>
#include <mm_sound_stream.h>
#include "../../include/mm_sound.h"
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;
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);
#define __MM_SOUND_PLUGIN_CODEC_H__
#include "mm_sound_plugin.h"
-#include <mm_source.h>
#include <mm_types.h>
#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 */
};
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;
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);
int MMSoundThreadPoolDump(int fulldump);
int MMSoundThreadPoolInit(void);
-gboolean IsMMSoundThreadPoolRunning(void);
int MMSoundThreadPoolRun(void *param, void (*func)(void*));
int MMSoundThreadPoolFini(void);
#include <stdio.h>
#include <string.h>
#include <pthread.h>
+#include <unistd.h>
+#include <errno.h>
-#include <mm_source.h>
#include <mm_error.h>
#include <mm_types.h>
#include <mm_debug.h>
#include <mm_ipc.h>
#include <mm_session.h>
+#include <glib.h>
+
#include "include/mm_sound_mgr_common.h"
#include "include/mm_sound_mgr_codec.h"
#include "include/mm_sound_mgr_ipc.h"
#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 {
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;
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");
}
}
- 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;
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
/*
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;
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;
}
}
#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;
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;
#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;
}
}
#endif
+
#ifdef DEBUG_DETAIL
- debug_leave("\n");
+ debug_leave();
#endif
return err;
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;
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;
}
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;
#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;
#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;
}
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;
}
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
//
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;
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;
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
#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
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;
}
#endif
#ifdef DEBUG_DETAIL
- debug_leave("\n");
+ debug_leave();
#endif
return err;
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;
}
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;
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;
}
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);
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;
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;
}
}
}
- 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;
}
cleanup:
- pthread_mutex_unlock(&g_slot_mutex);
+ SLOT_UNLOCK();
debug_leave("(err : 0x%08X)\n", err);
return err;
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
/*
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;
}
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;
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;
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);
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;
}
}
#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;
}
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);
#include <mm_error.h>
#include <mm_debug.h>
+#include <glib.h>
+
#include "../include/mm_sound_common.h"
#include "include/mm_sound_thread_pool.h"
#include "include/mm_sound_mgr_run.h"
#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
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()
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);
}
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");
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());
#include <mm_debug.h>
#include <mm_sound_thread_pool.h>
-#define USE_G_THREAD_POOL
-#ifdef USE_G_THREAD_POOL
#include <glib.h>
-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
{
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;
}
/* 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; i<MAX_UNUSED_THREADS_IN_THREADPOOL; i++) {
- MMSoundThreadPoolRun ((void *)i, __DummyWork);
+ /* To reserve unused threads, let's start some threads for beginning
+ his dummy thread will be remained unused as soon as it started */
+ debug_msg("run threads to reserve minimum thread\n");
+ for (i = 0; i < MAX_UNUSED_THREADS_IN_THREADPOOL; i++) {
+ MMSoundThreadPoolRun((void *)i, __DummyWork);
}
MMSoundThreadPoolDump(TRUE);
- return MM_ERROR_NONE;
+ return MM_ERROR_NONE;
}
int MMSoundThreadPoolRun(void *param, void (*func)(void*))
{
- GError* error = NULL;
+ GError *error = NULL;
/* Dump current thread pool */
MMSoundThreadPoolDump(FALSE);
/* Create thread info structure.
This thread info data will be free in __ThreadWork(), after use. */
- THREAD_INFO* thread_info = (THREAD_INFO*)malloc (sizeof(THREAD_INFO));
+ THREAD_INFO *thread_info = (THREAD_INFO *)malloc(sizeof(THREAD_INFO));
if (thread_info) {
thread_info->func = 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;
}
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
-
-if OGG_SUPPORT
-SUBDIRS = wav tone ogg
-else
SUBDIRS = wav tone
-endif
-
+++ /dev/null
-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
+++ /dev/null
-/*
- * libmm-sound
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: Seungbae Shin <seungbae.shin@samsung.com>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <semaphore.h>
-#include <pthread.h>
-
-#include <mm_error.h>
-#include <mm_debug.h>
-#include <tremolo_vorbisdec_api.h>
-
-#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;
-}
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;
debug_enter("\n");
intf->GetSupportTypes = MMSoundPlugCodecToneGetSupportTypes;
- intf->Parse = MMSoundPlugCodecToneParse;
intf->Create = MMSoundPlugCodecToneCreate;
intf->Destroy = MMSoundPlugCodecToneDestroy;
intf->Play = MMSoundPlugCodecTonePlay;
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
#include <string.h>
#include <stdint.h>
-#include <semaphore.h>
#include <mm_error.h>
#include <mm_debug.h>
-#include <pthread.h>
#include <mm_sound_pa_client.h>
#include "../../include/mm_sound_plugin_codec.h"
#include "../../../include/mm_sound_common.h"
#include <unistd.h>
-#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 <sndfile.h>
+#include <pulse/pulseaudio.h>
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;
}