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