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