4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Haejeong Kim <backto.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <string.h> /*memcmp*/
24 #include <stdlib.h> /*malloc*/
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"
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"
45 /*--------------------------------------------------------------------------*/
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 */
52 #define MINIMUM_LENGTH (20)
54 #define MELODY_MAP (0)
56 #define NUM_OF_MAPS (2)
59 /*--------------------------------------------------------------------------*/
61 /*--------------------------------------------------------------------------*/
62 typedef struct _tagMidChInfo {
63 unsigned long dKeyCon; /* 0:Melady, 1:OFF, 2:ON */
64 unsigned long dLedSync; /* 0:OFF, 1:ON */
65 unsigned long dVibSync; /* 0:OFF, 1:ON */
66 } MIDCHINFO, *PMIDCHINFO;
68 typedef struct _tagTrack {
69 unsigned long dSmfCmd; /* CMD @ now */
70 unsigned long dSize; /* [byte] 0 measns nothing in it. */
71 unsigned char *pbBase; /* NULL measns nothing in it. */
72 unsigned long dOffset; /* offset byte */
74 } TRACKINFO, *PTRACKINFO;
76 typedef struct _tagOrderList {
77 struct _tagOrderList *pPrev;
78 struct _tagOrderList *pNext;
81 } ORDERLIST, *PORDERLIST;
83 typedef struct _tagMidInfo {
84 unsigned long dTimeResolution; /* 0..0x7fff */
85 unsigned char *pbText; /* */
86 unsigned long dSizeText; /* */
87 unsigned char *pbTitle; /* */
88 unsigned long dSizeTitle; /* */
89 unsigned char *pbCopyright; /* */
90 unsigned long dSizeCopyright; /* */
91 unsigned long dNumOfTracks; /* 1..32 */
92 unsigned long dSmfFormat; /* 0..1 */
93 unsigned long dSetupBar; /* 0:No, 1:Yes */
94 unsigned long dStart; /* Index after SetupBar */
95 unsigned long dVibNoteVoice; /* 0:No, 1:Yes */
97 long sdTotalTicks; /* Total ticks */
98 long sdDataEndTime; /* (22.10)[ms] */
100 unsigned long dEndFlag; /* */
101 TRACKINFO TrackInfo[MAX_SMF_TRACKS];
103 struct _tagOrderList *pTopOrderList;
104 struct _tagOrderList *pDoneOrderList;
105 struct _tagOrderList *pBottomOrderList;
106 ORDERLIST OrderList[MAX_SMF_TRACKS + 3];
108 MIDCHINFO ChInfo[16]; /* */
109 unsigned long dValid; /* 0:none, 1:Valid */
110 unsigned char bVoiceMap[NUM_OF_MAPS][128];/* 0:Empty, 1:Valid */
111 } MIDINFO, *PMIDINFO;
113 /*---------------------------------------------------------------------------*/
115 /*---------------------------------------------------------------------------*/
119 * internal midi parsing functions
121 static bool __AvParseSkipXmf2Mid(unsigned char *pbFile, unsigned long dFSize, unsigned long *skipSize)
123 unsigned long skipVal;
125 for (skipVal = 0; skipVal < dFSize - 3; skipVal++) {
126 if (pbFile[skipVal] == 'M' &&
127 pbFile[skipVal + 1] == 'T' &&
128 pbFile[skipVal + 2] == 'h' &&
129 pbFile[skipVal + 3] == 'd') {
130 debug_msg(RELEASE, "__AvParseSkipForXMF : MThd Header found!\n");
136 debug_error(DEBUG, "MThd header not found\n");
141 static void __AvMidInitializeOrderList(void)
145 for (idx = 1; idx <= MAX_SMF_TRACKS + 1; idx++) {
146 gPi->OrderList[idx].pPrev = &gPi->OrderList[idx - 1];
147 gPi->OrderList[idx].pNext = &gPi->OrderList[idx + 1];
148 gPi->OrderList[idx].dTrack = 0xFF;
149 gPi->OrderList[idx].dTicks = 0xFFFFFFFFL;
151 gPi->OrderList[0].pPrev = NULL;
152 gPi->OrderList[0].pNext = &gPi->OrderList[1];
153 gPi->OrderList[MAX_SMF_TRACKS + 2].pPrev = &gPi->OrderList[MAX_SMF_TRACKS + 1];
154 gPi->OrderList[MAX_SMF_TRACKS + 2].pNext = NULL;
155 gPi->pTopOrderList = &gPi->OrderList[0];
156 gPi->pDoneOrderList = &gPi->OrderList[1];
157 gPi->pBottomOrderList = &gPi->OrderList[MAX_SMF_TRACKS + 2];
160 static void __AvMidSortOrderList(void)
165 pSlot = (gPi->pTopOrderList)->pNext;
166 (pSlot->pPrev)->pNext = pSlot->pNext;
167 (pSlot->pNext)->pPrev = pSlot->pPrev;
168 pSlot->dTicks = ((unsigned long)gPi->TrackInfo[pSlot->dTrack].sdTicks << 5) + pSlot->dTrack;
170 pTerget = pSlot->pNext;
171 while (pTerget != gPi->pDoneOrderList) {
172 if (pSlot->dTicks <= pTerget->dTicks)
174 pTerget = pTerget->pNext;
177 (pTerget->pPrev)->pNext = pSlot;
178 pSlot->pPrev = pTerget->pPrev;
179 pTerget->pPrev = pSlot;
180 pSlot->pNext = pTerget;
183 static void __AvMidInsertOrderList(unsigned long dTrack, long sdTicks)
187 if (gPi->dNumOfTracks == 1)
190 if (((gPi->dEndFlag >> dTrack) & 0x01) == 0)
193 pTerget = gPi->pDoneOrderList->pNext;
194 if (pTerget == gPi->pBottomOrderList)
197 gPi->pDoneOrderList->pNext = pTerget->pNext;
198 (pTerget->pNext)->pPrev = gPi->pDoneOrderList;
200 pTerget->dTrack = dTrack;
201 pTerget->dTicks = ((unsigned long)sdTicks << 5) + dTrack;
202 pTerget->pPrev = gPi->pTopOrderList;
203 pTerget->pNext = (gPi->pTopOrderList)->pNext;
204 ((gPi->pTopOrderList)->pNext)->pPrev = pTerget;
205 (gPi->pTopOrderList)->pNext = pTerget;
207 __AvMidSortOrderList();
210 static void __AvMidRemoveFromOrderList(void)
215 pSlot = (gPi->pTopOrderList)->pNext;
216 (pSlot->pPrev)->pNext = pSlot->pNext;
217 (pSlot->pNext)->pPrev = pSlot->pPrev;
219 pTerget = gPi->pBottomOrderList;
220 (pTerget->pPrev)->pNext = pSlot;
221 pSlot->pPrev = pTerget->pPrev;
222 pTerget->pPrev = pSlot;
223 pSlot->pNext = pTerget;
226 static void __AvMidGetTrackTime(unsigned long dTrack)
232 if (((gPi->dEndFlag >> dTrack) & 0x01) == 0)
235 pMt = &(gPi->TrackInfo[dTrack]);
239 if (pMt->dOffset >= pMt->dSize) {
240 gPi->dEndFlag &= ~(1L << dTrack);
243 dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
244 dTime = (dTime << 7) + (dTemp & 0x7f);
245 } while (dTemp >= 0x80);
247 pMt->sdTicks += dTime;
250 static void __AvMidUpdateTrackTime(unsigned long dTrack)
256 if (gPi->dNumOfTracks == 1) {
258 if (((gPi->dEndFlag >> dTrack) & 0x01) == 0)
261 pMt = &(gPi->TrackInfo[dTrack]);
265 if (pMt->dOffset >= pMt->dSize) {
266 gPi->dEndFlag &= ~(1L << dTrack);
269 dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
270 dTime = (dTime << 7) + (dTemp & 0x7f);
271 } while (dTemp >= 0x80);
273 pMt->sdTicks += dTime;
276 if (((gPi->dEndFlag >> dTrack) & 0x01) == 0) {
277 __AvMidRemoveFromOrderList();
281 pMt = &(gPi->TrackInfo[dTrack]);
285 if (pMt->dOffset >= pMt->dSize) {
286 gPi->dEndFlag &= ~(1L << dTrack);
287 __AvMidRemoveFromOrderList();
290 dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
291 dTime = (dTime << 7) + (dTemp & 0x7f);
292 } while (dTemp >= 0x80);
294 pMt->sdTicks += dTime;
295 __AvMidSortOrderList();
299 static void __AvMidResetTimeInfo(void)
301 unsigned long sdTrack;
306 for (sdTrack = 0; sdTrack < gPi->dNumOfTracks; sdTrack++) {
307 pMt = &(gPi->TrackInfo[sdTrack]);
313 gPi->dEndFlag |= (1L << sdTrack);
316 __AvMidInitializeOrderList();
318 if (gPi->dNumOfTracks > MAX_SMF_TRACKS) {
319 debug_error(DEBUG, "__AvMidResetTimeInfo: Num of tracks is over MAX track number. !!\n");
323 for (sdTrack = 0; sdTrack < gPi->dNumOfTracks; sdTrack++) {
324 __AvMidGetTrackTime(sdTrack);
325 pMt = &(gPi->TrackInfo[sdTrack]);
326 __AvMidInsertOrderList(sdTrack, pMt->sdTicks);
330 static bool __AvMidGetLeastTimeTrack(unsigned long *leastTimeTrack)
334 pTerget = (gPi->pTopOrderList)->pNext;
335 if (pTerget == gPi->pBottomOrderList)
338 *leastTimeTrack = pTerget->dTrack;
342 static long __AvGetSizeOfFileInfo(void)
350 unsigned long sdTotalTicks;
356 unsigned long dSetup; /* bit0:beat@0, bit1:tempo@0, bit2:GmOn@0, bit3:tempo@1 */
360 static unsigned long dBank[16];
361 static unsigned long dCurrBank[16];
363 long sdNonConductorTime;
364 long sdNonConductorTicks;
365 unsigned long dConductorNote;
369 sdNonConductorTime = 0x7FFFFFFF;
370 sdNonConductorTicks = 0;
372 sdDelta = (unsigned long)(500 << 10) / gPi->dTimeResolution; /* default=0.5sec */
378 gPi->pbCopyright = NULL;
379 gPi->dSizeCopyright = 0;
382 gPi->dVibNoteVoice = 0;
384 for (dCh = 0; dCh < NUM_OF_MAPS; dCh++) {
385 for (dTemp = 0; dTemp < 128; dTemp++) {
386 gPi->bVoiceMap[dCh][dTemp] = 0;
389 gPi->bVoiceMap[MELODY_MAP][0] = 1; /* GM Default Piano */
391 for (dCh = 0; dCh < 16; dCh++) {
394 pCh = &gPi->ChInfo[dCh];
400 __AvMidResetTimeInfo();
402 if (gPi->dSmfFormat != 0)
405 while (gPi->dEndFlag != 0) {
406 if ((gPi->dEndFlag == 1) && (sdNonConductorTime == 0x7FFFFFFF)) {
407 sdNonConductorTime = sdCurrentTime;
408 sdNonConductorTicks = sdTotalTicks;
412 if (gPi->dNumOfTracks == 1) {
415 if (!__AvMidGetLeastTimeTrack(&sdTr))
419 if (sdTr >= MAX_SMF_TRACKS) {
420 debug_error(DEBUG, "__AvGetSizeOfFileInfo: Num of tracks is over MAX track number. !!\n");
424 pMt = &(gPi->TrackInfo[sdTr]);
426 dTime = pMt->sdTicks - sdTotalTicks;
427 sdCurrentTime += dTime * sdDelta;
428 sdTotalTicks = pMt->sdTicks;
429 if ((sdCurrentTime < 0) || (sdTotalTicks > 0x07FFFFFFL))
432 dCmd = (unsigned long)pMt->pbBase[pMt->dOffset++];
447 switch (dCmd & 0xf0) {
448 case 0x90: /* NoteOn */
449 /* Conductor Track Note Check */
452 switch (dCurrBank[dCh] >> 8) {
459 gPi->bVoiceMap[DRUM_MAP][pMt->pbBase[pMt->dOffset] & 0x7F] = 1;
464 /* Unknown: default GM Drum */
465 gPi->bVoiceMap[DRUM_MAP][pMt->pbBase[pMt->dOffset] & 0x7F] = 1;
471 case 0xC0: /* Program change */
472 switch (dBank[dCh] >> 8) {
474 if (dBank[dCh] != 0x7906) {
476 gPi->bVoiceMap[MELODY_MAP][pMt->pbBase[pMt->dOffset] & 0x7F] = 1;
479 gPi->dVibNoteVoice = 1;
488 /* default GM Melody */
490 gPi->bVoiceMap[MELODY_MAP][pMt->pbBase[pMt->dOffset] & 0x7F] = 1;
494 dCurrBank[dCh] = dBank[dCh];
498 case 0xD0: /* Channel pressure */
502 case 0xB0: /* Control Change */
503 switch (pMt->pbBase[pMt->dOffset]) {
504 case 0x00: /* Bank select(MSB) */
505 dBank[dCh] = (dBank[dCh] & 0x00FF) | (pMt->pbBase[pMt->dOffset + 1] << 8);
508 case 0x20: /* Bank select (LSB) */
509 dBank[dCh] = (dBank[dCh] & 0xFF00) | pMt->pbBase[pMt->dOffset + 1];
523 case 0xF0: /* SysEx */
524 case 0xF7: /* SysEx */
528 dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
529 dSize = (dSize << 7) + (dTemp & 0x7f);
530 } while (dTemp >= 0x80);
533 (pMt->pbBase[pMt->dOffset] == 0x7e) &&
534 (pMt->pbBase[pMt->dOffset + 1] == 0x7f) &&
535 (pMt->pbBase[pMt->dOffset + 2] == 0x09) &&
536 (pMt->pbBase[pMt->dOffset + 3] == 0x01)) {
538 if (sdTotalTicks == 0) {
542 if (gPi->dSetupBar == 0) {
544 (pMt->pbBase[pMt->dOffset] == 0x43) &&
545 (pMt->pbBase[pMt->dOffset + 1] == 0x79) &&
546 (pMt->pbBase[pMt->dOffset + 2] == 0x06) &&
547 (pMt->pbBase[pMt->dOffset + 3] == 0x7C) &&
548 (pMt->pbBase[pMt->dOffset + 4] == 0x02)) {
550 for (dCh = 0; dCh < 16; dCh++) {
551 pCh = &gPi->ChInfo[dCh];
552 dTemp = pMt->pbBase[pMt->dOffset + 5 + dCh];
553 pCh->dKeyCon = (dTemp >> 2) & 0x03;
554 pCh->dVibSync = (dTemp >> 1) & 0x01;
555 pCh->dLedSync = dTemp & 0x01;
561 pMt->dOffset += dSize;
564 case 0xF1: /* System Msg */
565 case 0xF3: /* System Msg */
569 case 0xF2: /* System Msg */
573 case 0xFF: /* Meta */
574 dCmd2 = (unsigned long)pMt->pbBase[pMt->dOffset++]; /* Meta Command */
575 dSize = 0; /* Size */
577 dTemp = (unsigned long)pMt->pbBase[pMt->dOffset++];
578 dSize = (dSize << 7) + (dTemp & 0x7f);
579 } while (dTemp >= 0x80);
582 case 0x01: /* Text */
583 if (gPi->pbText == NULL) {
584 gPi->pbText = &pMt->pbBase[pMt->dOffset];
585 gPi->dSizeText = dSize;
589 case 0x02: /* Copyright */
590 if (gPi->pbCopyright == NULL) {
591 gPi->pbCopyright = &pMt->pbBase[pMt->dOffset];
592 gPi->dSizeCopyright = dSize;
596 case 0x06: /* Title */
597 if (gPi->pbTitle == NULL) {
598 gPi->pbTitle = &pMt->pbBase[pMt->dOffset];
599 gPi->dSizeTitle = dSize;
604 gPi->dEndFlag &= ~(1L << sdTr);
607 case 0x51: /* Set Tempo */
611 dTime = ((unsigned long)pMt->pbBase[pMt->dOffset] << 16) +
612 ((unsigned long)pMt->pbBase[pMt->dOffset + 1] << 8) +
613 (unsigned long)pMt->pbBase[pMt->dOffset + 2];
614 if ((sdTotalTicks == 0) && (dTime == 250000)) dSetup |= 0x02;
615 if (sdTotalTicks == (unsigned long)gPi->dTimeResolution) dSetup |= 0x08;
617 sdDelta = (unsigned long)(dTime / (gPi->dTimeResolution > 0 ? gPi->dTimeResolution : 1));
625 case 0x58: /* Set TimeSignature */
626 if ((sdTotalTicks == 0) &&
627 (pMt->pbBase[pMt->dOffset] == 1) &&
628 (pMt->pbBase[pMt->dOffset + 1] == 2)) dSetup |= 0x01;
633 pMt->dOffset += dSize;
640 __AvMidUpdateTrackTime(sdTr);
642 if (dSetup == 0x0F) {
646 gPi->dStart = gPi->TrackInfo[0].dOffset;
650 if ((dConductorNote != 2) || (gPi->dSmfFormat == 0)) {
651 gPi->sdTotalTicks = sdTotalTicks;
652 gPi->sdDataEndTime = sdCurrentTime;
654 gPi->sdTotalTicks = sdNonConductorTicks;
655 gPi->sdDataEndTime = sdNonConductorTime;
658 if (gPi->dSetupBar == 0) {
659 for (dCh = 0; dCh < 16; dCh++) {
660 pCh = &gPi->ChInfo[dCh];
666 if ((gPi->sdDataEndTime >> 10) <= MINIMUM_LENGTH)
669 return gPi->sdDataEndTime;
672 static long __AvCheckSizeOfMidFile(unsigned char *src_fp, unsigned long dFsize)
676 unsigned long dFormat;
677 unsigned long dNumOfTracks;
679 unsigned char *fp = src_fp;
681 while (dFsize >= 22) {
682 dTemp = ((unsigned long)fp[0] << 24) + ((unsigned long)fp[1] << 16) + ((unsigned long)fp[2] << 8) + (unsigned long)fp[3];
683 if (dTemp == 0x4D546864)
689 mm_file_retvm_if_fails(DEBUG, dFsize >= 22, -1);
694 dTemp = ((unsigned long)fp[0] << 24) + ((unsigned long)fp[1] << 16) + ((unsigned long)fp[2] << 8) + (unsigned long)fp[3];
695 mm_file_retvm_if_fails(DEBUG, dTemp == 6, -1);
700 gPi = g_new0(MIDINFO, 1);
702 /*--- Check format -------------------------------------------------*/
703 dFormat = ((unsigned long)fp[0] << 8) + (unsigned long)fp[1];
704 mm_file_retvm_if_fails(DEBUG, dFormat <= 1, -1);
706 /*--- Check number of tracks ---------------------------------------*/
707 dNumOfTracks = ((unsigned long)fp[2] << 8) + (unsigned long)fp[3];
708 mm_file_retvm_if_fails(DEBUG, dNumOfTracks > 0, -1);
709 mm_file_retvm_if_fails(DEBUG, dFormat != 0 || dNumOfTracks == 1, -1);
711 gPi->dNumOfTracks = (dNumOfTracks > MAX_SMF_TRACKS) ? MAX_SMF_TRACKS : dNumOfTracks;
713 /*--- Check Time unit --------------------------------------------*/
714 dTemp = ((unsigned long)fp[4] << 8) + (unsigned long)fp[5];
715 gPi->dTimeResolution = dTemp & 0x7fff;
716 if (((dTemp & 0x8000) != 0) || (gPi->dTimeResolution == 0)) {
717 debug_error(DEBUG, "__AvCheckSizeOfMidFile Error/ Unknown TimeUnit\n");
723 for (i = 0; i < dNumOfTracks; i++) {
724 /*--- Check chunk name --------------------------------------------*/
725 while (dFsize >= 8) {
726 dTemp = ((unsigned long)fp[0] << 24) + ((unsigned long)fp[1] << 16) + ((unsigned long)fp[2] << 8) + (unsigned long)fp[3];
727 if (dTemp == 0x4D54726B)
733 mm_file_retvm_if_fails(DEBUG, dFsize >= 8, -1);
735 /*--- Check size ----------------------------------------------------*/
736 dSize = ((unsigned long)fp[4] << 24) + ((unsigned long)fp[5] << 16) + ((unsigned long)fp[6] << 8) + (unsigned long)fp[7];
738 if (dFsize < (dSize + 8)) {
739 debug_error(DEBUG, "__AvCheckSizeOfMidFile Error/ Bad size [%ld] vs [%ld]\n", dFsize, dSize + 22);
742 gPi->TrackInfo[i].pbBase = &fp[8];
743 gPi->TrackInfo[i].dSize = dSize;
745 dFsize -= (dSize + 8);
747 gPi->dSmfFormat = dFormat;
749 return __AvGetSizeOfFileInfo();
752 static void __AvGetMidiDuration(char *szFileName, MIDI_INFO_SIMPLE *info)
754 unsigned long xmfheaderSkip = 0;
755 MMFileIOHandle *hFile = NULL;
756 unsigned char *pbFile = NULL;
757 unsigned char *pIMYbuf = NULL;
759 int sdCurrentTime = 0;
761 int codecType = AV_DEC_AUDIO_MIDI;
764 if (!szFileName || !info)
768 if (mmfile_open(&hFile, szFileName, MMFILE_RDONLY) != MMFILE_UTIL_SUCCESS) {
769 debug_error(DEBUG, "failed to open\n");
774 dFileSize = mmfile_get_size(hFile);
775 if (dFileSize <= 0) {
776 debug_error(DEBUG, "failed to get file size.\n");
777 goto _RELEASE_RESOURCE;
780 /*alloc read buffer*/
781 pbFile = g_malloc0(dFileSize + 1);
784 if ((readed = mmfile_read(hFile, pbFile, dFileSize)) != dFileSize) {
785 debug_error(DEBUG, "read error. size = %d\n", readed);
786 goto _RELEASE_RESOURCE;
790 if (!(memcmp(pbFile, MMFILE_XMF_100, 8)) ||
791 !(memcmp(pbFile, MMFILE_XMF_101, 8)) ||
792 !(memcmp(pbFile, MMFILE_MXMF_200, 8))) {
795 codecType = AV_DEC_AUDIO_XMF;
796 } else if (!(memcmp(pbFile, MMFILE_RMF, 4))) {
798 codecType = AV_DEC_AUDIO_RMF;
801 codecType = AV_DEC_AUDIO_MIDI;
805 if (codecType == AV_DEC_AUDIO_RMF) {
806 info->duration = sdCurrentTime = 0; /*not yet implemented.*/
807 info->track_num = 1; /*not yet implemented.*/
808 info->is_xmf = is_xmf;
810 /*get duration. XMF/MIDI*/
811 if (codecType == AV_DEC_AUDIO_XMF) {
812 if (!__AvParseSkipXmf2Mid(pbFile, dFileSize, &xmfheaderSkip))
813 goto _RELEASE_RESOURCE;
815 sdCurrentTime = __AvCheckSizeOfMidFile(pbFile + xmfheaderSkip, dFileSize);
817 sdCurrentTime = __AvCheckSizeOfMidFile(pbFile, dFileSize);
820 if (sdCurrentTime < 0) {
821 debug_error(DEBUG, "__AvGetMidiDuration: sdResult's error Code!(%d)\n", sdCurrentTime);
822 goto _RELEASE_RESOURCE;
825 if (sdCurrentTime > 0)
826 sdCurrentTime /= 1000;
828 info->duration = sdCurrentTime;
829 info->track_num = gPi->dNumOfTracks;
830 info->is_xmf = is_xmf;
832 info->title = g_strndup((const char *)gPi->pbTitle, gPi->dSizeTitle);
833 info->copyright = g_strndup((const char *)gPi->pbCopyright, gPi->dSizeCopyright);
834 info->comment = g_strndup((const char *)gPi->pbText, gPi->dSizeText);
842 mmfile_free(pIMYbuf);
845 /* mm plugin interface */
846 int mmfile_format_read_stream_mid(MMFileFormatContext *formatContext);
847 int mmfile_format_read_frame_mid(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
848 int mmfile_format_read_tag_mid(MMFileFormatContext *formatContext);
849 int mmfile_format_close_mid(MMFileFormatContext *formatContext);
852 int mmfile_format_open_mid(MMFileFormatContext *formatContext)
854 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
855 mm_file_retvm_if_fails(DEBUG, formatContext->uriFileName, MMFILE_FORMAT_FAIL);
856 mm_file_retvm_if_fails(DEBUG, MMFileFormatIsValidMID(NULL, formatContext->uriFileName, 0), MMFILE_FORMAT_FAIL);
858 formatContext->ReadStream = mmfile_format_read_stream_mid;
859 formatContext->ReadFrame = mmfile_format_read_frame_mid;
860 formatContext->ReadTag = mmfile_format_read_tag_mid;
861 formatContext->Close = mmfile_format_close_mid;
863 formatContext->videoTotalTrackNum = 0;
864 formatContext->audioTotalTrackNum = 1;
866 formatContext->privateFormatData = NULL;
868 return MMFILE_FORMAT_SUCCESS;
871 int mmfile_format_read_stream_mid(MMFileFormatContext *formatContext)
873 MMFileFormatStream *audioStream = NULL;
874 MIDI_INFO_SIMPLE *info = NULL;
876 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
879 info = mmfile_format_get_midi_infomation(formatContext->uriFileName);
881 formatContext->duration = info->duration;
882 formatContext->videoStreamId = -1;
883 formatContext->videoTotalTrackNum = 0;
884 formatContext->audioTotalTrackNum = info->track_num;
885 formatContext->nbStreams = 1;
887 audioStream = g_new0(MMFileFormatStream, 1);
889 audioStream->streamType = MMFILE_AUDIO_STREAM;
890 audioStream->codecId = (info->is_xmf == 1) ? MM_AUDIO_CODEC_MXMF : MM_AUDIO_CODEC_MIDI;
891 audioStream->bitRate = 0;
892 audioStream->framePerSec = 0;
893 audioStream->width = 0;
894 audioStream->height = 0;
895 audioStream->nbChannel = 1;
896 audioStream->samplePerSec = 0;
897 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
899 #ifdef __MMFILE_TEST_MODE__
900 mmfile_format_print_contents(formatContext);
903 mmfile_format_free_midi_infomation(info);
904 return MMFILE_FORMAT_SUCCESS;
908 int mmfile_format_read_tag_mid(MMFileFormatContext *formatContext)
910 MIDI_INFO_SIMPLE *info = NULL;
911 const char *locale = MMFileUtilGetLocale();
913 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
916 info = mmfile_format_get_midi_infomation(formatContext->uriFileName);
922 formatContext->title = mmfile_convert_to_utf8((const char *)info->title, -1, locale);
923 if (formatContext->title == NULL) {
924 debug_warning(DEBUG, "failed to UTF8 convert.\n");
925 formatContext->title = g_strdup(info->title);
929 if (info->copyright) {
930 formatContext->copyright = mmfile_convert_to_utf8((const char *)info->copyright, -1, locale);
931 if (formatContext->copyright == NULL) {
932 debug_warning(DEBUG, "failed to UTF8 convert.\n");
933 formatContext->copyright = g_strdup(info->copyright);
938 formatContext->comment = mmfile_convert_to_utf8((const char *)info->comment, -1, locale);
939 if (formatContext->comment == NULL) {
940 debug_warning(DEBUG, "failed to UTF8 convert.\n");
941 formatContext->comment = g_strdup(info->comment);
945 #ifdef __MMFILE_TEST_MODE__
946 mmfile_format_print_contents(formatContext);
949 mmfile_format_free_midi_infomation(info);
950 return MMFILE_FORMAT_SUCCESS;
954 int mmfile_format_read_frame_mid(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
956 debug_error(DEBUG, "error: mmfile_format_read_frame_midi, no handling\n");
958 return MMFILE_FORMAT_FAIL;
962 int mmfile_format_close_mid(MMFileFormatContext *formatContext)
964 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
965 mmfile_free(formatContext->streams[MMFILE_AUDIO_STREAM]);
967 formatContext->ReadStream = NULL;
968 formatContext->ReadFrame = NULL;
969 formatContext->ReadTag = NULL;
970 formatContext->Close = NULL;
972 return MMFILE_FORMAT_SUCCESS;
975 MIDI_INFO_SIMPLE * mmfile_format_get_midi_infomation(char *szFileName)
977 MIDI_INFO_SIMPLE *info = g_new0(MIDI_INFO_SIMPLE, 1);
979 __AvGetMidiDuration(szFileName, info);
984 void mmfile_format_free_midi_infomation(MIDI_INFO_SIMPLE *info)
987 mmfile_free(info->title);
988 mmfile_free(info->copyright);
989 mmfile_free(info->comment);