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_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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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