Tizen 2.0 Release
[profile/ivi/libmm-sound.git] / common / mm_source.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/mman.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31
32 #include "mm_types.h"
33 #include "mm_debug.h"
34 #include "mm_error.h"
35 #include "mm_source.h"
36
37
38 bool _is_drm_file(
39         const char       *filePath
40 )
41 {
42         if(!filePath || filePath[0] == '\0')
43         {
44                 debug_error("invalid argument\n");
45                 return false;
46         }
47         char *p = NULL;
48         p = (char*) strrchr(filePath, '.');
49
50         if( p &&  ((strncasecmp(p, ".odf", 4) == 0) || (strncasecmp(p, ".dcf", 4) == 0) || (strncasecmp(p, ".o4a", 4) == 0) || (strncasecmp(p, ".o4v", 4) == 0)))
51         {
52         return true;
53         }
54         return false;
55 }
56
57 EXPORT_API
58 int mm_source_open_file(const char *filename, MMSourceType *source, int drmsupport)
59 {
60         struct stat finfo = {0, };
61         int fd = -1;
62         void *mmap_buf = NULL;
63
64         if(filename == NULL)
65         {
66                 debug_error("filename is null\n");
67                 return MM_ERROR_SOUND_INVALID_FILE;
68         }
69         if(drmsupport)
70         {
71                 if(_is_drm_file(filename))
72                 {
73                         debug_error("%s is DRM contents\n", filename);
74                         return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
75                 }
76         }
77
78         fd = open(filename, O_RDONLY);
79         debug_fenter();
80         debug_msg("Open file name is %s\n", filename);
81     unsigned int mediaSize,readSize,offSet=0;
82         char genStr[20],i; 
83                 
84         if (fd == -1)
85         {
86                 debug_error("file open fail\n\n");
87                 return MM_ERROR_SOUND_INTERNAL;
88         }
89         if (fstat(fd, &finfo) == -1)
90         {
91                 debug_error("file get info fail\n");
92                 close(fd);
93                 return MM_ERROR_SOUND_INTERNAL;
94         }
95
96         mediaSize = (unsigned int)finfo.st_size;
97         
98     {
99                 /* get the extension (3 characters from last including NULL)*/
100                 strncpy((void *)genStr,(void *)(filename+(strlen(filename)-2)),3);      
101                 
102                 debug_msg("ExtName of the Sound file %s\n",genStr);
103
104                 
105                 if(strcasecmp (genStr, "dm") == 0)
106                 {
107                         debug_msg("It is DM file going ahead with special decoding\n");
108
109                         /* Vlidation of the DM file */
110                         readSize = read(fd,(void*)genStr,0x8);
111                         if(readSize != 0x8)
112                         {
113                                 debug_error("Error in Reading the file Header %x/0x8\n",readSize);
114                                 return MM_ERROR_SOUND_INTERNAL;
115                         }
116
117                         genStr[readSize] ='\0';
118                         
119                         debug_msg("Header details of DM file %s\n",genStr);
120                         
121                         if(strcasecmp (genStr, "--random") != 0)
122                         {
123                                 debug_error("It is not a valied DM file");
124                                 return MM_ERROR_SOUND_INTERNAL;
125                         }
126
127                         /*checking the Media Type */
128                         readSize = lseek(fd, 0x32, SEEK_SET);
129                         if(readSize != 0x32)
130                         {
131                                 debug_error("Error in Seeking the file to offset %x/0x32\n",readSize);
132                                 return MM_ERROR_SOUND_INTERNAL;
133                         }
134                                 
135                         readSize = read(fd,(void*)genStr,0xf);
136
137                         for(i=0;i<0xf;i++)
138                         {
139                                 if(genStr[i] == (char)0xD)
140                                 {
141                                         genStr[i] ='\0';
142                                         break;
143                                 }
144                         }
145                         
146                         debug_msg("Header details of DM file %s\n",genStr);
147
148                         /*Finding the Media Offset */
149                         
150                         if(strcasecmp (genStr, "audio/mpeg") == 0)
151                         {
152                                 offSet = 0x63;
153                         }
154                         else if(strcasecmp (genStr, "audio/wav") == 0)
155                         {
156                                 offSet = 0x62;
157                         }
158                         else
159                         {
160                                 debug_error("It is not MP3/Wav DM file \n");
161                                 return MM_ERROR_SOUND_INTERNAL;
162                         }
163
164                         /*Finding the Media Size */
165                         
166                         mediaSize -= (offSet + 0x28);
167                         
168                         /*Seeking the file to start */
169                         readSize = lseek(fd, 0x0, SEEK_SET);
170                         
171                         if( readSize != 0x0)
172                         {
173                                 debug_error("Error in Seeking the file to offset %x/0x32\n",readSize);
174                                 return MM_ERROR_SOUND_INTERNAL;
175                         }
176
177                 }
178                 else
179                 {
180                         debug_msg("It is NON DM file going ahead with normal decoding\n");
181                 }
182         }
183
184         mmap_buf  = mmap(0, finfo.st_size, PROT_READ, MAP_SHARED, fd,0);
185         
186         if (mmap_buf == NULL)
187         {
188                 debug_error("MMAP fail\n");
189                 close(fd);
190                 return MM_ERROR_SOUND_INTERNAL;
191         }
192         source->ptr = mmap_buf+offSet;
193         source->medOffset = offSet;
194         debug_msg("source ptr = %p\n", source->ptr);
195         debug_msg("Med Offset Size : %d",source->medOffset);
196         source->tot_size = finfo.st_size;
197         source->cur_size = mediaSize;
198         source->type = MM_SOURCE_FILE;
199         source->fd = fd;
200
201         return MM_ERROR_NONE;
202 }
203
204 EXPORT_API
205 int mm_source_open_full_memory(const void *ptr, int totsize, int alloc, MMSourceType *source)
206 {
207         int err = MM_ERROR_NONE;
208         if (ptr == NULL)
209         {
210                 debug_error("PTR is NULL\n");
211                 return MM_ERROR_INVALID_ARGUMENT;
212         }
213         if (alloc)
214         {
215                 err = mm_source_open_memory(ptr, totsize, totsize, source);
216         }
217         else
218         {
219             source->ptr = ptr;
220             source->tot_size = totsize;
221             source->cur_size = totsize;
222
223             source->type = MM_SOURCE_MEMORY_NOTALLOC;
224             source->fd = -1;
225         }
226     return err;
227 }
228
229 EXPORT_API
230 int mm_source_open_memory(const void *ptr, int totsize, int size, MMSourceType *source)
231 {
232     source->ptr = (unsigned char*) malloc(totsize);
233     if (source->ptr == NULL)
234     {
235         debug_error("memory alloc fail\n");
236         return MM_ERROR_SOUND_NO_FREE_SPACE;
237     }
238     source->tot_size = totsize;
239     source->cur_size = 0;
240     source->type = MM_SOURCE_MEMORY;
241     source->fd = -1;
242
243     return mm_source_append_memory(ptr, size, source);
244 }
245
246 EXPORT_API
247 int mm_source_append_memory(const void *ptr, int size, MMSourceType *source)
248 {
249     if (source->cur_size + size > source->tot_size)
250     {
251         debug_error("memory too large\n");
252         return MM_ERROR_SOUND_NO_FREE_SPACE;
253     }
254
255     memcpy(source->ptr + source->cur_size, ptr, size);
256     source->cur_size += size;
257     return MM_ERROR_NONE;
258 }
259
260 EXPORT_API
261 int mm_source_close(MMSourceType *source)
262 {
263     debug_fenter();
264
265     ////PREVENT
266     if(source == NULL)
267     {
268         debug_critical("source is null %s\n", __func__);
269         return MM_ERROR_CLASS;
270     }
271     /////
272         debug_msg("Source type = %d\n", source->type);
273     switch(source->type)
274     {
275         case MM_SOURCE_FILE:
276                 if(source->ptr != NULL)
277                 {
278                         source->ptr -= source->medOffset;
279                                 debug_msg("Med Offset Size : %d/%d",source->medOffset,source->tot_size);
280                         if (munmap(source->ptr, source->tot_size) == -1) {
281                                 debug_error("MEM UNMAP fail\n\n");
282                         }
283                 }
284             close(source->fd);
285             break;
286         case MM_SOURCE_MEMORY:
287                 if(source->ptr != NULL)
288                         free(source->ptr);
289             break;
290         case MM_SOURCE_MEMORY_NOTALLOC:
291             break;
292         default:
293             debug_critical("Unknown Source\n");
294             break;
295     }
296     memset(source, 0, sizeof(MMSourceType));
297     return MM_ERROR_NONE;
298 }
299