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