1 /*---------------------------------------------------------------------------- 2 * 3 * File: 4 * eas_xmf.c 5 * 5 6 * Contents and purpose: 7 * XMF File Parser 8 * 9 * Copyright Sonic Network Inc. 2005 10 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 * 23 *---------------------------------------------------------------------------- 24 * Revision Control: 25 * $Revision: 501 $ 26 * $Date: 2006-12-11 17:53:36 -0800 (Mon, 11 Dec 2006) $ 27 *---------------------------------------------------------------------------- 28 */ 29 30 #include "eas_data.h" 31 #include "eas_miditypes.h" 32 #include "eas_parser.h" 33 #include "eas_report.h" 34 #include "eas_host.h" 35 #include "eas_midi.h" 36 #include "eas_xmf.h" 37 #include "eas_xmfdata.h" 38 #include "eas_config.h" 39 #include "eas_vm_protos.h" 40 #include "eas_mdls.h" 41 #include "eas_smf.h" 42 43 44 /* XMF header file type */ 45 #define XMF_IDENTIFIER 0x584d465f 46 #define XMF_VERSION_2_00 0x322e3030 47 #define XMF_FILE_TYPE 0x00000002 48 #define XMF_SPEC_LEVEL 0x00000001 49 #define XMF_RIFF_CHUNK 0x52494646 50 #define XMF_RIFF_DLS 0x444c5320 51 #define XMF_SMF_CHUNK 0x4d546864 52 53 /* local prototypes */ 54 static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); 55 static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); 56 static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); 57 static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); 58 static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); 59 static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); 60 static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); 61 static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); 62 static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); 63 static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); 64 static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); 65 static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData); 66 static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength); 67 static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value); 68 69 70 /*---------------------------------------------------------------------------- 71 * 72 * XMF_Parser 73 * 74 * This structure contains the functional interface for the XMF parser 75 *---------------------------------------------------------------------------- 76 */ 77 const S_FILE_PARSER_INTERFACE EAS_XMF_Parser = 78 { 79 XMF_CheckFileType, 80 XMF_Prepare, 81 XMF_Time, 82 XMF_Event, 83 XMF_State, 84 XMF_Close, 85 XMF_Reset, 86 XMF_Pause, 87 XMF_Resume, 88 NULL, 89 XMF_SetData, 90 XMF_GetData, 91 NULL 92 }; 93 94 /*---------------------------------------------------------------------------- 95 * XMF_CheckFileType() 96 *---------------------------------------------------------------------------- 97 * Purpose: 98 * Check the file type to see if we can parse it 99 * 100 * Inputs: 101 * pEASData - pointer to overall EAS data structure 102 * handle - pointer to file handle 103 * 104 * Outputs: 105 * 106 * 107 * Side Effects: 108 * 109 *---------------------------------------------------------------------------- 110 */ 111 static 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 */ 199 static 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 */ 251 static 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 */ 273 static 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 */ 296 static 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 */ 318 static 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 */ 359 static 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 */ 381 static 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 */ 403 static 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 */ 426 static 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 */ 449 static 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 */ 489 static 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 */ 542 static 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 */ 672 static 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 */ 826 static 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