1 /*----------------------------------------------------------------------------
2 *
3 * File:
4 * eas_xmf.c
5 * 5
6 * Contents and purpose:
7 * XMF File Parser
8 *
9 * Copyright Sonic Network Inc. 2005
10
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 *
23 *----------------------------------------------------------------------------
24 * Revision Control:
25 * $Revision: 501 $
26 * $Date: 2006-12-11 17:53:36 -0800 (Mon, 11 Dec 2006) $
27 *----------------------------------------------------------------------------
28 */
29
30 #include <log/log.h>
31
32 #include "eas_data.h"
33 #include "eas_miditypes.h"
34 #include "eas_parser.h"
35 #include "eas_report.h"
36 #include "eas_host.h"
37 #include "eas_midi.h"
38 #include "eas_xmf.h"
39 #include "eas_xmfdata.h"
40 #include "eas_config.h"
41 #include "eas_vm_protos.h"
42 #include "eas_mdls.h"
43 #include "eas_smf.h"
44
45
46 /* XMF header file type */
47 #define XMF_IDENTIFIER 0x584d465f
48 #define XMF_VERSION_1_00 0x312e3030
49 #define XMF_VERSION_1_01 0x312e3031
50 #define XMF_VERSION_2_00 0x322e3030
51 #define XMF_FILE_TYPE 0x00000002
52 #define XMF_SPEC_LEVEL 0x00000001
53 #define XMF_RIFF_CHUNK 0x52494646
54 #define XMF_RIFF_DLS 0x444c5320
55 #define XMF_SMF_CHUNK 0x4d546864
56
57 /* local prototypes */
58 static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
59 static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
60 static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
61 static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
62 static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
63 static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
64 static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
65 static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
66 static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
67 static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
68 static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
69 static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData);
70 static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength, EAS_I32 depth);
71 static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value);
72
73
74 /*----------------------------------------------------------------------------
75 *
76 * XMF_Parser
77 *
78 * This structure contains the functional interface for the XMF parser
79 *----------------------------------------------------------------------------
80 */
81 const S_FILE_PARSER_INTERFACE EAS_XMF_Parser =
82 {
83 XMF_CheckFileType,
84 XMF_Prepare,
85 XMF_Time,
86 XMF_Event,
87 XMF_State,
88 XMF_Close,
89 XMF_Reset,
90 XMF_Pause,
91 XMF_Resume,
92 NULL,
93 XMF_SetData,
94 XMF_GetData,
95 NULL
96 };
97
98 /*----------------------------------------------------------------------------
99 * XMF_CheckFileType()
100 *----------------------------------------------------------------------------
101 * Purpose:
102 * Check the file type to see if we can parse it
103 *
104 * Inputs:
105 * pEASData - pointer to overall EAS data structure
106 * handle - pointer to file handle
107 *
108 * Outputs:
109 *
110 *
111 * Side Effects:
112 *
113 *----------------------------------------------------------------------------
114 */
XMF_CheckFileType(S_EAS_DATA * pEASData,EAS_FILE_HANDLE fileHandle,EAS_VOID_PTR * ppHandle,EAS_I32 offset)115 static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
116 {
117 S_XMF_DATA *pXMFData;
118 EAS_RESULT result;
119 EAS_U32 temp;
120
121 /* assume we don't recognize it initially */
122 *ppHandle = NULL;
123
124 /* read the file identifier */
125 if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS)
126 return result;
127 if (temp != XMF_IDENTIFIER)
128 return EAS_SUCCESS;
129
130 /* read the version */
131 if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS)
132 return result;
133
134 if (temp == XMF_VERSION_2_00)
135 {
136 /* read the file type */
137 result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE);
138 if (result != EAS_SUCCESS)
139 return result;
140
141 if (temp != XMF_FILE_TYPE)
142 {
143 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR,
144 "XMF file type was 0x%08x, expected 0x%08x\n", temp, XMF_FILE_TYPE); */ }
145 return EAS_SUCCESS;
146 }
147
148 /* read the spec level */
149 result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE);
150 if (result != EAS_SUCCESS)
151 return result;
152
153 if (temp != XMF_SPEC_LEVEL)
154 {
155 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR,
156 "XMF file spec was 0x%08x, expected 0x%08x\n", temp, XMF_SPEC_LEVEL); */ }
157 return EAS_SUCCESS;
158 }
159 }
160 else if (temp != XMF_VERSION_1_00 && temp != XMF_VERSION_1_01)
161 {
162 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file version was 0x%08x\n", temp); */ }
163 return EAS_SUCCESS;
164 }
165
166 /* check for static memory allocation */
167 if (pEASData->staticMemoryModel)
168 pXMFData = EAS_CMEnumData(EAS_CM_XMF_DATA);
169 else
170 pXMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_XMF_DATA));
171 if (!pXMFData)
172 return EAS_ERROR_MALLOC_FAILED;
173
174 /* zero the memory to insure complete initialization */
175 EAS_HWMemSet((void *)pXMFData,0, sizeof(S_XMF_DATA));
176
177 pXMFData->fileHandle = fileHandle;
178 pXMFData->fileOffset = offset;
179 *ppHandle = pXMFData;
180
181 /* locate the SMF and DLS contents */
182 if ((result = XMF_FindFileContents(pEASData->hwInstData, pXMFData)) != EAS_SUCCESS)
183 {
184 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ }
185 return result;
186 }
187
188 /* let the SMF parser take over */
189 if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pXMFData->midiOffset)) != EAS_SUCCESS)
190 return result;
191 return SMF_CheckFileType(pEASData, fileHandle, &pXMFData->pSMFData, pXMFData->midiOffset);
192 }
193
194 /*----------------------------------------------------------------------------
195 * XMF_Prepare()
196 *----------------------------------------------------------------------------
197 * Purpose:
198 * Prepare to parse the file. Allocates instance data (or uses static allocation for
199 * static memory model).
200 *
201 * Inputs:
202 * pEASData - pointer to overall EAS data structure
203 * handle - pointer to file handle
204 *
205 * Outputs:
206 *
207 *
208 * Side Effects:
209 *
210 *----------------------------------------------------------------------------
211 */
XMF_Prepare(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)212 static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
213 {
214 S_XMF_DATA* pXMFData;
215 EAS_RESULT result;
216
217 /* parse DLS collection */
218 pXMFData = (S_XMF_DATA*) pInstData;
219 if (pXMFData->dlsOffset != 0)
220 {
221 if ((result = DLSParser(pEASData->hwInstData, pXMFData->fileHandle, pXMFData->dlsOffset, &pXMFData->pDLS)) != EAS_SUCCESS)
222 {
223 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error converting XMF DLS data\n"); */ }
224 return result;
225 }
226 }
227
228 /* Prepare the SMF parser */
229 if ((result = SMF_Prepare(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS)
230 return result;
231
232 /* if no DLS file, skip this step */
233 if (pXMFData->pDLS == NULL)
234 return EAS_SUCCESS;
235
236 /* tell the synth to use the DLS collection */
237 result = VMSetDLSLib(((S_SMF_DATA*) pXMFData->pSMFData)->pSynth, pXMFData->pDLS);
238 if (result == EAS_SUCCESS)
239 {
240 DLSAddRef(pXMFData->pDLS);
241 VMInitializeAllChannels(pEASData->pVoiceMgr, ((S_SMF_DATA*) pXMFData->pSMFData)->pSynth);
242 }
243 return result;
244 }
245
246 /*----------------------------------------------------------------------------
247 * XMF_Time()
248 *----------------------------------------------------------------------------
249 * Purpose:
250 * Returns the time of the next event in msecs
251 *
252 * Inputs:
253 * pEASData - pointer to overall EAS data structure
254 * handle - pointer to file handle
255 * pTime - pointer to variable to hold time of next event (in msecs)
256 *
257 * Outputs:
258 *
259 *
260 * Side Effects:
261 *
262 *----------------------------------------------------------------------------
263 */
XMF_Time(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_U32 * pTime)264 static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
265 {
266 return SMF_Time(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pTime);
267 }
268
269 /*----------------------------------------------------------------------------
270 * XMF_Event()
271 *----------------------------------------------------------------------------
272 * Purpose:
273 * Parse the next event in the file
274 *
275 * Inputs:
276 * pEASData - pointer to overall EAS data structure
277 * handle - pointer to file handle
278 *
279 * Outputs:
280 *
281 *
282 * Side Effects:
283 *
284 *----------------------------------------------------------------------------
285 */
XMF_Event(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_INT parserMode)286 static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
287 {
288 return SMF_Event(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, parserMode);
289 }
290
291 /*----------------------------------------------------------------------------
292 * XMF_State()
293 *----------------------------------------------------------------------------
294 * Purpose:
295 * Returns the current state of the stream
296 *
297 * Inputs:
298 * pEASData - pointer to overall EAS data structure
299 * handle - pointer to file handle
300 * pState - pointer to variable to store state
301 *
302 * Outputs:
303 *
304 *
305 * Side Effects:
306 *
307 *----------------------------------------------------------------------------
308 */
XMF_State(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_I32 * pState)309 static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
310 {
311 return SMF_State(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pState);
312 }
313
314 /*----------------------------------------------------------------------------
315 * XMF_Close()
316 *----------------------------------------------------------------------------
317 * Purpose:
318 * Close the file and clean up
319 *
320 * Inputs:
321 * pEASData - pointer to overall EAS data structure
322 * handle - pointer to file handle
323 *
324 * Outputs:
325 *
326 *
327 * Side Effects:
328 *
329 *----------------------------------------------------------------------------
330 */
XMF_Close(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)331 static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
332 {
333 S_XMF_DATA* pXMFData;
334 EAS_RESULT result;
335
336 pXMFData = (S_XMF_DATA *)pInstData;
337
338 /* close the SMF stream, it will close the file handle */
339 if ((result = SMF_Close(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS)
340 return result;
341
342 if (pXMFData->pDLS)
343 DLSCleanup(pEASData->hwInstData, pXMFData->pDLS);
344
345 /* if using dynamic memory, free it */
346 if (!pEASData->staticMemoryModel)
347 {
348 /* free the instance data */
349 EAS_HWFree(pEASData->hwInstData, pXMFData);
350 }
351
352 return EAS_SUCCESS;
353 }
354
355 /*----------------------------------------------------------------------------
356 * XMF_Reset()
357 *----------------------------------------------------------------------------
358 * Purpose:
359 * Reset the sequencer. Used for locating backwards in the file.
360 *
361 * Inputs:
362 * pEASData - pointer to overall EAS data structure
363 * handle - pointer to file handle
364 *
365 * Outputs:
366 *
367 *
368 * Side Effects:
369 *
370 *----------------------------------------------------------------------------
371 */
XMF_Reset(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)372 static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
373 {
374 return SMF_Reset(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData);
375 }
376
377 /*----------------------------------------------------------------------------
378 * XMF_Pause()
379 *----------------------------------------------------------------------------
380 * Purpose:
381 * Pauses the sequencer. Mutes all voices and sets state to pause.
382 *
383 * Inputs:
384 * pEASData - pointer to overall EAS data structure
385 * handle - pointer to file handle
386 *
387 * Outputs:
388 *
389 *
390 * Side Effects:
391 *
392 *----------------------------------------------------------------------------
393 */
XMF_Pause(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)394 static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
395 {
396 return SMF_Pause(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData);
397 }
398
399 /*----------------------------------------------------------------------------
400 * XMF_Resume()
401 *----------------------------------------------------------------------------
402 * Purpose:
403 * Resume playing after a pause, sets state back to playing.
404 *
405 * Inputs:
406 * pEASData - pointer to overall EAS data structure
407 * handle - pointer to file handle
408 *
409 * Outputs:
410 *
411 *
412 * Side Effects:
413 *
414 *----------------------------------------------------------------------------
415 */
XMF_Resume(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)416 static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
417 {
418 return SMF_Resume(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData);
419 }
420
421 /*----------------------------------------------------------------------------
422 * XMF_SetData()
423 *----------------------------------------------------------------------------
424 * Purpose:
425 * Sets the playback rate of the underlying SMF file
426 *
427 * Inputs:
428 * pEASData - pointer to overall EAS data structure
429 * handle - pointer to file handle
430 * rate - rate (28-bit fraction)
431 *
432 * Outputs:
433 *
434 *
435 * Side Effects:
436 *
437 *----------------------------------------------------------------------------
438 */
XMF_SetData(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_I32 param,EAS_I32 value)439 static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
440 {
441 return SMF_SetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, value);
442 }
443
444 /*----------------------------------------------------------------------------
445 * XMF_GetData()
446 *----------------------------------------------------------------------------
447 * Purpose:
448 * Gets the file type
449 *
450 * Inputs:
451 * pEASData - pointer to overall EAS data structure
452 * handle - pointer to file handle
453 * rate - rate (28-bit fraction)
454 *
455 * Outputs:
456 *
457 *
458 * Side Effects:
459 *
460 *----------------------------------------------------------------------------
461 */
XMF_GetData(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_I32 param,EAS_I32 * pValue)462 static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
463 {
464 EAS_RESULT result;
465
466 /* call SMF parser to get value */
467 if ((result = SMF_GetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, pValue)) != EAS_SUCCESS)
468 return result;
469
470 /* special case for file type */
471 if (param == PARSER_DATA_FILE_TYPE)
472 {
473 if (*pValue == EAS_FILE_SMF0)
474 *pValue = EAS_FILE_XMF0;
475 else if (*pValue == EAS_FILE_SMF1)
476 *pValue = EAS_FILE_XMF1;
477 }
478
479 return EAS_SUCCESS;
480 }
481
482 /*----------------------------------------------------------------------------
483 * XMF_FindFileContents()
484 *----------------------------------------------------------------------------
485 * Purpose:
486 * Finds SMF data and DLS data in XMF file, and remembers offset for each.
487 * If more than one is found, uses the first one found of each.
488 * Makes assumptions about the format of a mobile XMF file
489 *
490 * Inputs:
491 * pEASData - pointer to overall EAS data structure
492 * pXMFData - pointer to XMF parser instance data
493 * handle - pointer to file handle
494 *
495 * Outputs:
496 *
497 *
498 * Side Effects:
499 *
500 *----------------------------------------------------------------------------
501 */
XMF_FindFileContents(EAS_HW_DATA_HANDLE hwInstData,S_XMF_DATA * pXMFData)502 static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData)
503 {
504 EAS_RESULT result;
505 EAS_I32 value;
506 EAS_I32 length;
507 EAS_I32 node_depth = 0 ;
508
509 /* initialize offsets */
510 pXMFData->dlsOffset = pXMFData->midiOffset = 0;
511
512 /* read file length, ignore it for now */
513 if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS)
514 return result;
515
516 /* read MetaDataTypesTable length and skip over it */
517 if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS)
518 return result;
519 if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, value)) != EAS_SUCCESS)
520 return result;
521
522 /* get TreeStart offset and jump to it */
523 if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS)
524 return result;
525 if ((result = XMF_ReadNode(hwInstData, pXMFData, value, &length, node_depth)) != EAS_SUCCESS)
526 return result;
527
528 /* check for SMF data */
529 if (pXMFData->midiOffset == 0)
530 {
531 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ }
532 return EAS_ERROR_FILE_FORMAT;
533 }
534
535 /* check for SFM in wrong order */
536 if ((pXMFData->dlsOffset > 0) && (pXMFData->midiOffset < pXMFData->dlsOffset))
537 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS data must precede SMF data in Mobile XMF file\n"); */ }
538
539 return EAS_SUCCESS;
540 }
541
542 /*----------------------------------------------------------------------------
543 * XMF_ReadNode()
544 *----------------------------------------------------------------------------
545 * Purpose:
546 *
547 * Inputs:
548 *
549 * Outputs:
550 *
551 *
552 * Side Effects:
553 *
554 *----------------------------------------------------------------------------
555 */
XMF_ReadNode(EAS_HW_DATA_HANDLE hwInstData,S_XMF_DATA * pXMFData,EAS_I32 nodeOffset,EAS_I32 * pLength,EAS_I32 depth)556 static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength, EAS_I32 depth)
557 {
558 EAS_RESULT result;
559 EAS_I32 refType;
560 EAS_I32 numItems;
561 EAS_I32 offset;
562 EAS_I32 length;
563 EAS_I32 headerLength;
564 EAS_U32 chunkType;
565
566 /* check the depth of current node*/
567 if ( depth > 100 )
568 return EAS_ERROR_FILE_FORMAT;
569
570 /* seek to start of node */
571 if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset)) != EAS_SUCCESS)
572 return result;
573
574 /* get node length */
575 if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, pLength)) != EAS_SUCCESS)
576 return result;
577
578 /* get number of contained items */
579 if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &numItems)) != EAS_SUCCESS)
580 return result;
581
582 /* get node header length */
583 if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &headerLength)) != EAS_SUCCESS)
584 return result;
585
586 /* get metadata length */
587 if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &length)) != EAS_SUCCESS)
588 return result;
589
590 /* get the current location */
591 if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
592 return result;
593
594 if (offset - nodeOffset > headerLength)
595 return EAS_FAILURE;
596
597 /* skip to node contents */
598 if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset + headerLength)) != EAS_SUCCESS)
599 return result;
600
601 /* get reference type */
602 if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &refType)) != EAS_SUCCESS)
603 return result;
604
605 /* get the current location */
606 if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
607 return result;
608
609 /* process file node */
610 if (numItems == 0)
611
612 {
613 /* if in-file resource, find out where it is and jump to it */
614 if (refType == 2)
615 {
616 if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
617 return result;
618 offset += pXMFData->fileOffset;
619 if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS)
620 return result;
621 }
622
623 /* or else it must be an inline resource */
624 else if (refType != 1)
625 {
626 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected reference type %d\n", refType); */ }
627 return EAS_ERROR_FILE_FORMAT;
628 }
629
630 /* get the chunk type */
631 if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS)
632 return result;
633
634 /* found a RIFF chunk, check for DLS type */
635 if (chunkType == XMF_RIFF_CHUNK)
636 {
637 /* skip length */
638 if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, sizeof(EAS_I32))) != EAS_SUCCESS)
639 return result;
640
641 /* get RIFF file type */
642 if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS)
643 return result;
644 if (chunkType == XMF_RIFF_DLS)
645 pXMFData->dlsOffset = offset;
646 }
647
648 /* found an SMF chunk */
649 else if (chunkType == XMF_SMF_CHUNK)
650 pXMFData->midiOffset = offset;
651 }
652
653 /* folder node, process the items in the list */
654 else
655 {
656 for ( ; numItems > 0; numItems--)
657 {
658 /* process this item */
659 if (offset <= nodeOffset) {
660 ALOGE("b/36725407: parser did not advance");
661 return EAS_ERROR_FILE_FORMAT;
662 }
663
664 if ((result = XMF_ReadNode(hwInstData, pXMFData, offset, &length, depth+1)) != EAS_SUCCESS)
665 return result;
666
667 /* seek to start of next item */
668 offset += length;
669 if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS)
670 return result;
671 }
672 }
673
674 return EAS_SUCCESS;
675 }
676
677 #if 0
678 /*----------------------------------------------------------------------------
679 * XMF_FindFileContents()
680 *----------------------------------------------------------------------------
681 * Purpose:
682 * Finds SMF data and DLS data in XMF file, and remembers offset for each.
683 * If more than one is found, uses the first one found of each.
684 * Makes assumptions about the format of a mobile XMF file
685 *
686 * Inputs:
687 * pEASData - pointer to overall EAS data structure
688 * pXMFData - pointer to XMF parser instance data
689 * handle - pointer to file handle
690 *
691 * Outputs:
692 *
693 *
694 * Side Effects:
695 *
696 *----------------------------------------------------------------------------
697 */
698 static EAS_RESULT XMF_FindFileContents(S_EAS_DATA *pEASData, S_XMF_DATA *pXMFData, EAS_FILE_HANDLE fileHandle)
699 {
700 EAS_RESULT result;
701 EAS_I32 offset;
702 EAS_I32 value;
703 EAS_I32 numItems;
704 EAS_I32 length;
705 EAS_CHAR id[4];
706 EAS_I32 location;
707
708 /* init dls offset, so that we know we haven't found a dls chunk yet */
709 pXMFData->dlsOffset = 0;
710
711 /* read file length, ignore it for now */
712 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
713 return result;
714
715 /* read MetaDataTypesTable length and skip over it */
716 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
717 return result;
718 if ((result = EAS_HWFileSeekOfs(pEASData, fileHandle, value)) != EAS_SUCCESS)
719 return result;
720
721 /* get TreeStart offset and jump to it */
722 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &offset)) != EAS_SUCCESS)
723 return result;
724 if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS)
725 return result;
726
727 /* read node length, ignore it for now */
728 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
729 return result;
730
731 /* read number of contained items */
732 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &numItems)) != EAS_SUCCESS)
733 return result;
734
735 /*read node header length */
736 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
737 return result;
738
739 /*go to the node offset */
740 if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS)
741 return result;
742
743 /* read Reference Type */
744 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
745 return result;
746
747 /* make sure it is an in-line resource, for now */
748 if (value != 1)
749 {
750 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file tree\n"); */ }
751 return EAS_FAILURE;
752 }
753
754 /* parse through the list of items */
755 while (numItems > 0)
756 {
757 /*get current offset */
758 if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &offset)) != EAS_SUCCESS)
759 return result;
760
761 /*read node length */
762 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &length)) != EAS_SUCCESS)
763 return result;
764
765 /* read number of items */
766 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
767 return result;
768
769 /* make sure not a folder */
770 if (value != 0)
771 {
772 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ }
773 return EAS_FAILURE;
774 }
775
776 /* read offset to resource and jump to it */
777 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
778 return result;
779 if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS)
780 return result;
781
782 /* read Reference Type */
783 if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
784 return result;
785
786 /* make sure it is an in-line resource */
787 if (value != 1)
788 {
789 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ }
790 return EAS_FAILURE;
791 }
792
793 /* get current offset as a possible location for SMF file or DLS file */
794 if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &location)) != EAS_SUCCESS)
795 return result;
796
797 /* read four bytes */
798 if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, id, sizeof(id), &value)) != EAS_SUCCESS)
799 return result;
800
801 /* check if DLS */
802 if (pXMFData->dlsOffset == 0 && id[0] == 'R' && id[1] == 'I' && id[2] == 'F' && id[3] == 'F')
803 {
804 //remember offset
805 pXMFData->dlsOffset = location;
806 }
807
808 /* else check if SMF */
809 else if (id[0] == 'M' && id[1] == 'T' && id[2] == 'h' && id[3] == 'd')
810 {
811 //remember offset
812 pXMFData->midiOffset = location;
813
814 //we are done
815 return EAS_SUCCESS;
816 }
817
818 //one less item
819 numItems--;
820
821 //if more data, go to the next item
822 if (numItems >0)
823 {
824 if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + length)) != EAS_SUCCESS)
825 return result;
826 }
827 }
828
829 return EAS_FAILURE;
830
831 }
832 #endif
833
834 /*----------------------------------------------------------------------------
835 * XMF_ReadVLQ()
836 *----------------------------------------------------------------------------
837 * Purpose:
838 * Reads a VLQ encoded value from the file referenced by fileHandle
839 *
840 * Inputs:
841 * pEASData - pointer to overall EAS data structure
842 * fileHandle - pointer to file handle
843 *
844 * Outputs:
845 * value - pointer to the value decoded from the VLQ data
846 *
847 *
848 * Side Effects:
849 *
850 *----------------------------------------------------------------------------
851 */
XMF_ReadVLQ(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE fileHandle,EAS_I32 * value)852 static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value)
853 {
854 EAS_RESULT result;
855 EAS_U8 c;
856
857 *value = 0;
858
859 if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
860 return result;
861
862 while (c > 0x7F)
863 {
864 /*lint -e{703} shift for performance */
865 *value = (*value << 7) | (c & 0x7F);
866
867 if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
868 return result;
869 }
870
871 /*lint -e{703} shift for performance */
872 *value = (*value << 7) | c;
873
874 return EAS_SUCCESS;
875 }
876
877