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