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