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 <log/log.h>
     31 
     32 #include "eas_data.h"
     33 #include "eas_miditypes.h"
     34 #include "eas_parser.h"
     35 #include "eas_report.h"
     36 #include "eas_host.h"
     37 #include "eas_midi.h"
     38 #include "eas_xmf.h"
     39 #include "eas_xmfdata.h"
     40 #include "eas_config.h"
     41 #include "eas_vm_protos.h"
     42 #include "eas_mdls.h"
     43 #include "eas_smf.h"
     44 
     45 
     46 /* XMF header file type */
     47 #define XMF_IDENTIFIER          0x584d465f
     48 #define XMF_VERSION_1_00        0x312e3030
     49 #define XMF_VERSION_1_01        0x312e3031
     50 #define XMF_VERSION_2_00        0x322e3030
     51 #define XMF_FILE_TYPE           0x00000002
     52 #define XMF_SPEC_LEVEL          0x00000001
     53 #define XMF_RIFF_CHUNK          0x52494646
     54 #define XMF_RIFF_DLS            0x444c5320
     55 #define XMF_SMF_CHUNK           0x4d546864
     56 
     57 /* local prototypes */
     58 static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
     59 static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
     60 static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
     61 static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
     62 static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
     63 static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
     64 static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
     65 static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
     66 static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
     67 static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
     68 static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
     69 static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData);
     70 static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength);
     71 static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value);
     72 
     73 
     74 /*----------------------------------------------------------------------------
     75  *
     76  * XMF_Parser
     77  *
     78  * This structure contains the functional interface for the XMF parser
     79  *----------------------------------------------------------------------------
     80 */
     81 const S_FILE_PARSER_INTERFACE EAS_XMF_Parser =
     82 {
     83     XMF_CheckFileType,
     84     XMF_Prepare,
     85     XMF_Time,
     86     XMF_Event,
     87     XMF_State,
     88     XMF_Close,
     89     XMF_Reset,
     90     XMF_Pause,
     91     XMF_Resume,
     92     NULL,
     93     XMF_SetData,
     94     XMF_GetData,
     95     NULL
     96 };
     97 
     98 /*----------------------------------------------------------------------------
     99  * XMF_CheckFileType()
    100  *----------------------------------------------------------------------------
    101  * Purpose:
    102  * Check the file type to see if we can parse it
    103  *
    104  * Inputs:
    105  * pEASData         - pointer to overall EAS data structure
    106  * handle           - pointer to file handle
    107  *
    108  * Outputs:
    109  *
    110  *
    111  * Side Effects:
    112  *
    113  *----------------------------------------------------------------------------
    114 */
    115 static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
    116 {
    117     S_XMF_DATA *pXMFData;
    118     EAS_RESULT result;
    119     EAS_U32 temp;
    120 
    121     /* assume we don't recognize it initially */
    122     *ppHandle = NULL;
    123 
    124     /* read the file identifier */
    125     if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE))  != EAS_SUCCESS)
    126         return result;
    127     if (temp != XMF_IDENTIFIER)
    128         return EAS_SUCCESS;
    129 
    130     /* read the version */
    131     if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE))  != EAS_SUCCESS)
    132         return result;
    133 
    134     if (temp == XMF_VERSION_2_00)
    135     {
    136         /* read the file type */
    137         result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE);
    138         if (result != EAS_SUCCESS)
    139             return result;
    140 
    141         if (temp != XMF_FILE_TYPE)
    142         {
    143             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR,
    144                           "XMF file type was 0x%08x, expected 0x%08x\n", temp, XMF_FILE_TYPE); */ }
    145             return EAS_SUCCESS;
    146         }
    147 
    148         /* read the spec level */
    149         result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE);
    150         if (result != EAS_SUCCESS)
    151             return result;
    152 
    153         if (temp != XMF_SPEC_LEVEL)
    154         {
    155             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR,
    156                           "XMF file spec was 0x%08x, expected 0x%08x\n", temp, XMF_SPEC_LEVEL); */ }
    157             return EAS_SUCCESS;
    158         }
    159     }
    160     else if (temp != XMF_VERSION_1_00 && temp != XMF_VERSION_1_01)
    161     {
    162         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file version was 0x%08x\n", temp); */ }
    163         return EAS_SUCCESS;
    164     }
    165 
    166     /* check for static memory allocation */
    167     if (pEASData->staticMemoryModel)
    168         pXMFData = EAS_CMEnumData(EAS_CM_XMF_DATA);
    169     else
    170         pXMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_XMF_DATA));
    171     if (!pXMFData)
    172         return EAS_ERROR_MALLOC_FAILED;
    173 
    174     /* zero the memory to insure complete initialization */
    175     EAS_HWMemSet((void *)pXMFData,0, sizeof(S_XMF_DATA));
    176 
    177     pXMFData->fileHandle = fileHandle;
    178     pXMFData->fileOffset = offset;
    179     *ppHandle = pXMFData;
    180 
    181     /* locate the SMF and DLS contents */
    182     if ((result = XMF_FindFileContents(pEASData->hwInstData, pXMFData)) != EAS_SUCCESS)
    183     {
    184         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ }
    185         return result;
    186     }
    187 
    188     /* let the SMF parser take over */
    189     if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pXMFData->midiOffset)) != EAS_SUCCESS)
    190         return result;
    191     return SMF_CheckFileType(pEASData, fileHandle, &pXMFData->pSMFData, pXMFData->midiOffset);
    192 }
    193 
    194 /*----------------------------------------------------------------------------
    195  * XMF_Prepare()
    196  *----------------------------------------------------------------------------
    197  * Purpose:
    198  * Prepare to parse the file. Allocates instance data (or uses static allocation for
    199  * static memory model).
    200  *
    201  * Inputs:
    202  * pEASData         - pointer to overall EAS data structure
    203  * handle           - pointer to file handle
    204  *
    205  * Outputs:
    206  *
    207  *
    208  * Side Effects:
    209  *
    210  *----------------------------------------------------------------------------
    211 */
    212 static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
    213 {
    214     S_XMF_DATA* pXMFData;
    215     EAS_RESULT result;
    216 
    217     /* parse DLS collection */
    218     pXMFData = (S_XMF_DATA*) pInstData;
    219     if (pXMFData->dlsOffset != 0)
    220     {
    221         if ((result = DLSParser(pEASData->hwInstData, pXMFData->fileHandle, pXMFData->dlsOffset, &pXMFData->pDLS)) != EAS_SUCCESS)
    222         {
    223             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error converting XMF DLS data\n"); */ }
    224             return result;
    225         }
    226     }
    227 
    228     /* Prepare the SMF parser */
    229     if ((result = SMF_Prepare(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS)
    230         return result;
    231 
    232     /* if no DLS file, skip this step */
    233     if (pXMFData->pDLS == NULL)
    234         return EAS_SUCCESS;
    235 
    236     /* tell the synth to use the DLS collection */
    237     result = VMSetDLSLib(((S_SMF_DATA*) pXMFData->pSMFData)->pSynth, pXMFData->pDLS);
    238     if (result == EAS_SUCCESS)
    239     {
    240         DLSAddRef(pXMFData->pDLS);
    241         VMInitializeAllChannels(pEASData->pVoiceMgr, ((S_SMF_DATA*) pXMFData->pSMFData)->pSynth);
    242     }
    243     return result;
    244 }
    245 
    246 /*----------------------------------------------------------------------------
    247  * XMF_Time()
    248  *----------------------------------------------------------------------------
    249  * Purpose:
    250  * Returns the time of the next event in msecs
    251  *
    252  * Inputs:
    253  * pEASData         - pointer to overall EAS data structure
    254  * handle           - pointer to file handle
    255  * pTime            - pointer to variable to hold time of next event (in msecs)
    256  *
    257  * Outputs:
    258  *
    259  *
    260  * Side Effects:
    261  *
    262  *----------------------------------------------------------------------------
    263 */
    264 static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
    265 {
    266     return SMF_Time(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pTime);
    267 }
    268 
    269 /*----------------------------------------------------------------------------
    270  * XMF_Event()
    271  *----------------------------------------------------------------------------
    272  * Purpose:
    273  * Parse the next event in the file
    274  *
    275  * Inputs:
    276  * pEASData         - pointer to overall EAS data structure
    277  * handle           - pointer to file handle
    278  *
    279  * Outputs:
    280  *
    281  *
    282  * Side Effects:
    283  *
    284  *----------------------------------------------------------------------------
    285 */
    286 static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
    287 {
    288     return SMF_Event(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, parserMode);
    289 }
    290 
    291 /*----------------------------------------------------------------------------
    292  * XMF_State()
    293  *----------------------------------------------------------------------------
    294  * Purpose:
    295  * Returns the current state of the stream
    296  *
    297  * Inputs:
    298  * pEASData         - pointer to overall EAS data structure
    299  * handle           - pointer to file handle
    300  * pState           - pointer to variable to store state
    301  *
    302  * Outputs:
    303  *
    304  *
    305  * Side Effects:
    306  *
    307  *----------------------------------------------------------------------------
    308 */
    309 static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
    310 {
    311     return SMF_State(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pState);
    312 }
    313 
    314 /*----------------------------------------------------------------------------
    315  * XMF_Close()
    316  *----------------------------------------------------------------------------
    317  * Purpose:
    318  * Close the file and clean up
    319  *
    320  * Inputs:
    321  * pEASData         - pointer to overall EAS data structure
    322  * handle           - pointer to file handle
    323  *
    324  * Outputs:
    325  *
    326  *
    327  * Side Effects:
    328  *
    329  *----------------------------------------------------------------------------
    330 */
    331 static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
    332 {
    333     S_XMF_DATA* pXMFData;
    334     EAS_RESULT result;
    335 
    336     pXMFData = (S_XMF_DATA *)pInstData;
    337 
    338     /* close the SMF stream, it will close the file handle */
    339     if ((result = SMF_Close(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS)
    340         return result;
    341 
    342     if (pXMFData->pDLS)
    343         DLSCleanup(pEASData->hwInstData, pXMFData->pDLS);
    344 
    345     /* if using dynamic memory, free it */
    346     if (!pEASData->staticMemoryModel)
    347     {
    348         /* free the instance data */
    349         EAS_HWFree(pEASData->hwInstData, pXMFData);
    350     }
    351 
    352     return EAS_SUCCESS;
    353 }
    354 
    355 /*----------------------------------------------------------------------------
    356  * XMF_Reset()
    357  *----------------------------------------------------------------------------
    358  * Purpose:
    359  * Reset the sequencer. Used for locating backwards in the file.
    360  *
    361  * Inputs:
    362  * pEASData         - pointer to overall EAS data structure
    363  * handle           - pointer to file handle
    364  *
    365  * Outputs:
    366  *
    367  *
    368  * Side Effects:
    369  *
    370  *----------------------------------------------------------------------------
    371 */
    372 static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
    373 {
    374     return SMF_Reset(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData);
    375 }
    376 
    377 /*----------------------------------------------------------------------------
    378  * XMF_Pause()
    379  *----------------------------------------------------------------------------
    380  * Purpose:
    381  * Pauses the sequencer. Mutes all voices and sets state to pause.
    382  *
    383  * Inputs:
    384  * pEASData         - pointer to overall EAS data structure
    385  * handle           - pointer to file handle
    386  *
    387  * Outputs:
    388  *
    389  *
    390  * Side Effects:
    391  *
    392  *----------------------------------------------------------------------------
    393 */
    394 static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
    395 {
    396     return SMF_Pause(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData);
    397 }
    398 
    399 /*----------------------------------------------------------------------------
    400  * XMF_Resume()
    401  *----------------------------------------------------------------------------
    402  * Purpose:
    403  * Resume playing after a pause, sets state back to playing.
    404  *
    405  * Inputs:
    406  * pEASData         - pointer to overall EAS data structure
    407  * handle           - pointer to file handle
    408  *
    409  * Outputs:
    410  *
    411  *
    412  * Side Effects:
    413  *
    414  *----------------------------------------------------------------------------
    415 */
    416 static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
    417 {
    418     return SMF_Resume(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData);
    419 }
    420 
    421 /*----------------------------------------------------------------------------
    422  * XMF_SetData()
    423  *----------------------------------------------------------------------------
    424  * Purpose:
    425  * Sets the playback rate of the underlying SMF file
    426  *
    427  * Inputs:
    428  * pEASData         - pointer to overall EAS data structure
    429  * handle           - pointer to file handle
    430  * rate             - rate (28-bit fraction)
    431  *
    432  * Outputs:
    433  *
    434  *
    435  * Side Effects:
    436  *
    437  *----------------------------------------------------------------------------
    438 */
    439 static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
    440 {
    441     return SMF_SetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, value);
    442 }
    443 
    444 /*----------------------------------------------------------------------------
    445  * XMF_GetData()
    446  *----------------------------------------------------------------------------
    447  * Purpose:
    448  * Gets the file type
    449  *
    450  * Inputs:
    451  * pEASData         - pointer to overall EAS data structure
    452  * handle           - pointer to file handle
    453  * rate             - rate (28-bit fraction)
    454  *
    455  * Outputs:
    456  *
    457  *
    458  * Side Effects:
    459  *
    460  *----------------------------------------------------------------------------
    461 */
    462 static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
    463 {
    464     EAS_RESULT result;
    465 
    466     /* call SMF parser to get value */
    467     if ((result = SMF_GetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, pValue)) != EAS_SUCCESS)
    468         return result;
    469 
    470     /* special case for file type */
    471     if (param == PARSER_DATA_FILE_TYPE)
    472     {
    473         if (*pValue == EAS_FILE_SMF0)
    474             *pValue = EAS_FILE_XMF0;
    475         else if (*pValue == EAS_FILE_SMF1)
    476             *pValue = EAS_FILE_XMF1;
    477     }
    478 
    479     return EAS_SUCCESS;
    480 }
    481 
    482 /*----------------------------------------------------------------------------
    483  * XMF_FindFileContents()
    484  *----------------------------------------------------------------------------
    485  * Purpose:
    486  * Finds SMF data and DLS data in XMF file, and remembers offset for each.
    487  * If more than one is found, uses the first one found of each.
    488  * Makes assumptions about the format of a mobile XMF file
    489  *
    490  * Inputs:
    491  * pEASData         - pointer to overall EAS data structure
    492  * pXMFData         - pointer to XMF parser instance data
    493  * handle           - pointer to file handle
    494  *
    495  * Outputs:
    496  *
    497  *
    498  * Side Effects:
    499  *
    500  *----------------------------------------------------------------------------
    501 */
    502 static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData)
    503 {
    504     EAS_RESULT result;
    505     EAS_I32 value;
    506     EAS_I32 length;
    507 
    508     /* initialize offsets */
    509     pXMFData->dlsOffset = pXMFData->midiOffset = 0;
    510 
    511     /* read file length, ignore it for now */
    512     if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS)
    513         return result;
    514 
    515     /* read MetaDataTypesTable length and skip over it */
    516     if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS)
    517         return result;
    518     if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, value)) != EAS_SUCCESS)
    519         return result;
    520 
    521     /* get TreeStart offset and jump to it */
    522     if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS)
    523         return result;
    524     if ((result = XMF_ReadNode(hwInstData, pXMFData, value, &length)) != EAS_SUCCESS)
    525         return result;
    526 
    527     /* check for SMF data */
    528     if (pXMFData->midiOffset == 0)
    529     {
    530         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ }
    531         return EAS_ERROR_FILE_FORMAT;
    532     }
    533 
    534     /* check for SFM in wrong order */
    535     if ((pXMFData->dlsOffset > 0) && (pXMFData->midiOffset < pXMFData->dlsOffset))
    536         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS data must precede SMF data in Mobile XMF file\n"); */ }
    537 
    538     return EAS_SUCCESS;
    539 }
    540 
    541 /*----------------------------------------------------------------------------
    542  * XMF_ReadNode()
    543  *----------------------------------------------------------------------------
    544  * Purpose:
    545  *
    546  * Inputs:
    547  *
    548  * Outputs:
    549  *
    550  *
    551  * Side Effects:
    552  *
    553  *----------------------------------------------------------------------------
    554 */
    555 static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength)
    556 {
    557     EAS_RESULT result;
    558     EAS_I32 refType;
    559     EAS_I32 numItems;
    560     EAS_I32 offset;
    561     EAS_I32 length;
    562     EAS_I32 headerLength;
    563     EAS_U32 chunkType;
    564 
    565     /* seek to start of node */
    566     if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset)) != EAS_SUCCESS)
    567         return result;
    568 
    569     /* get node length */
    570     if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, pLength)) != EAS_SUCCESS)
    571         return result;
    572 
    573     /* get number of contained items */
    574     if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &numItems)) != EAS_SUCCESS)
    575         return result;
    576 
    577     /* get node header length */
    578     if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &headerLength)) != EAS_SUCCESS)
    579         return result;
    580 
    581     /* get metadata length */
    582     if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &length)) != EAS_SUCCESS)
    583         return result;
    584 
    585     /* get the current location */
    586     if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
    587         return result;
    588 
    589     if (offset - nodeOffset > headerLength)
    590         return EAS_FAILURE;
    591 
    592     /* skip to node contents */
    593     if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset + headerLength)) != EAS_SUCCESS)
    594         return result;
    595 
    596     /* get reference type */
    597     if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &refType)) != EAS_SUCCESS)
    598         return result;
    599 
    600     /* get the current location */
    601     if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
    602         return result;
    603 
    604     /* process file node */
    605     if (numItems == 0)
    606 
    607     {
    608         /* if in-file resource, find out where it is and jump to it */
    609         if (refType == 2)
    610         {
    611             if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
    612                 return result;
    613             offset += pXMFData->fileOffset;
    614             if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS)
    615                 return result;
    616         }
    617 
    618         /* or else it must be an inline resource */
    619         else if (refType != 1)
    620         {
    621             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected reference type %d\n", refType); */ }
    622             return EAS_ERROR_FILE_FORMAT;
    623         }
    624 
    625         /* get the chunk type */
    626         if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS)
    627             return result;
    628 
    629         /* found a RIFF chunk, check for DLS type */
    630         if (chunkType == XMF_RIFF_CHUNK)
    631         {
    632             /* skip length */
    633             if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, sizeof(EAS_I32))) != EAS_SUCCESS)
    634                 return result;
    635 
    636             /* get RIFF file type */
    637             if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS)
    638                 return result;
    639             if (chunkType == XMF_RIFF_DLS)
    640                 pXMFData->dlsOffset = offset;
    641         }
    642 
    643         /* found an SMF chunk */
    644         else if (chunkType == XMF_SMF_CHUNK)
    645             pXMFData->midiOffset = offset;
    646     }
    647 
    648     /* folder node, process the items in the list */
    649     else
    650     {
    651         for ( ; numItems > 0; numItems--)
    652         {
    653             /* process this item */
    654             if (offset <= nodeOffset) {
    655                 ALOGE("b/36725407: parser did not advance");
    656                 return EAS_ERROR_FILE_FORMAT;
    657             }
    658 
    659             if ((result = XMF_ReadNode(hwInstData, pXMFData, offset, &length)) != EAS_SUCCESS)
    660                 return result;
    661 
    662             /* seek to start of next item */
    663             offset += length;
    664             if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS)
    665                 return result;
    666         }
    667     }
    668 
    669     return EAS_SUCCESS;
    670 }
    671 
    672 #if 0
    673 /*----------------------------------------------------------------------------
    674  * XMF_FindFileContents()
    675  *----------------------------------------------------------------------------
    676  * Purpose:
    677  * Finds SMF data and DLS data in XMF file, and remembers offset for each.
    678  * If more than one is found, uses the first one found of each.
    679  * Makes assumptions about the format of a mobile XMF file
    680  *
    681  * Inputs:
    682  * pEASData         - pointer to overall EAS data structure
    683  * pXMFData         - pointer to XMF parser instance data
    684  * handle           - pointer to file handle
    685  *
    686  * Outputs:
    687  *
    688  *
    689  * Side Effects:
    690  *
    691  *----------------------------------------------------------------------------
    692 */
    693 static EAS_RESULT XMF_FindFileContents(S_EAS_DATA *pEASData, S_XMF_DATA *pXMFData, EAS_FILE_HANDLE fileHandle)
    694 {
    695     EAS_RESULT result;
    696     EAS_I32 offset;
    697     EAS_I32 value;
    698     EAS_I32 numItems;
    699     EAS_I32 length;
    700     EAS_CHAR id[4];
    701     EAS_I32 location;
    702 
    703     /* init dls offset, so that we know we haven't found a dls chunk yet */
    704     pXMFData->dlsOffset = 0;
    705 
    706     /* read file length, ignore it for now */
    707     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
    708         return result;
    709 
    710     /* read MetaDataTypesTable length and skip over it */
    711     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
    712         return result;
    713     if ((result = EAS_HWFileSeekOfs(pEASData, fileHandle, value)) != EAS_SUCCESS)
    714         return result;
    715 
    716     /* get TreeStart offset and jump to it */
    717     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &offset)) != EAS_SUCCESS)
    718         return result;
    719     if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS)
    720         return result;
    721 
    722     /* read node length, ignore it for now */
    723     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
    724         return result;
    725 
    726     /* read number of contained items */
    727     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &numItems)) != EAS_SUCCESS)
    728         return result;
    729 
    730     /*read node header length */
    731     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
    732         return result;
    733 
    734     /*go to the node offset */
    735     if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS)
    736         return result;
    737 
    738     /* read Reference Type */
    739     if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
    740         return result;
    741 
    742     /* make sure it is an in-line resource, for now */
    743     if (value != 1)
    744     {
    745         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file tree\n"); */ }
    746         return EAS_FAILURE;
    747     }
    748 
    749     /* parse through the list of items */
    750     while (numItems > 0)
    751     {
    752         /*get current offset */
    753         if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &offset)) != EAS_SUCCESS)
    754             return result;
    755 
    756         /*read node length */
    757         if ((result = XMF_ReadVLQ(pEASData, fileHandle, &length)) != EAS_SUCCESS)
    758             return result;
    759 
    760         /* read number of items */
    761         if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
    762             return result;
    763 
    764         /* make sure not a folder */
    765         if (value != 0)
    766         {
    767             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ }
    768             return EAS_FAILURE;
    769         }
    770 
    771         /* read offset to resource and jump to it */
    772         if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
    773             return result;
    774         if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS)
    775             return result;
    776 
    777         /* read Reference Type */
    778         if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
    779             return result;
    780 
    781         /* make sure it is an in-line resource */
    782         if (value != 1)
    783         {
    784             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ }
    785             return EAS_FAILURE;
    786         }
    787 
    788         /* get current offset as a possible location for SMF file or DLS file */
    789         if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &location)) != EAS_SUCCESS)
    790             return result;
    791 
    792         /* read four bytes */
    793         if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, id, sizeof(id), &value)) != EAS_SUCCESS)
    794             return result;
    795 
    796         /* check if DLS */
    797         if (pXMFData->dlsOffset == 0 && id[0] == 'R' && id[1] == 'I' && id[2] == 'F' && id[3] == 'F')
    798         {
    799             //remember offset
    800             pXMFData->dlsOffset = location;
    801         }
    802 
    803         /* else check if SMF */
    804         else if (id[0] == 'M' && id[1] == 'T' && id[2] == 'h' && id[3] == 'd')
    805         {
    806             //remember offset
    807             pXMFData->midiOffset = location;
    808 
    809             //we are done
    810             return EAS_SUCCESS;
    811         }
    812 
    813         //one less item
    814         numItems--;
    815 
    816         //if more data, go to the next item
    817         if (numItems >0)
    818         {
    819             if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + length)) != EAS_SUCCESS)
    820                 return result;
    821         }
    822     }
    823 
    824     return EAS_FAILURE;
    825 
    826 }
    827 #endif
    828 
    829 /*----------------------------------------------------------------------------
    830  * XMF_ReadVLQ()
    831  *----------------------------------------------------------------------------
    832  * Purpose:
    833  * Reads a VLQ encoded value from the file referenced by fileHandle
    834  *
    835  * Inputs:
    836  * pEASData         - pointer to overall EAS data structure
    837  * fileHandle       - pointer to file handle
    838  *
    839  * Outputs:
    840  * value            - pointer to the value decoded from the VLQ data
    841  *
    842  *
    843  * Side Effects:
    844  *
    845  *----------------------------------------------------------------------------
    846 */
    847 static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value)
    848 {
    849     EAS_RESULT result;
    850     EAS_U8 c;
    851 
    852     *value = 0;
    853 
    854     if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
    855         return result;
    856 
    857     while (c > 0x7F)
    858     {
    859         /*lint -e{703} shift for performance */
    860         *value = (*value << 7) | (c & 0x7F);
    861 
    862         if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
    863             return result;
    864     }
    865 
    866     /*lint -e{703} shift for performance */
    867     *value = (*value << 7) | c;
    868 
    869     return EAS_SUCCESS;
    870 }
    871 
    872