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