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