Home | History | Annotate | Download | only in lib_src
      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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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