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