Support m360 tag in mp4
[platform/core/multimedia/libmm-fileinfo.git] / formats / ffmpeg / mm_file_format_midi.c
1 /*
2  * libmm-fileinfo
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Haejeong Kim <backto.kim@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 #include <string.h>     /*memcmp*/
23 #include <stdio.h>
24 #include <stdlib.h>     /*malloc*/
25
26 #include "mm_file_debug.h"
27 #include "mm_file_utils.h"
28 #include "mm_file_format_private.h"
29 #include "mm_file_format_midi.h"
30
31 /**
32  * internal defines
33  */
34 enum {
35         AV_DEC_AUDIO_MIDI,
36         AV_DEC_AUDIO_XMF,
37         AV_DEC_AUDIO_RMF,
38 };
39
40 #define MMFILE_XMF_100          "XMF_1.00"
41 #define MMFILE_XMF_101          "XMF_1.01"
42 #define MMFILE_MXMF_200         "XMF_2.00"
43 #define MMFILE_RMF                      "IREZ"
44
45 /*--------------------------------------------------------------------------*/
46 /*   Defines                                                                */
47 /*--------------------------------------------------------------------------*/
48 #define MAX_SMF_MESSAGES                        256                                                     /*                          */
49 #define MAX_SMF_TRACKS                          32                                                      /* Should be <= 32          */
50 #define SMF_MAX_GAIN                            76                                                      /* - 6[dB] : 90             */
51 /* -18[dB] : 45             */
52 #define MINIMUM_LENGTH                          (20)
53
54 #define MELODY_MAP                                      (0)
55 #define DRUM_MAP                                        (1)
56 #define NUM_OF_MAPS                                     (2)
57
58
59 /*--------------------------------------------------------------------------*/
60 /*   Types                                                                  */
61 /*--------------------------------------------------------------------------*/
62
63 typedef struct _tagTrack {
64         unsigned long           dSmfCmd;                                        /* CMD @ now                      */
65         unsigned long           dSize;                                          /* [byte] 0 means nothing in it. */
66         unsigned char           *pbBase;                                                /* NULL means nothing in it.     */
67         unsigned long           dOffset;                                        /* offset byte                    */
68         long                            sdTicks;                                        /*                                */
69 } TRACKINFO, *PTRACKINFO;
70
71 typedef struct _tagOrderList {
72         struct _tagOrderList    *pPrev;
73         struct _tagOrderList    *pNext;
74         unsigned long                   dTrack;
75         unsigned long                   dTicks;
76 } ORDERLIST, *PORDERLIST;
77
78 typedef struct _tagMidInfo {
79         unsigned long           dTimeResolution;                        /* 0..0x7fff                       */
80         unsigned char           *pbText;                                                /*                                 */
81         unsigned long           dSizeText;                                      /*                                 */
82         unsigned char           *pbTitle;                                       /*                                 */
83         unsigned long           dSizeTitle;                                     /*                                 */
84         unsigned char           *pbCopyright;                           /*                                 */
85         unsigned long           dSizeCopyright;                         /*                                 */
86         unsigned long           dNumOfTracks;                           /* 1..32                           */
87         unsigned long           dSmfFormat;                                     /* 0..1                            */
88
89         long            sdTotalTicks;                           /* Total ticks                     */
90         long            sdDataEndTime;                          /* (22.10)[ms]                     */
91
92         unsigned long           dEndFlag;                                       /*                                 */
93         TRACKINFO                       TrackInfo[MAX_SMF_TRACKS];
94
95         struct _tagOrderList    *pTopOrderList;
96         struct _tagOrderList    *pDoneOrderList;
97         struct _tagOrderList    *pBottomOrderList;
98         ORDERLIST                               OrderList[MAX_SMF_TRACKS + 3];
99 } MIDINFO, *PMIDINFO;
100
101 /*---------------------------------------------------------------------------*/
102 /*   Globals                                                                 */
103 /*---------------------------------------------------------------------------*/
104 static PMIDINFO gPi;
105
106 /**
107  * internal midi parsing functions
108  */
109 static bool __AvParseSkipXmf2Mid(unsigned char *pbFile, unsigned long dFSize, unsigned long *skipSize)
110 {
111         unsigned long skipVal;
112
113         for (skipVal = 0; skipVal < dFSize - 3; skipVal++) {
114                 if (pbFile[skipVal] == 'M' &&
115                         pbFile[skipVal + 1] == 'T' &&
116                         pbFile[skipVal + 2] == 'h' &&
117                         pbFile[skipVal + 3] == 'd') {
118                         debug_msg(RELEASE, "__AvParseSkipForXMF : MThd Header found!\n");
119                         *skipSize = skipVal;
120                         return true;
121                 }
122         }
123
124         debug_error(DEBUG, "MThd header not found\n");
125
126         return false;
127 }
128
129 static void __AvMidInitializeOrderList(void)
130 {
131         int idx;
132
133         for (idx = 1; idx <= MAX_SMF_TRACKS + 1; idx++) {
134                 gPi->OrderList[idx].pPrev = &gPi->OrderList[idx - 1];
135                 gPi->OrderList[idx].pNext = &gPi->OrderList[idx + 1];
136                 gPi->OrderList[idx].dTrack = 0xFF;
137                 gPi->OrderList[idx].dTicks = 0xFFFFFFFFL;
138         }
139         gPi->OrderList[0].pPrev = NULL;
140         gPi->OrderList[0].pNext = &gPi->OrderList[1];
141         gPi->OrderList[MAX_SMF_TRACKS + 2].pPrev = &gPi->OrderList[MAX_SMF_TRACKS + 1];
142         gPi->OrderList[MAX_SMF_TRACKS + 2].pNext = NULL;
143         gPi->pTopOrderList = &gPi->OrderList[0];
144         gPi->pDoneOrderList = &gPi->OrderList[1];
145         gPi->pBottomOrderList = &gPi->OrderList[MAX_SMF_TRACKS + 2];
146 }
147
148 static void __AvMidSortOrderList(void)
149 {
150         PORDERLIST pSlot;
151         PORDERLIST pTerget;
152
153         pSlot = (gPi->pTopOrderList)->pNext;
154         (pSlot->pPrev)->pNext = pSlot->pNext;
155         (pSlot->pNext)->pPrev = pSlot->pPrev;
156         pSlot->dTicks = ((unsigned long)gPi->TrackInfo[pSlot->dTrack].sdTicks << 5) + pSlot->dTrack;
157
158         pTerget = pSlot->pNext;
159         while (pTerget != gPi->pDoneOrderList) {
160                 if (pSlot->dTicks <= pTerget->dTicks)
161                         break;
162                 pTerget = pTerget->pNext;
163         }
164
165         (pTerget->pPrev)->pNext = pSlot;
166         pSlot->pPrev = pTerget->pPrev;
167         pTerget->pPrev = pSlot;
168         pSlot->pNext = pTerget;
169 }
170
171 static void __AvMidInsertOrderList(unsigned long dTrack, long sdTicks)
172 {
173         PORDERLIST pTerget;
174
175         if (gPi->dNumOfTracks == 1)
176                 return;
177
178         if (((gPi->dEndFlag >> dTrack) & 0x01) == 0)
179                 return;
180
181         pTerget = gPi->pDoneOrderList->pNext;
182         if (pTerget == gPi->pBottomOrderList)
183                 return;
184
185         gPi->pDoneOrderList->pNext = pTerget->pNext;
186         (pTerget->pNext)->pPrev = gPi->pDoneOrderList;
187
188         pTerget->dTrack = dTrack;
189         pTerget->dTicks = ((unsigned long)sdTicks << 5) + dTrack;
190         pTerget->pPrev = gPi->pTopOrderList;
191         pTerget->pNext = (gPi->pTopOrderList)->pNext;
192         ((gPi->pTopOrderList)->pNext)->pPrev = pTerget;
193         (gPi->pTopOrderList)->pNext = pTerget;
194
195         __AvMidSortOrderList();
196 }
197
198 static void __AvMidRemoveFromOrderList(void)
199 {
200         PORDERLIST pSlot;
201         PORDERLIST pTerget;
202
203         pSlot = (gPi->pTopOrderList)->pNext;
204         (pSlot->pPrev)->pNext = pSlot->pNext;
205         (pSlot->pNext)->pPrev = pSlot->pPrev;
206
207         pTerget = gPi->pBottomOrderList;
208         (pTerget->pPrev)->pNext = pSlot;
209         pSlot->pPrev = pTerget->pPrev;
210         pTerget->pPrev = pSlot;
211         pSlot->pNext = pTerget;
212 }
213
214 static void __AvMidGetTrackTime(unsigned long dTrack)
215 {
216         unsigned long dTemp;
217         long dTime;
218         PTRACKINFO pMt;
219
220         if (((gPi->dEndFlag >> dTrack) & 0x01) == 0)
221                 return;
222
223         pMt = &(gPi->TrackInfo[dTrack]);
224
225         dTime = 0;
226         do {
227                 if (pMt->dOffset >= pMt->dSize) {
228                         gPi->dEndFlag &= ~(1L << dTrack);
229                         return;
230                 }
231                 dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
232                 dTime = (dTime << 7) + (dTemp & 0x7f);
233         } while (dTemp >= 0x80);
234
235         pMt->sdTicks += dTime;
236 }
237
238 static void __AvMidUpdateTrackTime(unsigned long dTrack)
239 {
240         unsigned long dTemp;
241         long dTime;
242         PTRACKINFO pMt;
243
244         if (gPi->dNumOfTracks == 1) {
245                 /* Single track */
246                 if (((gPi->dEndFlag >> dTrack) & 0x01) == 0)
247                         return;
248
249                 pMt = &(gPi->TrackInfo[dTrack]);
250
251                 dTime = 0;
252                 do {
253                         if (pMt->dOffset >= pMt->dSize) {
254                                 gPi->dEndFlag &= ~(1L << dTrack);
255                                 return;
256                         }
257                         dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
258                         dTime = (dTime << 7) + (dTemp & 0x7f);
259                 } while (dTemp >= 0x80);
260
261                 pMt->sdTicks += dTime;
262         } else {
263                 /* Multi track */
264                 if (((gPi->dEndFlag >> dTrack) & 0x01) == 0) {
265                         __AvMidRemoveFromOrderList();
266                         return;
267                 }
268
269                 pMt = &(gPi->TrackInfo[dTrack]);
270
271                 dTime = 0;
272                 do {
273                         if (pMt->dOffset >= pMt->dSize) {
274                                 gPi->dEndFlag &= ~(1L << dTrack);
275                                 __AvMidRemoveFromOrderList();
276                                 return;
277                         }
278                         dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
279                         dTime = (dTime << 7) + (dTemp & 0x7f);
280                 } while (dTemp >= 0x80);
281
282                 pMt->sdTicks += dTime;
283                 __AvMidSortOrderList();
284         }
285 }
286
287 static void __AvMidResetTimeInfo(void)
288 {
289         unsigned long sdTrack;
290         PTRACKINFO pMt;
291
292         gPi->dEndFlag = 0;
293
294         for (sdTrack = 0; sdTrack < gPi->dNumOfTracks; sdTrack++) {
295                 pMt = &(gPi->TrackInfo[sdTrack]);
296
297                 pMt->dSmfCmd = 0;
298                 pMt->dOffset = 0;
299                 pMt->sdTicks = 0;
300                 if (pMt->dSize > 0)
301                         gPi->dEndFlag |= (1L << sdTrack);
302         }
303
304         __AvMidInitializeOrderList();
305
306         if (gPi->dNumOfTracks > MAX_SMF_TRACKS) {
307                 debug_error(DEBUG, "__AvMidResetTimeInfo:  Num of tracks is over MAX track number. !!\n");
308                 return;
309         }
310
311         for (sdTrack = 0; sdTrack < gPi->dNumOfTracks; sdTrack++) {
312                 __AvMidGetTrackTime(sdTrack);
313                 pMt = &(gPi->TrackInfo[sdTrack]);
314                 __AvMidInsertOrderList(sdTrack, pMt->sdTicks);
315         }
316 }
317
318 static bool __AvMidGetLeastTimeTrack(unsigned long *leastTimeTrack)
319 {
320         PORDERLIST      pTerget;
321
322         pTerget = (gPi->pTopOrderList)->pNext;
323         if (pTerget == gPi->pBottomOrderList)
324                 return false;
325
326         *leastTimeTrack = pTerget->dTrack;
327         return true;
328 }
329
330 static void __AvMidInfoInit(void)
331 {
332         gPi->pbText = NULL;
333         gPi->dSizeText = 0;
334         gPi->pbTitle = NULL;
335         gPi->dSizeTitle = 0;
336         gPi->pbCopyright = NULL;
337         gPi->dSizeCopyright = 0;
338 }
339
340 static long __AvGetSizeOfFileInfo(void)
341 {
342         unsigned long dCmd;
343         unsigned long dCmd2;
344         unsigned long dSize;
345
346         unsigned long dTemp;
347         unsigned long dTime;
348         unsigned long sdTotalTicks = 0;
349         long sdCurrentTime = 0;
350         long sdDelta = (unsigned long)(500 << 10) / gPi->dTimeResolution;       /* default=0.5sec */
351
352         unsigned long dSetup = 0;       /* bit0:beat@0, bit1:tempo@0, bit2:GmOn@0, bit3:tempo@1 */
353         PTRACKINFO pMt;
354         unsigned long sdTr;
355
356         long sdNonConductorTime = 0x7FFFFFFF;
357         long sdNonConductorTicks = 0;
358         unsigned long dConductorNote = 0;
359
360         __AvMidInfoInit();
361         __AvMidResetTimeInfo();
362
363         if (gPi->dSmfFormat != 0)
364                 dSetup |= 0x20;
365
366         while (gPi->dEndFlag != 0) {
367                 if ((gPi->dEndFlag == 1) && (sdNonConductorTime == 0x7FFFFFFF)) {
368                         sdNonConductorTime = sdCurrentTime;
369                         sdNonConductorTicks = sdTotalTicks;
370                         dConductorNote |= 2;
371                 }
372
373                 if (gPi->dNumOfTracks == 1) {
374                         sdTr = 0;
375                 } else {
376                         if (!__AvMidGetLeastTimeTrack(&sdTr))
377                                 break;
378                 }
379
380                 mm_file_retvm_if_fails(DEBUG, sdTr < MAX_SMF_TRACKS, -1);
381
382                 pMt = &(gPi->TrackInfo[sdTr]);
383
384                 sdCurrentTime += (pMt->sdTicks - sdTotalTicks) * sdDelta;
385                 sdTotalTicks = pMt->sdTicks;
386                 if ((sdCurrentTime < 0) || (sdTotalTicks > 0x07FFFFFFL))
387                         return -1;
388
389                 dCmd = (unsigned long)pMt->pbBase[pMt->dOffset++];
390
391                 if (dCmd < 0xf0) {
392                         /*--- MidiMsg ---*/
393                         if (dCmd < 0x80) {
394                                 dCmd = pMt->dSmfCmd;
395                                 if (dCmd < 0x80)
396                                         return -1;
397                                 pMt->dOffset--;
398                         } else {
399                                 pMt->dSmfCmd = dCmd;
400                         }
401
402                         switch (dCmd & 0xf0) {
403                         case 0x90:      /* NoteOn */
404                                 /* Conductor Track Note Check */
405                                 if (sdTr == 0)
406                                         dConductorNote |= 1;
407
408                                 pMt->dOffset += 2;
409                                 break;
410
411                         case 0xC0:      /* Program change */
412                                 /* Fall through */
413                         case 0xD0:      /* Channel pressure */
414                                 pMt->dOffset++;
415                                 break;
416
417                         default:
418                                 pMt->dOffset += 2;
419                                 break;
420                         }
421                 } else {
422                         switch (dCmd) {
423                         case 0xF0:                      /* SysEx */
424                                 /* Fall through */
425                         case 0xF7:                      /* SysEx */
426                                 pMt->dSmfCmd = 0;
427                                 dSize = 0;
428                                 do {
429                                         dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
430                                         dSize = (dSize << 7) + (dTemp & 0x7f);
431                                 } while (dTemp >= 0x80);
432
433                                 if ((dSize == 5) &&
434                                         (pMt->pbBase[pMt->dOffset] == 0x7e) &&
435                                         (pMt->pbBase[pMt->dOffset + 1] == 0x7f) &&
436                                         (pMt->pbBase[pMt->dOffset + 2] == 0x09) &&
437                                         (pMt->pbBase[pMt->dOffset + 3] == 0x01)) {
438                                         /* System On */
439                                         if (sdTotalTicks == 0) {
440                                                 dSetup |= 0x04;
441                                         }
442                                 }
443
444                                 pMt->dOffset += dSize;
445                                 break;
446
447                         case 0xF1:                      /* System Msg */
448                                 /* Fall through */
449                         case 0xF3:                      /* System Msg */
450                                 pMt->dOffset++;
451                                 break;
452
453                         case 0xF2:                      /* System Msg */
454                                 pMt->dOffset += 2;
455                                 break;
456
457                         case 0xFF:                                                                                      /* Meta          */
458                                 dCmd2 = (unsigned long)pMt->pbBase[pMt->dOffset++];     /* Meta Command  */
459                                 dSize = 0;                                                                              /* Size          */
460                                 do {
461                                         dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
462                                         dSize = (dSize << 7) + (dTemp & 0x7f);
463                                 } while (dTemp >= 0x80);
464
465                                 switch (dCmd2) {
466                                 case 0x01:      /* Text */
467                                         if (gPi->pbText == NULL) {
468                                                 gPi->pbText = &pMt->pbBase[pMt->dOffset];
469                                                 gPi->dSizeText = dSize;
470                                         }
471                                         break;
472
473                                 case 0x02:      /* Copyright */
474                                         if (gPi->pbCopyright == NULL) {
475                                                 gPi->pbCopyright = &pMt->pbBase[pMt->dOffset];
476                                                 gPi->dSizeCopyright = dSize;
477                                         }
478                                         break;
479
480                                 case 0x06:      /* Title */
481                                         if (gPi->pbTitle == NULL) {
482                                                 gPi->pbTitle = &pMt->pbBase[pMt->dOffset];
483                                                 gPi->dSizeTitle = dSize;
484                                         }
485                                         break;
486
487                                 case 0x2f:              /* End */
488                                         gPi->dEndFlag &= ~(1L << sdTr);
489                                         break;
490
491                                 case 0x51:              /* Set Tempo */
492                                         switch (dSize) {
493                                         case 3:
494                                                 /* Fall through */
495                                         case 4:
496                                                 dTime = ((unsigned long)pMt->pbBase[pMt->dOffset] << 16) +
497                                                                 ((unsigned long)pMt->pbBase[pMt->dOffset + 1] << 8) +
498                                                                 (unsigned long)pMt->pbBase[pMt->dOffset + 2];
499                                                 if ((sdTotalTicks == 0) && (dTime == 250000))
500                                                         dSetup |= 0x02;
501                                                 if (sdTotalTicks == (unsigned long)gPi->dTimeResolution)
502                                                         dSetup |= 0x08;
503
504                                                 sdDelta = (unsigned long)(dTime / (gPi->dTimeResolution > 0 ? gPi->dTimeResolution : 1));
505                                                 break;
506
507                                         default:
508                                                 break;
509                                         }
510                                         break;
511
512                                 case 0x58:              /* Set TimeSignature */
513                                         if ((sdTotalTicks == 0) &&
514                                                 (pMt->pbBase[pMt->dOffset] == 1) &&
515                                                 (pMt->pbBase[pMt->dOffset + 1] == 2)) dSetup |= 0x01;
516                                         break;
517                                 default:
518                                         break;
519                                 }
520                                 pMt->dOffset += dSize;
521                                 break;
522                         default:
523                                 break;
524                         }
525                 }
526
527                 __AvMidUpdateTrackTime(sdTr);
528
529                 if (dSetup == 0x0F) {
530                         dSetup |= 0x10;
531                         sdCurrentTime = 0;
532                 }
533         }
534
535         if ((dConductorNote != 2) || (gPi->dSmfFormat == 0)) {
536                 gPi->sdTotalTicks = sdTotalTicks;
537                 gPi->sdDataEndTime = sdCurrentTime;
538         } else {
539                 gPi->sdTotalTicks = sdNonConductorTicks;
540                 gPi->sdDataEndTime = sdNonConductorTime;
541         }
542
543         if ((gPi->sdDataEndTime >> 10) <= MINIMUM_LENGTH)
544                 return -1;
545
546         return gPi->sdDataEndTime;
547 }
548
549 static long __AvCheckSizeOfMidFile(unsigned char *src_fp, unsigned long dFsize)
550 {
551         unsigned long   dTemp;
552         unsigned long   dSize;
553         unsigned long   dFormat;
554         unsigned long   dNumOfTracks;
555         unsigned long   i;
556         unsigned char *fp = src_fp;
557
558         while (dFsize >= 22) {
559                 dTemp = ((unsigned long)fp[0] << 24) + ((unsigned long)fp[1] << 16) + ((unsigned long)fp[2] << 8) + (unsigned long)fp[3];
560                 if (dTemp == 0x4D546864)
561                         break;          /* 'MThd' */
562                 fp++;
563                 dFsize--;
564         }
565
566         mm_file_retvm_if_fails(DEBUG, dFsize >= 22, -1);
567
568         fp += 4;
569         dFsize -= 4;
570
571         dTemp = ((unsigned long)fp[0] << 24) + ((unsigned long)fp[1] << 16) + ((unsigned long)fp[2] << 8) + (unsigned long)fp[3];
572         mm_file_retvm_if_fails(DEBUG, dTemp == 6, -1);
573
574         fp += 4;
575         dFsize -= 4;
576
577         gPi = g_new0(MIDINFO, 1);
578
579         /*--- Check format -------------------------------------------------*/
580         dFormat = ((unsigned long)fp[0] << 8) + (unsigned long)fp[1];
581         mm_file_retvm_if_fails(DEBUG, dFormat <= 1, -1);
582
583         /*--- Check number of tracks ---------------------------------------*/
584         dNumOfTracks = ((unsigned long)fp[2] << 8) + (unsigned long)fp[3];
585         mm_file_retvm_if_fails(DEBUG, dNumOfTracks > 0, -1);
586         mm_file_retvm_if_fails(DEBUG, dFormat != 0 || dNumOfTracks == 1, -1);
587
588         gPi->dNumOfTracks = (dNumOfTracks > MAX_SMF_TRACKS) ? MAX_SMF_TRACKS : dNumOfTracks;
589
590         /*--- Check Time unit --------------------------------------------*/
591         dTemp = ((unsigned long)fp[4] << 8) + (unsigned long)fp[5];
592         gPi->dTimeResolution = dTemp & 0x7fff;
593         if (((dTemp & 0x8000) != 0) || (gPi->dTimeResolution == 0)) {
594                 debug_error(DEBUG, "__AvCheckSizeOfMidFile Error/ Unknown TimeUnit\n");
595                 return -1;
596         }
597         fp += 6;
598         dFsize -= 6;
599
600         for (i = 0; i < dNumOfTracks; i++) {
601                 /*--- Check chunk name --------------------------------------------*/
602                 while (dFsize >= 8) {
603                         dTemp = ((unsigned long)fp[0] << 24) + ((unsigned long)fp[1] << 16) + ((unsigned long)fp[2] << 8) + (unsigned long)fp[3];
604                         if (dTemp == 0x4D54726B)
605                                 break;  /* 'MTrk' */
606                         fp++;
607                         dFsize--;
608                 }
609
610                 mm_file_retvm_if_fails(DEBUG, dFsize >= 8, -1);
611
612                 /*--- Check size ----------------------------------------------------*/
613                 dSize = ((unsigned long)fp[4] << 24) + ((unsigned long)fp[5] << 16) + ((unsigned long)fp[6] << 8) + (unsigned long)fp[7];
614
615                 if (dFsize < (dSize + 8)) {
616                         debug_error(DEBUG, "__AvCheckSizeOfMidFile Error/ Bad size [%ld] vs [%ld]\n", dFsize, dSize + 22);
617                         return -1;
618                 }
619                 gPi->TrackInfo[i].pbBase = &fp[8];
620                 gPi->TrackInfo[i].dSize = dSize;
621                 fp += (dSize + 8);
622                 dFsize -= (dSize + 8);
623         }
624         gPi->dSmfFormat = dFormat;
625
626         return __AvGetSizeOfFileInfo();
627 }
628
629 static void __AvGetMidiDuration(char *szFileName, MIDI_INFO_SIMPLE *info)
630 {
631         unsigned long xmfheaderSkip = 0;
632         MMFileIOHandle *hFile = NULL;
633         unsigned char *pbFile = NULL;
634         unsigned char *pIMYbuf = NULL;
635         long dFileSize;
636         int     sdCurrentTime = 0;
637         int readn = 0;
638         int codecType = AV_DEC_AUDIO_MIDI;
639         int is_xmf = 0;
640
641         if (!szFileName || !info)
642                 return;
643
644         /*open*/
645         if (mmfile_open(&hFile, szFileName, MMFILE_RDONLY) != MMFILE_UTIL_SUCCESS) {
646                 debug_error(DEBUG, "failed to open\n");
647                 return;
648         }
649
650         /*get file size*/
651         dFileSize = mmfile_get_size(hFile);
652         if (dFileSize <= 0) {
653                 debug_error(DEBUG, "failed to get file size.\n");
654                 goto _RELEASE_RESOURCE;
655         }
656
657         /*alloc read buffer*/
658         pbFile = g_malloc0(dFileSize + 1);
659
660         /*read data*/
661         if ((readn = mmfile_read(hFile, pbFile, dFileSize)) != dFileSize) {
662                 debug_error(DEBUG, "read error. size = %d\n", readn);
663                 goto _RELEASE_RESOURCE;
664         }
665
666         /*check format*/
667         if (dFileSize >= 8 && (!(memcmp(pbFile, MMFILE_XMF_100, 8)) ||
668                 !(memcmp(pbFile, MMFILE_XMF_101, 8)) ||
669                 !(memcmp(pbFile, MMFILE_MXMF_200, 8)))) {
670
671                 is_xmf = 1;
672                 codecType = AV_DEC_AUDIO_XMF;
673         } else if (dFileSize >= 4 && !(memcmp(pbFile, MMFILE_RMF, 4))) {
674                 is_xmf = 0;
675                 codecType = AV_DEC_AUDIO_RMF;
676         } else {
677                 is_xmf = 0;
678                 codecType = AV_DEC_AUDIO_MIDI;
679         }
680
681         /*set output param*/
682         if (codecType == AV_DEC_AUDIO_RMF) {
683                 info->duration = sdCurrentTime = 0;             /*not yet implemented.*/
684                 info->track_num = 1;                                    /*not yet implemented.*/
685                 info->is_xmf = is_xmf;
686         } else {
687                 /*get duration. XMF/MIDI*/
688                 if (codecType ==  AV_DEC_AUDIO_XMF) {
689                         if (!__AvParseSkipXmf2Mid(pbFile, dFileSize, &xmfheaderSkip))
690                                 goto _RELEASE_RESOURCE;
691
692                         sdCurrentTime = __AvCheckSizeOfMidFile(pbFile + xmfheaderSkip, dFileSize);
693                 } else {
694                         sdCurrentTime = __AvCheckSizeOfMidFile(pbFile, dFileSize);
695                 }
696
697                 if (sdCurrentTime < 0) {
698                         debug_error(DEBUG, "__AvGetMidiDuration: sdResult's error Code!(%d)\n", sdCurrentTime);
699                         goto _RELEASE_RESOURCE;
700                 }
701
702                 if (sdCurrentTime > 0)
703                         sdCurrentTime /= 1000;
704
705                 info->duration = sdCurrentTime;
706                 info->track_num = gPi->dNumOfTracks;
707                 info->is_xmf = is_xmf;
708
709                 info->title = g_strndup((const char *)gPi->pbTitle, gPi->dSizeTitle);
710                 info->copyright = g_strndup((const char *)gPi->pbCopyright, gPi->dSizeCopyright);
711                 info->comment = g_strndup((const char *)gPi->pbText, gPi->dSizeText);
712         }
713
714 _RELEASE_RESOURCE:
715         /*resource release*/
716         mmfile_free(gPi);
717         mmfile_close(hFile);
718         mmfile_free(pbFile);
719         mmfile_free(pIMYbuf);
720 }
721
722 /* mm plugin interface */
723 int mmfile_format_read_stream_mid(MMFileFormatContext *formatContext);
724 int mmfile_format_read_frame_mid(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
725 int mmfile_format_read_tag_mid(MMFileFormatContext *formatContext);
726 int mmfile_format_close_mid(MMFileFormatContext *formatContext);
727
728
729 int mmfile_format_open_mid(MMFileFormatContext *formatContext)
730 {
731         mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
732         mm_file_retvm_if_fails(DEBUG, formatContext->uriFileName, MMFILE_FORMAT_FAIL);
733         mm_file_retvm_if_fails(DEBUG, MMFileFormatIsValidMID(NULL, formatContext->uriFileName, 0), MMFILE_FORMAT_FAIL);
734
735         formatContext->ReadStream   = mmfile_format_read_stream_mid;
736         formatContext->ReadFrame    = mmfile_format_read_frame_mid;
737         formatContext->ReadTag      = mmfile_format_read_tag_mid;
738         formatContext->Close        = mmfile_format_close_mid;
739
740         formatContext->videoTotalTrackNum = 0;
741         formatContext->audioTotalTrackNum = 1;
742
743         formatContext->privateFormatData = NULL;
744
745         return MMFILE_FORMAT_SUCCESS;
746 }
747
748 int mmfile_format_read_stream_mid(MMFileFormatContext *formatContext)
749 {
750         MMFileFormatStream *audioStream = NULL;
751         MIDI_INFO_SIMPLE *info = NULL;
752
753         mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
754
755         /*get infomation*/
756         info = mmfile_format_get_midi_infomation(formatContext->uriFileName);
757
758         formatContext->duration = info->duration;
759         formatContext->videoStreamId = -1;
760         formatContext->videoTotalTrackNum = 0;
761         formatContext->audioTotalTrackNum = info->track_num;
762         formatContext->nbStreams = 1;
763
764         audioStream = g_new0(MMFileFormatStream, 1);
765
766         audioStream->streamType = MMFILE_AUDIO_STREAM;
767         audioStream->codecId = (info->is_xmf == 1) ? MM_AUDIO_CODEC_MXMF : MM_AUDIO_CODEC_MIDI;
768         audioStream->bitRate = 0;
769         audioStream->framePerSec = 0;
770         audioStream->width = 0;
771         audioStream->height = 0;
772         audioStream->nbChannel = 1;
773         audioStream->samplePerSec = 0;
774         formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
775
776 #ifdef  __MMFILE_TEST_MODE__
777         mmfile_format_print_contents(formatContext);
778 #endif
779
780         mmfile_format_free_midi_infomation(info);
781         return MMFILE_FORMAT_SUCCESS;
782 }
783
784
785 int mmfile_format_read_tag_mid(MMFileFormatContext *formatContext)
786 {
787         MIDI_INFO_SIMPLE *info = NULL;
788         const char *locale = MMFileUtilGetLocale();
789
790         mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
791
792         /*get infomation*/
793         info = mmfile_format_get_midi_infomation(formatContext->uriFileName);
794
795         /**
796          * UTF8 converting.
797          */
798         if (info->title) {
799                 formatContext->title = mmfile_convert_to_utf8(info->title, strlen(info->title), locale);
800                 if (formatContext->title == NULL) {
801                         debug_warning(DEBUG, "failed to UTF8 convert.\n");
802                         formatContext->title = g_strdup(info->title);
803                 }
804         }
805
806         if (info->copyright) {
807                 formatContext->copyright = mmfile_convert_to_utf8(info->copyright, strlen(info->copyright), locale);
808                 if (formatContext->copyright == NULL) {
809                         debug_warning(DEBUG, "failed to UTF8 convert.\n");
810                         formatContext->copyright = g_strdup(info->copyright);
811                 }
812         }
813
814         if (info->comment) {
815                 formatContext->comment = mmfile_convert_to_utf8(info->comment, strlen(info->comment), locale);
816                 if (formatContext->comment == NULL) {
817                         debug_warning(DEBUG, "failed to UTF8 convert.\n");
818                         formatContext->comment = g_strdup(info->comment);
819                 }
820         }
821
822 #ifdef  __MMFILE_TEST_MODE__
823         mmfile_format_print_contents(formatContext);
824 #endif
825
826         mmfile_format_free_midi_infomation(info);
827         return MMFILE_FORMAT_SUCCESS;
828 }
829
830
831 int mmfile_format_read_frame_mid(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
832 {
833         debug_error(DEBUG, "error: mmfile_format_read_frame_midi, no handling\n");
834
835         return MMFILE_FORMAT_FAIL;
836 }
837
838
839 int mmfile_format_close_mid(MMFileFormatContext *formatContext)
840 {
841         mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
842         mmfile_free(formatContext->streams[MMFILE_AUDIO_STREAM]);
843
844         formatContext->ReadStream   = NULL;
845         formatContext->ReadFrame    = NULL;
846         formatContext->ReadTag      = NULL;
847         formatContext->Close        = NULL;
848
849         return MMFILE_FORMAT_SUCCESS;
850 }
851
852 MIDI_INFO_SIMPLE * mmfile_format_get_midi_infomation(char *szFileName)
853 {
854         MIDI_INFO_SIMPLE *info = g_new0(MIDI_INFO_SIMPLE, 1);
855
856         __AvGetMidiDuration(szFileName, info);
857
858         return info;
859 }
860
861 void mmfile_format_free_midi_infomation(MIDI_INFO_SIMPLE *info)
862 {
863         if (info) {
864                 mmfile_free(info->title);
865                 mmfile_free(info->copyright);
866                 mmfile_free(info->comment);
867                 mmfile_free(info);
868         }
869 }