• 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_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