summaryrefslogtreecommitdiff
path: root/common/mm_source.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/mm_source.c')
-rw-r--r--common/mm_source.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/common/mm_source.c b/common/mm_source.c
new file mode 100644
index 0000000..059e7f4
--- /dev/null
+++ b/common/mm_source.c
@@ -0,0 +1,272 @@
+/*
+ * 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,readSize,offSet=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) {
+ debug_error("file [%s] open fail\n", filename);
+ 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);
+
+ 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;
+}