| /*---------------------------------------------------------------------------- |
| * |
| * File: |
| * eas_xmf.c |
| * 5 |
| * Contents and purpose: |
| * XMF File Parser |
| * |
| * Copyright Sonic Network Inc. 2005 |
| |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *---------------------------------------------------------------------------- |
| * Revision Control: |
| * $Revision: 501 $ |
| * $Date: 2006-12-11 17:53:36 -0800 (Mon, 11 Dec 2006) $ |
| *---------------------------------------------------------------------------- |
| */ |
| |
| #include "eas_data.h" |
| #include "eas_miditypes.h" |
| #include "eas_parser.h" |
| #include "eas_report.h" |
| #include "eas_host.h" |
| #include "eas_midi.h" |
| #include "eas_xmf.h" |
| #include "eas_xmfdata.h" |
| #include "eas_config.h" |
| #include "eas_vm_protos.h" |
| #include "eas_mdls.h" |
| #include "eas_smf.h" |
| |
| |
| /* XMF header file type */ |
| #define XMF_IDENTIFIER 0x584d465f |
| #define XMF_VERSION_1_00 0x312e3030 |
| #define XMF_VERSION_1_01 0x312e3031 |
| #define XMF_VERSION_2_00 0x322e3030 |
| #define XMF_FILE_TYPE 0x00000002 |
| #define XMF_SPEC_LEVEL 0x00000001 |
| #define XMF_RIFF_CHUNK 0x52494646 |
| #define XMF_RIFF_DLS 0x444c5320 |
| #define XMF_SMF_CHUNK 0x4d546864 |
| |
| /* local prototypes */ |
| static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); |
| static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); |
| static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); |
| static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); |
| static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); |
| static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); |
| static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); |
| static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); |
| static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); |
| static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); |
| static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); |
| static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData); |
| static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength); |
| static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value); |
| |
| |
| /*---------------------------------------------------------------------------- |
| * |
| * XMF_Parser |
| * |
| * This structure contains the functional interface for the XMF parser |
| *---------------------------------------------------------------------------- |
| */ |
| const S_FILE_PARSER_INTERFACE EAS_XMF_Parser = |
| { |
| XMF_CheckFileType, |
| XMF_Prepare, |
| XMF_Time, |
| XMF_Event, |
| XMF_State, |
| XMF_Close, |
| XMF_Reset, |
| XMF_Pause, |
| XMF_Resume, |
| NULL, |
| XMF_SetData, |
| XMF_GetData, |
| NULL |
| }; |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_CheckFileType() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Check the file type to see if we can parse it |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) |
| { |
| S_XMF_DATA *pXMFData; |
| EAS_RESULT result; |
| EAS_U32 temp; |
| |
| /* assume we don't recognize it initially */ |
| *ppHandle = NULL; |
| |
| /* read the file identifier */ |
| if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) |
| return result; |
| if (temp != XMF_IDENTIFIER) |
| return EAS_SUCCESS; |
| |
| /* read the version */ |
| if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) |
| return result; |
| |
| if (temp == XMF_VERSION_2_00) |
| { |
| /* read the file type */ |
| result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE); |
| if (result != EAS_SUCCESS) |
| return result; |
| |
| if (temp != XMF_FILE_TYPE) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, |
| "XMF file type was 0x%08x, expected 0x%08x\n", temp, XMF_FILE_TYPE); */ } |
| return EAS_SUCCESS; |
| } |
| |
| /* read the spec level */ |
| result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE); |
| if (result != EAS_SUCCESS) |
| return result; |
| |
| if (temp != XMF_SPEC_LEVEL) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, |
| "XMF file spec was 0x%08x, expected 0x%08x\n", temp, XMF_SPEC_LEVEL); */ } |
| return EAS_SUCCESS; |
| } |
| } |
| else if (temp != XMF_VERSION_1_00 && temp != XMF_VERSION_1_01) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file version was 0x%08x\n", temp); */ } |
| return EAS_SUCCESS; |
| } |
| |
| /* check for static memory allocation */ |
| if (pEASData->staticMemoryModel) |
| pXMFData = EAS_CMEnumData(EAS_CM_XMF_DATA); |
| else |
| pXMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_XMF_DATA)); |
| if (!pXMFData) |
| return EAS_ERROR_MALLOC_FAILED; |
| |
| /* zero the memory to insure complete initialization */ |
| EAS_HWMemSet((void *)pXMFData,0, sizeof(S_XMF_DATA)); |
| |
| pXMFData->fileHandle = fileHandle; |
| pXMFData->fileOffset = offset; |
| *ppHandle = pXMFData; |
| |
| /* locate the SMF and DLS contents */ |
| if ((result = XMF_FindFileContents(pEASData->hwInstData, pXMFData)) != EAS_SUCCESS) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ } |
| return result; |
| } |
| |
| /* let the SMF parser take over */ |
| if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pXMFData->midiOffset)) != EAS_SUCCESS) |
| return result; |
| return SMF_CheckFileType(pEASData, fileHandle, &pXMFData->pSMFData, pXMFData->midiOffset); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_Prepare() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Prepare to parse the file. Allocates instance data (or uses static allocation for |
| * static memory model). |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) |
| { |
| S_XMF_DATA* pXMFData; |
| EAS_RESULT result; |
| |
| /* parse DLS collection */ |
| pXMFData = (S_XMF_DATA*) pInstData; |
| if (pXMFData->dlsOffset != 0) |
| { |
| if ((result = DLSParser(pEASData->hwInstData, pXMFData->fileHandle, pXMFData->dlsOffset, &pXMFData->pDLS)) != EAS_SUCCESS) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error converting XMF DLS data\n"); */ } |
| return result; |
| } |
| } |
| |
| /* Prepare the SMF parser */ |
| if ((result = SMF_Prepare(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS) |
| return result; |
| |
| /* if no DLS file, skip this step */ |
| if (pXMFData->pDLS == NULL) |
| return EAS_SUCCESS; |
| |
| /* tell the synth to use the DLS collection */ |
| result = VMSetDLSLib(((S_SMF_DATA*) pXMFData->pSMFData)->pSynth, pXMFData->pDLS); |
| if (result == EAS_SUCCESS) |
| { |
| DLSAddRef(pXMFData->pDLS); |
| VMInitializeAllChannels(pEASData->pVoiceMgr, ((S_SMF_DATA*) pXMFData->pSMFData)->pSynth); |
| } |
| return result; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_Time() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Returns the time of the next event in msecs |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * pTime - pointer to variable to hold time of next event (in msecs) |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) |
| { |
| return SMF_Time(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pTime); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_Event() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Parse the next event in the file |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) |
| { |
| return SMF_Event(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, parserMode); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_State() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Returns the current state of the stream |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * pState - pointer to variable to store state |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) |
| { |
| return SMF_State(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pState); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_Close() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Close the file and clean up |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) |
| { |
| S_XMF_DATA* pXMFData; |
| EAS_RESULT result; |
| |
| pXMFData = (S_XMF_DATA *)pInstData; |
| |
| /* close the SMF stream, it will close the file handle */ |
| if ((result = SMF_Close(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS) |
| return result; |
| |
| if (pXMFData->pDLS) |
| DLSCleanup(pEASData->hwInstData, pXMFData->pDLS); |
| |
| /* if using dynamic memory, free it */ |
| if (!pEASData->staticMemoryModel) |
| { |
| /* free the instance data */ |
| EAS_HWFree(pEASData->hwInstData, pXMFData); |
| } |
| |
| return EAS_SUCCESS; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_Reset() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Reset the sequencer. Used for locating backwards in the file. |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) |
| { |
| return SMF_Reset(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_Pause() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Pauses the sequencer. Mutes all voices and sets state to pause. |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) |
| { |
| return SMF_Pause(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_Resume() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Resume playing after a pause, sets state back to playing. |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) |
| { |
| return SMF_Resume(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_SetData() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Sets the playback rate of the underlying SMF file |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * rate - rate (28-bit fraction) |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) |
| { |
| return SMF_SetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, value); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_GetData() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Gets the file type |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * handle - pointer to file handle |
| * rate - rate (28-bit fraction) |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) |
| { |
| EAS_RESULT result; |
| |
| /* call SMF parser to get value */ |
| if ((result = SMF_GetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, pValue)) != EAS_SUCCESS) |
| return result; |
| |
| /* special case for file type */ |
| if (param == PARSER_DATA_FILE_TYPE) |
| { |
| if (*pValue == EAS_FILE_SMF0) |
| *pValue = EAS_FILE_XMF0; |
| else if (*pValue == EAS_FILE_SMF1) |
| *pValue = EAS_FILE_XMF1; |
| } |
| |
| return EAS_SUCCESS; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_FindFileContents() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Finds SMF data and DLS data in XMF file, and remembers offset for each. |
| * If more than one is found, uses the first one found of each. |
| * Makes assumptions about the format of a mobile XMF file |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * pXMFData - pointer to XMF parser instance data |
| * handle - pointer to file handle |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData) |
| { |
| EAS_RESULT result; |
| EAS_I32 value; |
| EAS_I32 length; |
| |
| /* initialize offsets */ |
| pXMFData->dlsOffset = pXMFData->midiOffset = 0; |
| |
| /* read file length, ignore it for now */ |
| if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| |
| /* read MetaDataTypesTable length and skip over it */ |
| if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, value)) != EAS_SUCCESS) |
| return result; |
| |
| /* get TreeStart offset and jump to it */ |
| if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| if ((result = XMF_ReadNode(hwInstData, pXMFData, value, &length)) != EAS_SUCCESS) |
| return result; |
| |
| /* check for SMF data */ |
| if (pXMFData->midiOffset == 0) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ } |
| return EAS_ERROR_FILE_FORMAT; |
| } |
| |
| /* check for SFM in wrong order */ |
| if ((pXMFData->dlsOffset > 0) && (pXMFData->midiOffset < pXMFData->dlsOffset)) |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS data must precede SMF data in Mobile XMF file\n"); */ } |
| |
| return EAS_SUCCESS; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_ReadNode() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * |
| * Inputs: |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength) |
| { |
| EAS_RESULT result; |
| EAS_I32 refType; |
| EAS_I32 numItems; |
| EAS_I32 offset; |
| EAS_I32 length; |
| EAS_I32 headerLength; |
| EAS_U32 chunkType; |
| |
| /* seek to start of node */ |
| if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset)) != EAS_SUCCESS) |
| return result; |
| |
| /* get node length */ |
| if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, pLength)) != EAS_SUCCESS) |
| return result; |
| |
| /* get number of contained items */ |
| if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &numItems)) != EAS_SUCCESS) |
| return result; |
| |
| /* get node header length */ |
| if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &headerLength)) != EAS_SUCCESS) |
| return result; |
| |
| /* get metadata length */ |
| if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &length)) != EAS_SUCCESS) |
| return result; |
| |
| /* get the current location */ |
| if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS) |
| return result; |
| |
| /* skip to node contents */ |
| if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset + headerLength)) != EAS_SUCCESS) |
| return result; |
| |
| /* get reference type */ |
| if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &refType)) != EAS_SUCCESS) |
| return result; |
| |
| /* get the current location */ |
| if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS) |
| return result; |
| |
| /* process file node */ |
| if (numItems == 0) |
| |
| { |
| /* if in-file resource, find out where it is and jump to it */ |
| if (refType == 2) |
| { |
| if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS) |
| return result; |
| offset += pXMFData->fileOffset; |
| if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS) |
| return result; |
| } |
| |
| /* or else it must be an inline resource */ |
| else if (refType != 1) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected reference type %d\n", refType); */ } |
| return EAS_ERROR_FILE_FORMAT; |
| } |
| |
| /* get the chunk type */ |
| if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS) |
| return result; |
| |
| /* found a RIFF chunk, check for DLS type */ |
| if (chunkType == XMF_RIFF_CHUNK) |
| { |
| /* skip length */ |
| if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, sizeof(EAS_I32))) != EAS_SUCCESS) |
| return result; |
| |
| /* get RIFF file type */ |
| if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS) |
| return result; |
| if (chunkType == XMF_RIFF_DLS) |
| pXMFData->dlsOffset = offset; |
| } |
| |
| /* found an SMF chunk */ |
| else if (chunkType == XMF_SMF_CHUNK) |
| pXMFData->midiOffset = offset; |
| } |
| |
| /* folder node, process the items in the list */ |
| else |
| { |
| for ( ; numItems > 0; numItems--) |
| { |
| /* process this item */ |
| if ((result = XMF_ReadNode(hwInstData, pXMFData, offset, &length)) != EAS_SUCCESS) |
| return result; |
| |
| /* seek to start of next item */ |
| offset += length; |
| if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS) |
| return result; |
| } |
| } |
| |
| return EAS_SUCCESS; |
| } |
| |
| #if 0 |
| /*---------------------------------------------------------------------------- |
| * XMF_FindFileContents() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Finds SMF data and DLS data in XMF file, and remembers offset for each. |
| * If more than one is found, uses the first one found of each. |
| * Makes assumptions about the format of a mobile XMF file |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * pXMFData - pointer to XMF parser instance data |
| * handle - pointer to file handle |
| * |
| * Outputs: |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_FindFileContents(S_EAS_DATA *pEASData, S_XMF_DATA *pXMFData, EAS_FILE_HANDLE fileHandle) |
| { |
| EAS_RESULT result; |
| EAS_I32 offset; |
| EAS_I32 value; |
| EAS_I32 numItems; |
| EAS_I32 length; |
| EAS_CHAR id[4]; |
| EAS_I32 location; |
| |
| /* init dls offset, so that we know we haven't found a dls chunk yet */ |
| pXMFData->dlsOffset = 0; |
| |
| /* read file length, ignore it for now */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| |
| /* read MetaDataTypesTable length and skip over it */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| if ((result = EAS_HWFileSeekOfs(pEASData, fileHandle, value)) != EAS_SUCCESS) |
| return result; |
| |
| /* get TreeStart offset and jump to it */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &offset)) != EAS_SUCCESS) |
| return result; |
| if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS) |
| return result; |
| |
| /* read node length, ignore it for now */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| |
| /* read number of contained items */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &numItems)) != EAS_SUCCESS) |
| return result; |
| |
| /*read node header length */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| |
| /*go to the node offset */ |
| if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS) |
| return result; |
| |
| /* read Reference Type */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| |
| /* make sure it is an in-line resource, for now */ |
| if (value != 1) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file tree\n"); */ } |
| return EAS_FAILURE; |
| } |
| |
| /* parse through the list of items */ |
| while (numItems > 0) |
| { |
| /*get current offset */ |
| if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &offset)) != EAS_SUCCESS) |
| return result; |
| |
| /*read node length */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &length)) != EAS_SUCCESS) |
| return result; |
| |
| /* read number of items */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| |
| /* make sure not a folder */ |
| if (value != 0) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ } |
| return EAS_FAILURE; |
| } |
| |
| /* read offset to resource and jump to it */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS) |
| return result; |
| |
| /* read Reference Type */ |
| if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) |
| return result; |
| |
| /* make sure it is an in-line resource */ |
| if (value != 1) |
| { |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ } |
| return EAS_FAILURE; |
| } |
| |
| /* get current offset as a possible location for SMF file or DLS file */ |
| if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &location)) != EAS_SUCCESS) |
| return result; |
| |
| /* read four bytes */ |
| if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, id, sizeof(id), &value)) != EAS_SUCCESS) |
| return result; |
| |
| /* check if DLS */ |
| if (pXMFData->dlsOffset == 0 && id[0] == 'R' && id[1] == 'I' && id[2] == 'F' && id[3] == 'F') |
| { |
| //remember offset |
| pXMFData->dlsOffset = location; |
| } |
| |
| /* else check if SMF */ |
| else if (id[0] == 'M' && id[1] == 'T' && id[2] == 'h' && id[3] == 'd') |
| { |
| //remember offset |
| pXMFData->midiOffset = location; |
| |
| //we are done |
| return EAS_SUCCESS; |
| } |
| |
| //one less item |
| numItems--; |
| |
| //if more data, go to the next item |
| if (numItems >0) |
| { |
| if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + length)) != EAS_SUCCESS) |
| return result; |
| } |
| } |
| |
| return EAS_FAILURE; |
| |
| } |
| #endif |
| |
| /*---------------------------------------------------------------------------- |
| * XMF_ReadVLQ() |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Reads a VLQ encoded value from the file referenced by fileHandle |
| * |
| * Inputs: |
| * pEASData - pointer to overall EAS data structure |
| * fileHandle - pointer to file handle |
| * |
| * Outputs: |
| * value - pointer to the value decoded from the VLQ data |
| * |
| * |
| * Side Effects: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value) |
| { |
| EAS_RESULT result; |
| EAS_U8 c; |
| |
| *value = 0; |
| |
| if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) |
| return result; |
| |
| while (c > 0x7F) |
| { |
| /*lint -e{703} shift for performance */ |
| *value = (*value << 7) | (c & 0x7F); |
| |
| if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) |
| return result; |
| } |
| |
| /*lint -e{703} shift for performance */ |
| *value = (*value << 7) | c; |
| |
| return EAS_SUCCESS; |
| } |
| |