• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     /* skip to node contents */
588     if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset + headerLength)) != EAS_SUCCESS)
589         return result;
590 
591     /* get reference type */
592     if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &refType)) != EAS_SUCCESS)
593         return result;
594 
595     /* get the current location */
596     if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
597         return result;
598 
599     /* process file node */
600     if (numItems == 0)
601 
602     {
603         /* if in-file resource, find out where it is and jump to it */
604         if (refType == 2)
605         {
606             if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
607                 return result;
608             offset += pXMFData->fileOffset;
609             if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS)
610                 return result;
611         }
612 
613         /* or else it must be an inline resource */
614         else if (refType != 1)
615         {
616             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected reference type %d\n", refType); */ }
617             return EAS_ERROR_FILE_FORMAT;
618         }
619 
620         /* get the chunk type */
621         if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS)
622             return result;
623 
624         /* found a RIFF chunk, check for DLS type */
625         if (chunkType == XMF_RIFF_CHUNK)
626         {
627             /* skip length */
628             if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, sizeof(EAS_I32))) != EAS_SUCCESS)
629                 return result;
630 
631             /* get RIFF file type */
632             if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS)
633                 return result;
634             if (chunkType == XMF_RIFF_DLS)
635                 pXMFData->dlsOffset = offset;
636         }
637 
638         /* found an SMF chunk */
639         else if (chunkType == XMF_SMF_CHUNK)
640             pXMFData->midiOffset = offset;
641     }
642 
643     /* folder node, process the items in the list */
644     else
645     {
646         for ( ; numItems > 0; numItems--)
647         {
648             /* process this item */
649             if ((result = XMF_ReadNode(hwInstData, pXMFData, offset, &length)) != EAS_SUCCESS)
650                 return result;
651 
652             /* seek to start of next item */
653             offset += length;
654             if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS)
655                 return result;
656         }
657     }
658 
659     return EAS_SUCCESS;
660 }
661 
662 #if 0
663 /*----------------------------------------------------------------------------
664  * XMF_FindFileContents()
665  *----------------------------------------------------------------------------
666  * Purpose:
667  * Finds SMF data and DLS data in XMF file, and remembers offset for each.
668  * If more than one is found, uses the first one found of each.
669  * Makes assumptions about the format of a mobile XMF file
670  *
671  * Inputs:
672  * pEASData         - pointer to overall EAS data structure
673  * pXMFData         - pointer to XMF parser instance data
674  * handle           - pointer to file handle
675  *
676  * Outputs:
677  *
678  *
679  * Side Effects:
680  *
681  *----------------------------------------------------------------------------
682 */
683 static EAS_RESULT XMF_FindFileContents(S_EAS_DATA *pEASData, S_XMF_DATA *pXMFData, EAS_FILE_HANDLE fileHandle)
684 {
685     EAS_RESULT result;
686     EAS_I32 offset;
687     EAS_I32 value;
688     EAS_I32 numItems;
689     EAS_I32 length;
690     EAS_CHAR id[4];
691     EAS_I32 location;
692 
693     /* init dls offset, so that we know we haven't found a dls chunk yet */
694     pXMFData->dlsOffset = 0;
695 
696     /* read file length, ignore it for now */
697     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
698         return result;
699 
700     /* read MetaDataTypesTable length and skip over it */
701     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
702         return result;
703     if ((result = EAS_HWFileSeekOfs(pEASData, fileHandle, value)) != EAS_SUCCESS)
704         return result;
705 
706     /* get TreeStart offset and jump to it */
707     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &offset)) != EAS_SUCCESS)
708         return result;
709     if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS)
710         return result;
711 
712     /* read node length, ignore it for now */
713     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
714         return result;
715 
716     /* read number of contained items */
717     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &numItems)) != EAS_SUCCESS)
718         return result;
719 
720     /*read node header length */
721     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
722         return result;
723 
724     /*go to the node offset */
725     if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS)
726         return result;
727 
728     /* read Reference Type */
729     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
730         return result;
731 
732     /* make sure it is an in-line resource, for now */
733     if (value != 1)
734     {
735         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file tree\n"); */ }
736         return EAS_FAILURE;
737     }
738 
739     /* parse through the list of items */
740     while (numItems > 0)
741     {
742         /*get current offset */
743         if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &offset)) != EAS_SUCCESS)
744             return result;
745 
746         /*read node length */
747         if ((result = XMF_ReadVLQ(pEASData, fileHandle, &length)) != EAS_SUCCESS)
748             return result;
749 
750         /* read number of items */
751         if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
752             return result;
753 
754         /* make sure not a folder */
755         if (value != 0)
756         {
757             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ }
758             return EAS_FAILURE;
759         }
760 
761         /* read offset to resource and jump to it */
762         if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
763             return result;
764         if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS)
765             return result;
766 
767         /* read Reference Type */
768         if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
769             return result;
770 
771         /* make sure it is an in-line resource */
772         if (value != 1)
773         {
774             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ }
775             return EAS_FAILURE;
776         }
777 
778         /* get current offset as a possible location for SMF file or DLS file */
779         if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &location)) != EAS_SUCCESS)
780             return result;
781 
782         /* read four bytes */
783         if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, id, sizeof(id), &value)) != EAS_SUCCESS)
784             return result;
785 
786         /* check if DLS */
787         if (pXMFData->dlsOffset == 0 && id[0] == 'R' && id[1] == 'I' && id[2] == 'F' && id[3] == 'F')
788         {
789             //remember offset
790             pXMFData->dlsOffset = location;
791         }
792 
793         /* else check if SMF */
794         else if (id[0] == 'M' && id[1] == 'T' && id[2] == 'h' && id[3] == 'd')
795         {
796             //remember offset
797             pXMFData->midiOffset = location;
798 
799             //we are done
800             return EAS_SUCCESS;
801         }
802 
803         //one less item
804         numItems--;
805 
806         //if more data, go to the next item
807         if (numItems >0)
808         {
809             if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + length)) != EAS_SUCCESS)
810                 return result;
811         }
812     }
813 
814     return EAS_FAILURE;
815 
816 }
817 #endif
818 
819 /*----------------------------------------------------------------------------
820  * XMF_ReadVLQ()
821  *----------------------------------------------------------------------------
822  * Purpose:
823  * Reads a VLQ encoded value from the file referenced by fileHandle
824  *
825  * Inputs:
826  * pEASData         - pointer to overall EAS data structure
827  * fileHandle       - pointer to file handle
828  *
829  * Outputs:
830  * value            - pointer to the value decoded from the VLQ data
831  *
832  *
833  * Side Effects:
834  *
835  *----------------------------------------------------------------------------
836 */
XMF_ReadVLQ(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE fileHandle,EAS_I32 * value)837 static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value)
838 {
839     EAS_RESULT result;
840     EAS_U8 c;
841 
842     *value = 0;
843 
844     if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
845         return result;
846 
847     while (c > 0x7F)
848     {
849         /*lint -e{703} shift for performance */
850         *value = (*value << 7) | (c & 0x7F);
851 
852         if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
853             return result;
854     }
855 
856     /*lint -e{703} shift for performance */
857     *value = (*value << 7) | c;
858 
859     return EAS_SUCCESS;
860 }
861 
862