1 /*---------------------------------------------------------------------------- 2 * 3 * File: 4 * jet.c 5 * 6 * Contents and purpose: 7 * Implementation for JET sound engine 8 * 9 * Copyright (c) 2006 Sonic Network Inc. 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 * Revision Control: 24 * $Revision: 563 $ 25 * $Date: 2007-02-13 20:26:23 -0800 (Tue, 13 Feb 2007) $ 26 *---------------------------------------------------------------------------- 27 */ 28 29 //#define LOG_NDEBUG 0 30 #define LOG_TAG "JET_C" 31 32 //#define DEBUG_JET 33 34 #include "eas_data.h" 35 #include "eas_smf.h" 36 #include "jet_data.h" 37 #include "eas_host.h" 38 #include "eas_report.h" 39 40 41 /* default configuration */ 42 static const S_JET_CONFIG jetDefaultConfig = 43 { 44 JET_EVENT_APP_LOW, 45 JET_EVENT_APP_HIGH 46 }; 47 48 /* function prototypes */ 49 extern EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value); 50 extern EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream); 51 extern EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_DLSLIB_HANDLE *ppDLS); 52 53 /*---------------------------------------------------------------------------- 54 * JET_ParseEvent() 55 *---------------------------------------------------------------------------- 56 * Returns current status 57 *---------------------------------------------------------------------------- 58 */ 59 EAS_PUBLIC void JET_ParseEvent (EAS_U32 event, S_JET_EVENT *pEvent) 60 { 61 pEvent->segment = (EAS_U8) ((event & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT); 62 pEvent->track = (EAS_U8) ((event & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT); 63 pEvent->channel = (EAS_U8) ((event & JET_EVENT_CHAN_MASK) >> JET_EVENT_CHAN_SHIFT); 64 pEvent->controller = (EAS_U8) ((event & JET_EVENT_CTRL_MASK) >> JET_EVENT_CTRL_SHIFT); 65 pEvent->value = (EAS_U8) (event & JET_EVENT_VAL_MASK); 66 } 67 68 #ifdef DEBUG_JET 69 /*---------------------------------------------------------------------------- 70 * JET_DumpEvent 71 *---------------------------------------------------------------------------- 72 * Advances queue read/write index 73 *---------------------------------------------------------------------------- 74 */ 75 static void JET_DumpEvent (const char *procName, EAS_U32 event) 76 { 77 S_JET_EVENT sEvent; 78 JET_ParseEvent(event, &sEvent); 79 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "%s: SegID=%d, TrkID=%d, channel=%d, ctrl=%d, val=%d\n", 80 procName, sEvent.segment, sEvent.track, sEvent.channel, sEvent.controller, sEvent.value); */ } 81 } 82 #endif 83 84 /*---------------------------------------------------------------------------- 85 * JET_IncQueueIndex 86 *---------------------------------------------------------------------------- 87 * Advances queue read/write index 88 *---------------------------------------------------------------------------- 89 */ 90 EAS_INLINE EAS_U8 JET_IncQueueIndex (EAS_U8 index, EAS_U8 queueSize) 91 { 92 if (++index == queueSize) 93 index = 0; 94 return index; 95 } 96 97 /*---------------------------------------------------------------------------- 98 * JET_WriteQueue 99 *---------------------------------------------------------------------------- 100 * Save event to queue 101 *---------------------------------------------------------------------------- 102 */ 103 EAS_INLINE void JET_WriteQueue (EAS_U32 *pEventQueue, EAS_U8 *pWriteIndex, EAS_U8 readIndex, EAS_U8 queueSize, EAS_U32 event) 104 { 105 EAS_U8 temp; 106 107 /* check for queue overflow */ 108 temp = JET_IncQueueIndex(*pWriteIndex, queueSize); 109 if (temp == readIndex) 110 { 111 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "JET_Event: Event queue overflow --- event ignored!\n"); */ } 112 return; 113 } 114 115 /* save in queue and advance write index */ 116 pEventQueue[*pWriteIndex] = event; 117 *pWriteIndex = temp; 118 } 119 120 /*---------------------------------------------------------------------------- 121 * JET_ReadQueue 122 *---------------------------------------------------------------------------- 123 * Read event to queue 124 *---------------------------------------------------------------------------- 125 */ 126 EAS_INLINE EAS_BOOL JET_ReadQueue (EAS_U32 *pEventQueue, EAS_U8 *pReadIndex, EAS_U8 writeIndex, EAS_U8 queueSize, EAS_U32 *pEvent) 127 { 128 129 /* check for empty queue */ 130 if (*pReadIndex == writeIndex) 131 return EAS_FALSE; 132 133 /* save in queue and advance write index */ 134 *pEvent = pEventQueue[*pReadIndex]; 135 *pReadIndex = JET_IncQueueIndex(*pReadIndex, queueSize); 136 return EAS_TRUE; 137 } 138 139 /*---------------------------------------------------------------------------- 140 * JET_NextSegment 141 *---------------------------------------------------------------------------- 142 * Advances segment number 143 *---------------------------------------------------------------------------- 144 */ 145 EAS_INLINE EAS_INT JET_NextSegment (EAS_INT seg_num) 146 { 147 if (++seg_num == SEG_QUEUE_DEPTH) 148 seg_num = 0; 149 return seg_num; 150 } 151 152 /*---------------------------------------------------------------------------- 153 * JET_PrepareSegment() 154 *---------------------------------------------------------------------------- 155 * Prepare a segment for playback 156 *---------------------------------------------------------------------------- 157 */ 158 static EAS_RESULT JET_PrepareSegment (EAS_DATA_HANDLE easHandle, EAS_I32 queueNum) 159 { 160 EAS_RESULT result; 161 S_JET_SEGMENT *p; 162 163 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_PrepareSegment: %d\n", queueNum); */ } 164 165 p = &easHandle->jetHandle->segQueue[queueNum]; 166 result = EAS_Prepare(easHandle, p->streamHandle); 167 if (result != EAS_SUCCESS) 168 return result; 169 170 /* pause segment - must be triggered by play or end of previous segment */ 171 result = EAS_Pause(easHandle, p->streamHandle); 172 if (result != EAS_SUCCESS) 173 return result; 174 p->state = JET_STATE_READY; 175 176 /* set calback data */ 177 result = EAS_IntSetStrmParam(easHandle, p->streamHandle, PARSER_DATA_JET_CB, queueNum); 178 if (result != EAS_SUCCESS) 179 return result; 180 181 /* set DLS collection */ 182 if (p->libNum >= 0) 183 { 184 result = EAS_IntSetStrmParam(easHandle, p->streamHandle, 185 PARSER_DATA_DLS_COLLECTION, (EAS_I32) easHandle->jetHandle->libHandles[p->libNum]); 186 if (result != EAS_SUCCESS) 187 return result; 188 } 189 190 /* set transposition */ 191 if (p->transpose) 192 { 193 result = EAS_SetTransposition(easHandle, p->streamHandle, p->transpose); 194 if (result != EAS_SUCCESS) 195 return result; 196 } 197 198 return result; 199 } 200 201 /*---------------------------------------------------------------------------- 202 * JET_StartPlayback() 203 *---------------------------------------------------------------------------- 204 * Start segment playback 205 *---------------------------------------------------------------------------- 206 */ 207 static EAS_RESULT JET_StartPlayback (EAS_DATA_HANDLE easHandle, EAS_I32 queueNum) 208 { 209 EAS_RESULT result = EAS_SUCCESS; 210 S_JET_SEGMENT *pSeg; 211 212 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_StartPlayback %d\n", queueNum); */ } 213 214 /* if next segment is queued, start playback */ 215 pSeg = &easHandle->jetHandle->segQueue[queueNum]; 216 if (pSeg->streamHandle != NULL) 217 { 218 result = EAS_Resume(easHandle, pSeg->streamHandle); 219 easHandle->jetHandle->segQueue[queueNum].state = JET_STATE_PLAYING; 220 221 /* set mute flags */ 222 if ((result == EAS_SUCCESS) && (pSeg->muteFlags != 0)) 223 result = EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 224 } 225 return result; 226 } 227 228 /*---------------------------------------------------------------------------- 229 * JET_CloseSegment 230 *---------------------------------------------------------------------------- 231 * Closes stream associated with a segment 232 *---------------------------------------------------------------------------- 233 */ 234 EAS_INLINE EAS_INT JET_CloseSegment (EAS_DATA_HANDLE easHandle, EAS_INT queueNum) 235 { 236 EAS_RESULT result; 237 238 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_CloseSegment %d\n", queueNum); */ } 239 240 /* close the segment */ 241 result = EAS_CloseFile(easHandle, easHandle->jetHandle->segQueue[queueNum].streamHandle); 242 if (result != EAS_SUCCESS) 243 return result; 244 245 easHandle->jetHandle->segQueue[queueNum].streamHandle = NULL; 246 easHandle->jetHandle->segQueue[queueNum].state = JET_STATE_CLOSED; 247 easHandle->jetHandle->numQueuedSegments--; 248 return result; 249 } 250 251 /*---------------------------------------------------------------------------- 252 * JetParseInfoChunk() 253 *---------------------------------------------------------------------------- 254 * Parses the JET info chunk 255 *---------------------------------------------------------------------------- 256 */ 257 static EAS_RESULT JetParseInfoChunk (EAS_DATA_HANDLE easHandle, EAS_I32 pos, EAS_I32 chunkSize) 258 { 259 EAS_RESULT result; 260 EAS_U32 infoType; 261 EAS_U32 temp; 262 263 /* offset to data */ 264 result = EAS_HWFileSeek(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos); 265 if (result != EAS_SUCCESS) 266 return result; 267 268 /* read the entire chunk */ 269 result = EAS_SUCCESS; 270 while ((result == EAS_SUCCESS) && (chunkSize > 0)) 271 { 272 273 /* get info infoType */ 274 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &infoType, EAS_TRUE); 275 if (result != EAS_SUCCESS) 276 break; 277 278 /* get info field */ 279 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &temp, EAS_FALSE); 280 if (result == EAS_SUCCESS) 281 282 switch (infoType) 283 { 284 case INFO_NUM_SMF_CHUNKS: 285 if (temp >= JET_MAX_SEGMENTS) { 286 return EAS_ERROR_INCOMPATIBLE_VERSION; 287 } 288 easHandle->jetHandle->numSegments = (EAS_U8) temp; 289 break; 290 291 case INFO_NUM_DLS_CHUNKS: 292 if (temp >= JET_MAX_DLS_COLLECTIONS) { 293 return EAS_ERROR_INCOMPATIBLE_VERSION; 294 } 295 easHandle->jetHandle->numLibraries = (EAS_U8) temp; 296 break; 297 298 case INFO_JET_VERSION: 299 /* check major version number */ 300 if ((temp & 0xff000000) != (JET_VERSION & 0xff000000)) 301 return EAS_ERROR_INCOMPATIBLE_VERSION; 302 break; 303 304 default: 305 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized JET info type 0x%08x", infoType); */ } 306 break; 307 } 308 309 chunkSize -= 8; 310 } 311 312 /* allocate pointers for chunks to follow */ 313 314 return result; 315 } 316 317 /*---------------------------------------------------------------------------- 318 * JET_OpenFile() 319 *---------------------------------------------------------------------------- 320 * Opens a JET content file for playback 321 *---------------------------------------------------------------------------- 322 */ 323 EAS_PUBLIC EAS_RESULT JET_OpenFile (EAS_DATA_HANDLE easHandle, EAS_FILE_LOCATOR locator) 324 { 325 EAS_RESULT result; 326 EAS_U32 chunkType; 327 EAS_I32 pos; 328 EAS_I32 chunkSize; 329 EAS_INT smfChunkNum; 330 EAS_INT dlsChunkNum; 331 EAS_I32 dataSize = 0; /* make lint happy */ 332 333 /* make sure that we don't have an open file */ 334 if (easHandle->jetHandle->jetFileHandle != NULL) 335 return EAS_ERROR_FILE_ALREADY_OPEN; 336 337 /* open the media file */ 338 result = EAS_HWOpenFile(easHandle->hwInstData, locator, &easHandle->jetHandle->jetFileHandle, EAS_FILE_READ); 339 if (result != EAS_SUCCESS) 340 return result; 341 342 /* check header */ 343 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkType, EAS_TRUE); 344 if (result == EAS_SUCCESS) 345 { 346 if (chunkType != JET_HEADER_TAG) 347 { 348 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "File is not JET format\n"); */ } 349 result = EAS_ERROR_UNRECOGNIZED_FORMAT; 350 } 351 } 352 /* get the file data size */ 353 if (result == EAS_SUCCESS) 354 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &dataSize, EAS_FALSE); 355 356 /* parse through the file to find contents */ 357 smfChunkNum = dlsChunkNum = 0; 358 pos = chunkSize = 8; 359 while ((result == EAS_SUCCESS) && (pos < dataSize)) 360 { 361 362 /* offset to chunk data */ 363 result = EAS_HWFileSeek(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos); 364 if (result != EAS_SUCCESS) 365 break; 366 367 /* get chunk size and type */ 368 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkType, EAS_TRUE); 369 if (result != EAS_SUCCESS) 370 break; 371 372 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkSize, EAS_FALSE); 373 if (result != EAS_SUCCESS) 374 break; 375 pos += 8; 376 377 switch (chunkType) 378 { 379 case JET_INFO_CHUNK: 380 result = JetParseInfoChunk(easHandle, pos, chunkSize); 381 break; 382 383 case JET_SMF_CHUNK: 384 if (smfChunkNum < easHandle->jetHandle->numSegments) 385 easHandle->jetHandle->segmentOffsets[smfChunkNum++] = pos; 386 else 387 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring extraneous SMF chunk"); */ } 388 break; 389 390 case JET_DLS_CHUNK: 391 if (dlsChunkNum < easHandle->jetHandle->numLibraries) 392 result = DLSParser(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos, &easHandle->jetHandle->libHandles[dlsChunkNum++]); 393 else 394 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring extraneous DLS chunk"); */ } 395 break; 396 397 case JET_APP_DATA_CHUNK: 398 easHandle->jetHandle->appDataOffset = pos; 399 easHandle->jetHandle->appDataSize = chunkSize; 400 break; 401 402 case INFO_JET_COPYRIGHT: 403 break; 404 405 default: 406 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized JET chunk type 0x%08x", chunkType); */ } 407 break; 408 } 409 410 /* offset to next chunk */ 411 pos += chunkSize; 412 } 413 414 /* close file if something went wrong */ 415 if (result != EAS_SUCCESS) 416 EAS_HWCloseFile(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle); 417 418 return result; 419 } 420 421 /*---------------------------------------------------------------------------- 422 * JET_GetAppData() 423 *---------------------------------------------------------------------------- 424 * Returns location and size of application data in the JET file 425 *---------------------------------------------------------------------------- 426 */ 427 EAS_RESULT JET_GetAppData (EAS_DATA_HANDLE easHandle, EAS_I32 *pAppDataOffset, EAS_I32 *pAppDataSize) 428 { 429 430 /* check for app chunk */ 431 if (easHandle->jetHandle->appDataSize == 0) 432 { 433 *pAppDataOffset = *pAppDataSize = 0; 434 return EAS_FAILURE; 435 } 436 437 /* return app data */ 438 *pAppDataOffset = easHandle->jetHandle->appDataOffset; 439 *pAppDataSize = easHandle->jetHandle->appDataSize; 440 return EAS_SUCCESS; 441 } 442 443 /*---------------------------------------------------------------------------- 444 * JET_CloseFile() 445 *---------------------------------------------------------------------------- 446 * Closes a JET content file and releases associated resources 447 *---------------------------------------------------------------------------- 448 */ 449 EAS_PUBLIC EAS_RESULT JET_CloseFile (EAS_DATA_HANDLE easHandle) 450 { 451 EAS_INT index; 452 EAS_RESULT result = EAS_SUCCESS; 453 454 /* close open streams */ 455 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 456 { 457 if (easHandle->jetHandle->segQueue[index].streamHandle != NULL) 458 { 459 result = JET_CloseSegment(easHandle, index); 460 if (result != EAS_SUCCESS) 461 break; 462 } 463 } 464 465 /* close the main file handle */ 466 if ((result == EAS_SUCCESS) && (easHandle->jetHandle->jetFileHandle != NULL)) 467 { 468 result = EAS_HWCloseFile(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle); 469 if (result == EAS_SUCCESS) 470 easHandle->jetHandle->jetFileHandle = NULL; 471 } 472 return result; 473 } 474 475 /*---------------------------------------------------------------------------- 476 * JET_Init() 477 *---------------------------------------------------------------------------- 478 * Initializes the JET library, allocates memory, etc. Call 479 * JET_Shutdown to de-allocate memory. 480 *---------------------------------------------------------------------------- 481 */ 482 EAS_PUBLIC EAS_RESULT JET_Init (EAS_DATA_HANDLE easHandle, const S_JET_CONFIG *pConfig, EAS_INT configSize) 483 { 484 S_JET_DATA *pJet; 485 EAS_U8 flags = 0; 486 487 /* sanity check */ 488 if (easHandle == NULL) 489 return EAS_ERROR_HANDLE_INTEGRITY; 490 if (easHandle->jetHandle != NULL) 491 return EAS_ERROR_FEATURE_ALREADY_ACTIVE; 492 if (pConfig == NULL) 493 pConfig = &jetDefaultConfig; 494 495 /* allocate the JET data object */ 496 pJet = EAS_HWMalloc(easHandle->hwInstData, sizeof(S_JET_DATA)); 497 if (pJet == NULL) 498 return EAS_ERROR_MALLOC_FAILED; 499 500 /* initialize JET data structure */ 501 EAS_HWMemSet(pJet, 0, sizeof(S_JET_DATA)); 502 easHandle->jetHandle = pJet; 503 pJet->flags = flags; 504 505 /* copy config data */ 506 if (configSize > (EAS_INT) sizeof(S_JET_CONFIG)) 507 configSize = sizeof(S_JET_CONFIG); 508 EAS_HWMemCpy(&pJet->config, pConfig, configSize); 509 return EAS_SUCCESS; 510 } 511 512 /*---------------------------------------------------------------------------- 513 * JET_Shutdown() 514 *---------------------------------------------------------------------------- 515 * Frees any memory used by the JET library 516 *---------------------------------------------------------------------------- 517 */ 518 EAS_PUBLIC EAS_RESULT JET_Shutdown (EAS_DATA_HANDLE easHandle) 519 { 520 EAS_RESULT result; 521 522 /* close any open files */ 523 result = JET_CloseFile(easHandle); 524 525 /* free allocated data */ 526 EAS_HWFree(easHandle->hwInstData, easHandle->jetHandle); 527 easHandle->jetHandle = NULL; 528 return result; 529 } 530 531 /*---------------------------------------------------------------------------- 532 * JET_Status() 533 *---------------------------------------------------------------------------- 534 * Returns current status 535 *---------------------------------------------------------------------------- 536 */ 537 EAS_PUBLIC EAS_RESULT JET_Status (EAS_DATA_HANDLE easHandle, S_JET_STATUS *pStatus) 538 { 539 S_JET_SEGMENT *pSeg; 540 541 pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; 542 if (pSeg->streamHandle != NULL) 543 { 544 pStatus->currentUserID = pSeg->userID; 545 pStatus->segmentRepeatCount = pSeg->repeatCount; 546 } 547 else 548 { 549 pStatus->currentUserID = -1; 550 pStatus->segmentRepeatCount = 0; 551 } 552 553 pStatus->paused = !(easHandle->jetHandle->flags & JET_FLAGS_PLAYING); 554 pStatus->numQueuedSegments = easHandle->jetHandle->numQueuedSegments; 555 pStatus->currentPlayingSegment = easHandle->jetHandle->playSegment; 556 pStatus->currentQueuedSegment = easHandle->jetHandle->queueSegment; 557 if (pSeg->streamHandle != NULL) 558 { 559 EAS_RESULT result; 560 EAS_I32 location ; 561 if ((result = EAS_GetLocation(easHandle, pSeg->streamHandle, &location)) == EAS_SUCCESS) 562 if(location != 0) 563 { 564 pStatus->location = location; 565 } 566 } 567 return EAS_SUCCESS; 568 } 569 570 /*---------------------------------------------------------------------------- 571 * JET_GetEvent() 572 *---------------------------------------------------------------------------- 573 * Checks for application events 574 *---------------------------------------------------------------------------- 575 */ 576 EAS_PUBLIC EAS_BOOL JET_GetEvent (EAS_DATA_HANDLE easHandle, EAS_U32 *pEventRaw, S_JET_EVENT *pEvent) 577 { 578 EAS_U32 jetEvent; 579 EAS_BOOL gotEvent; 580 581 /* process event queue */ 582 gotEvent = JET_ReadQueue(easHandle->jetHandle->appEventQueue, 583 &easHandle->jetHandle->appEventQueueRead, 584 easHandle->jetHandle->appEventQueueWrite, 585 APP_EVENT_QUEUE_SIZE, &jetEvent); 586 587 if (gotEvent) 588 { 589 if (pEventRaw != NULL) 590 *pEventRaw = jetEvent; 591 592 if (pEvent != NULL) 593 JET_ParseEvent(jetEvent, pEvent); 594 } 595 596 return gotEvent; 597 } 598 599 /*---------------------------------------------------------------------------- 600 * JET_QueueSegment() 601 *---------------------------------------------------------------------------- 602 * Queue a segment for playback 603 *---------------------------------------------------------------------------- 604 */ 605 EAS_PUBLIC EAS_RESULT JET_QueueSegment (EAS_DATA_HANDLE easHandle, EAS_INT segmentNum, EAS_INT libNum, EAS_INT repeatCount, EAS_INT transpose, EAS_U32 muteFlags, EAS_U8 userID) 606 { 607 EAS_FILE_HANDLE fileHandle; 608 EAS_RESULT result; 609 S_JET_SEGMENT *p; 610 611 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_QueueSegment segNum=%d, queue=%d\n", segmentNum, easHandle->jetHandle->queueSegment); */ } 612 613 /* make sure it's a valid segment */ 614 if (segmentNum >= easHandle->jetHandle->numSegments) 615 return EAS_ERROR_PARAMETER_RANGE; 616 617 /* make sure it's a valid DLS */ 618 if (libNum >= easHandle->jetHandle->numLibraries) 619 return EAS_ERROR_PARAMETER_RANGE; 620 621 /* check to see if queue is full */ 622 p = &easHandle->jetHandle->segQueue[easHandle->jetHandle->queueSegment]; 623 if (p->streamHandle != NULL) 624 return EAS_ERROR_QUEUE_IS_FULL; 625 626 /* initialize data */ 627 p->userID = userID; 628 p->repeatCount = (EAS_I16) repeatCount; 629 p->transpose = (EAS_I8) transpose; 630 p->libNum = (EAS_I8) libNum; 631 p->muteFlags = muteFlags; 632 p->state = JET_STATE_CLOSED; 633 634 /* open the file */ 635 result = EAS_OpenJETStream(easHandle, easHandle->jetHandle->jetFileHandle, easHandle->jetHandle->segmentOffsets[segmentNum], &p->streamHandle); 636 if (result != EAS_SUCCESS) 637 return result; 638 p->state = JET_STATE_OPEN; 639 640 /* if less than SEG_QUEUE_DEPTH segments queued up, prepare file for playback */ 641 if (++easHandle->jetHandle->numQueuedSegments < SEG_QUEUE_DEPTH) 642 { 643 result = JET_PrepareSegment(easHandle, easHandle->jetHandle->queueSegment); 644 if (result != EAS_SUCCESS) 645 return result; 646 } 647 648 /* create duplicate file handle */ 649 result = EAS_HWDupHandle(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &fileHandle); 650 if (result != EAS_SUCCESS) 651 return result; 652 653 easHandle->jetHandle->jetFileHandle = fileHandle; 654 easHandle->jetHandle->queueSegment = (EAS_U8) JET_NextSegment(easHandle->jetHandle->queueSegment); 655 return result; 656 } 657 658 /*---------------------------------------------------------------------------- 659 * JET_Play() 660 *---------------------------------------------------------------------------- 661 * Starts playback of the file 662 *---------------------------------------------------------------------------- 663 */ 664 EAS_PUBLIC EAS_RESULT JET_Play (EAS_DATA_HANDLE easHandle) 665 { 666 EAS_RESULT result; 667 EAS_INT index; 668 EAS_INT count = 0; 669 670 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Play\n"); */ } 671 672 /* sanity check */ 673 if (easHandle->jetHandle->flags & JET_FLAGS_PLAYING) 674 return EAS_ERROR_NOT_VALID_IN_THIS_STATE; 675 676 /* resume all paused streams */ 677 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 678 { 679 if (((index == easHandle->jetHandle->playSegment) && (easHandle->jetHandle->segQueue[index].state == JET_STATE_READY)) || 680 (easHandle->jetHandle->segQueue[index].state == JET_STATE_PAUSED)) 681 { 682 result = JET_StartPlayback(easHandle, index); 683 if (result != EAS_SUCCESS) 684 return result; 685 count++; 686 } 687 } 688 689 /* if no streams are playing, return error */ 690 if (!count) 691 return EAS_ERROR_QUEUE_IS_EMPTY; 692 693 easHandle->jetHandle->flags |= JET_FLAGS_PLAYING; 694 return EAS_SUCCESS; 695 } 696 697 /*---------------------------------------------------------------------------- 698 * JET_Pause() 699 *---------------------------------------------------------------------------- 700 * Pauses playback of the file 701 *---------------------------------------------------------------------------- 702 */ 703 EAS_PUBLIC EAS_RESULT JET_Pause (EAS_DATA_HANDLE easHandle) 704 { 705 EAS_RESULT result; 706 EAS_INT index; 707 EAS_INT count = 0; 708 709 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Pause\n"); */ } 710 711 /* sanity check */ 712 if ((easHandle->jetHandle->flags & JET_FLAGS_PLAYING) == 0) 713 return EAS_ERROR_NOT_VALID_IN_THIS_STATE; 714 715 /* pause all playing streams */ 716 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 717 { 718 if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) 719 { 720 result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle); 721 if (result != EAS_SUCCESS) 722 return result; 723 easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].state = JET_STATE_PAUSED; 724 count++; 725 } 726 } 727 728 /* if no streams are paused, return error */ 729 if (!count) 730 return EAS_ERROR_QUEUE_IS_EMPTY; 731 732 easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; 733 return EAS_SUCCESS; 734 } 735 736 /*---------------------------------------------------------------------------- 737 * JET_SetMuteFlags() 738 *---------------------------------------------------------------------------- 739 * Change the state of the mute flags 740 *---------------------------------------------------------------------------- 741 */ 742 EAS_PUBLIC EAS_RESULT JET_SetMuteFlags (EAS_DATA_HANDLE easHandle, EAS_U32 muteFlags, EAS_BOOL sync) 743 { 744 S_JET_SEGMENT *pSeg; 745 746 /* get pointer to current segment */ 747 pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; 748 749 /* unsynchronized mute, set flags and return */ 750 if (!sync) 751 { 752 if (pSeg->streamHandle == NULL) 753 return EAS_ERROR_QUEUE_IS_EMPTY; 754 pSeg->muteFlags = muteFlags; 755 return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) muteFlags); 756 } 757 758 759 /* check for valid stream state */ 760 if (pSeg->state == JET_STATE_CLOSED) 761 return EAS_ERROR_QUEUE_IS_EMPTY; 762 763 /* save mute flags */ 764 pSeg->muteFlags = muteFlags; 765 766 /* if repeating segment, set mute update flag */ 767 if (sync) 768 pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; 769 return EAS_SUCCESS; 770 } 771 772 /*---------------------------------------------------------------------------- 773 * JET_SetMuteFlag() 774 *---------------------------------------------------------------------------- 775 * Change the state of a single mute flag 776 *---------------------------------------------------------------------------- 777 */ 778 EAS_PUBLIC EAS_RESULT JET_SetMuteFlag (EAS_DATA_HANDLE easHandle, EAS_INT trackNum, EAS_BOOL muteFlag, EAS_BOOL sync) 779 { 780 S_JET_SEGMENT *pSeg; 781 EAS_U32 trackMuteFlag; 782 783 784 /* setup flag */ 785 if ((trackNum < 0) || (trackNum > 31)) 786 return EAS_ERROR_PARAMETER_RANGE; 787 trackMuteFlag = (1 << trackNum); 788 789 /* get pointer to current segment */ 790 pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; 791 792 /* unsynchronized mute, set flags and return */ 793 if (!sync) 794 { 795 if (pSeg->streamHandle == NULL) 796 return EAS_ERROR_QUEUE_IS_EMPTY; 797 if (muteFlag) 798 pSeg->muteFlags |= trackMuteFlag; 799 else 800 pSeg->muteFlags &= ~trackMuteFlag; 801 return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 802 } 803 804 805 /* check for valid stream state */ 806 if (pSeg->state == JET_STATE_CLOSED) 807 return EAS_ERROR_QUEUE_IS_EMPTY; 808 809 /* save mute flags and set mute update flag */ 810 if (muteFlag) 811 pSeg->muteFlags |= trackMuteFlag; 812 else 813 pSeg->muteFlags &= ~trackMuteFlag; 814 pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; 815 return EAS_SUCCESS; 816 } 817 818 /*---------------------------------------------------------------------------- 819 * JET_TriggerClip() 820 *---------------------------------------------------------------------------- 821 * Unmute a track and then mute it when it is complete. If a clip 822 * is already playing, change mute event to a trigger event. The 823 * JET_Event function will not mute the clip, but will allow it 824 * to continue playing through the next clip. 825 * 826 * NOTE: We use bit 7 to indicate an entry in the queue. For a 827 * small queue, it is cheaper in both memory and CPU cycles to 828 * scan the entire queue for non-zero events than keep enqueue 829 * and dequeue indices. 830 *---------------------------------------------------------------------------- 831 */ 832 EAS_PUBLIC EAS_RESULT JET_TriggerClip (EAS_DATA_HANDLE easHandle, EAS_INT clipID) 833 { 834 EAS_INT i; 835 EAS_INT index = -1; 836 837 /* check for valid clipID */ 838 if ((clipID < 0) || (clipID > 63)) 839 return EAS_ERROR_PARAMETER_RANGE; 840 841 /* set active flag */ 842 clipID |= JET_CLIP_ACTIVE_FLAG; 843 844 /* Reverse the search so that we get the first empty element */ 845 for (i = JET_MUTE_QUEUE_SIZE-1; i >= 0 ; i--) 846 { 847 if (easHandle->jetHandle->muteQueue[i] == clipID) 848 { 849 index = i; 850 break; 851 } 852 if (easHandle->jetHandle->muteQueue[i] == 0) 853 index = i; 854 } 855 if (index < 0) 856 return EAS_ERROR_QUEUE_IS_FULL; 857 858 easHandle->jetHandle->muteQueue[index] = (EAS_U8) clipID | JET_CLIP_TRIGGER_FLAG; 859 return EAS_SUCCESS; 860 } 861 862 /*---------------------------------------------------------------------------- 863 * JET_Process() 864 *---------------------------------------------------------------------------- 865 * Called during EAS_Render to process stream states 866 *---------------------------------------------------------------------------- 867 */ 868 EAS_PUBLIC EAS_RESULT JET_Process (EAS_DATA_HANDLE easHandle) 869 { 870 S_JET_SEGMENT *pSeg; 871 EAS_STATE state; 872 EAS_INT index; 873 EAS_INT playIndex; 874 EAS_RESULT result = EAS_SUCCESS; 875 EAS_BOOL endOfLoop = EAS_FALSE; 876 EAS_BOOL startNextSegment = EAS_FALSE; 877 EAS_BOOL prepareNextSegment = EAS_FALSE; 878 EAS_U32 jetEvent; 879 880 /* process event queue */ 881 while (JET_ReadQueue(easHandle->jetHandle->jetEventQueue, 882 &easHandle->jetHandle->jetEventQueueRead, 883 easHandle->jetHandle->jetEventQueueWrite, 884 JET_EVENT_QUEUE_SIZE, &jetEvent)) 885 { 886 S_JET_EVENT event; 887 #ifdef DEBUG_JET 888 JET_DumpEvent("JET_Process", jetEvent); 889 #endif 890 JET_ParseEvent(jetEvent, &event); 891 892 /* check for end of loop */ 893 if ((event.controller == JET_EVENT_MARKER) && 894 (event.value == JET_MARKER_LOOP_END) && 895 (easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle != NULL)) 896 endOfLoop = EAS_TRUE; 897 } 898 899 /* check state of all streams */ 900 index = playIndex = easHandle->jetHandle->playSegment; 901 for (;;) 902 { 903 pSeg = &easHandle->jetHandle->segQueue[index]; 904 if (pSeg->state != JET_STATE_CLOSED) 905 { 906 907 /* get playback state */ 908 result = EAS_State(easHandle, pSeg->streamHandle, &state); 909 if (result != EAS_SUCCESS) 910 return result; 911 912 /* process state */ 913 switch (pSeg->state) 914 { 915 /* take action if this segment is stopping */ 916 case JET_STATE_PLAYING: 917 if (endOfLoop || (state == EAS_STATE_STOPPING) || (state == EAS_STATE_STOPPED)) 918 { 919 /* handle repeats */ 920 if (pSeg->repeatCount != 0) 921 { 922 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render repeating segment %d\n", index); */ } 923 result = EAS_Locate(easHandle, pSeg->streamHandle, 0, EAS_FALSE); 924 if (result != EAS_SUCCESS) 925 return result; 926 if (pSeg->repeatCount > 0) 927 pSeg->repeatCount--; 928 929 /* update mute flags if necessary */ 930 if (pSeg->flags & JET_SEG_FLAG_MUTE_UPDATE) 931 { 932 result = EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 933 if (result != EAS_SUCCESS) 934 return result; 935 pSeg->flags &= ~JET_SEG_FLAG_MUTE_UPDATE; 936 } 937 938 } 939 /* no repeat, start next segment */ 940 else 941 { 942 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render stopping queue %d\n", index); */ } 943 startNextSegment = EAS_TRUE; 944 pSeg->state = JET_STATE_STOPPING; 945 easHandle->jetHandle->playSegment = (EAS_U8) JET_NextSegment(index); 946 } 947 } 948 break; 949 950 /* if playback has stopped, close the segment */ 951 case JET_STATE_STOPPING: 952 if (state == EAS_STATE_STOPPED) 953 { 954 result = JET_CloseSegment(easHandle, index); 955 if (result != EAS_SUCCESS) 956 return result; 957 } 958 break; 959 960 case JET_STATE_READY: 961 if (startNextSegment) 962 { 963 result = JET_StartPlayback(easHandle, index); 964 if (result != EAS_SUCCESS) 965 return result; 966 startNextSegment = EAS_FALSE; 967 prepareNextSegment = EAS_TRUE; 968 } 969 break; 970 971 case JET_STATE_OPEN: 972 if (prepareNextSegment) 973 { 974 result = JET_PrepareSegment(easHandle, index); 975 if (result != EAS_SUCCESS) 976 return result; 977 prepareNextSegment = EAS_FALSE; 978 } 979 break; 980 981 case JET_STATE_PAUSED: 982 break; 983 984 default: 985 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "JET_Render: Unexpected segment state %d\n", pSeg->state); */ } 986 break; 987 } 988 } 989 990 /* increment index */ 991 index = JET_NextSegment(index); 992 if (index == playIndex) 993 break; 994 } 995 996 /* if out of segments, clear playing flag */ 997 if (easHandle->jetHandle->numQueuedSegments == 0) 998 easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; 999 1000 return result; 1001 } 1002 1003 /*---------------------------------------------------------------------------- 1004 * JET_Event() 1005 *---------------------------------------------------------------------------- 1006 * Called from MIDI parser when data of interest is received 1007 *---------------------------------------------------------------------------- 1008 */ 1009 void JET_Event (EAS_DATA_HANDLE easHandle, EAS_U32 segTrack, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) 1010 { 1011 EAS_U32 event; 1012 1013 if (easHandle->jetHandle == NULL) 1014 return; 1015 1016 /* handle triggers */ 1017 if (controller == JET_EVENT_TRIGGER_CLIP) 1018 { 1019 S_JET_SEGMENT *pSeg; 1020 EAS_INT i; 1021 EAS_U32 muteFlag; 1022 1023 for (i = 0; i < JET_MUTE_QUEUE_SIZE; i++) 1024 { 1025 /* search for event in queue */ 1026 if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_ID_MASK) == (value & JET_CLIP_ID_MASK)) 1027 { 1028 /* get segment pointer and mute flag */ 1029 pSeg = &easHandle->jetHandle->segQueue[segTrack >> JET_EVENT_SEG_SHIFT]; 1030 muteFlag = 1 << ((segTrack & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT); 1031 1032 /* un-mute the track */ 1033 if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_TRIGGER_FLAG) && ((value & 0x40) > 0)) 1034 { 1035 pSeg->muteFlags &= ~muteFlag; 1036 easHandle->jetHandle->muteQueue[i] &= ~JET_CLIP_TRIGGER_FLAG; 1037 } 1038 1039 /* mute the track */ 1040 else 1041 { 1042 EAS_U32 beforeMute ; 1043 beforeMute = pSeg->muteFlags ; 1044 pSeg->muteFlags |= muteFlag; 1045 if (beforeMute != pSeg->muteFlags) 1046 easHandle->jetHandle->muteQueue[i] = 0; 1047 } 1048 EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 1049 return; 1050 } 1051 } 1052 return; 1053 } 1054 1055 /* generic event stuff */ 1056 event = (channel << JET_EVENT_CHAN_SHIFT) | (controller << JET_EVENT_CTRL_SHIFT) | value; 1057 1058 /* write to app queue, translate queue index to segment number */ 1059 if ((controller >= easHandle->jetHandle->config.appEventRangeLow) && (controller <= easHandle->jetHandle->config.appEventRangeHigh)) 1060 { 1061 1062 event |= easHandle->jetHandle->segQueue[(segTrack & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT].userID << JET_EVENT_SEG_SHIFT; 1063 #ifdef DEBUG_JET 1064 JET_DumpEvent("JET_Event[app]", event); 1065 #endif 1066 JET_WriteQueue(easHandle->jetHandle->appEventQueue, 1067 &easHandle->jetHandle->appEventQueueWrite, 1068 easHandle->jetHandle->appEventQueueRead, 1069 APP_EVENT_QUEUE_SIZE, 1070 event); 1071 } 1072 1073 /* write to JET queue */ 1074 else if ((controller >= JET_EVENT_LOW) && (controller <= JET_EVENT_HIGH)) 1075 { 1076 event |= segTrack; 1077 #ifdef DEBUG_JET 1078 JET_DumpEvent("JET_Event[jet]", event); 1079 #endif 1080 JET_WriteQueue(easHandle->jetHandle->jetEventQueue, 1081 &easHandle->jetHandle->jetEventQueueWrite, 1082 easHandle->jetHandle->jetEventQueueRead, 1083 JET_EVENT_QUEUE_SIZE, 1084 event); 1085 } 1086 } 1087 1088 /*---------------------------------------------------------------------------- 1089 * JET_Clear_Queue() 1090 *---------------------------------------------------------------------------- 1091 * Clears the queue and stops play without a complete shutdown 1092 *---------------------------------------------------------------------------- 1093 */ 1094 EAS_RESULT JET_Clear_Queue(EAS_DATA_HANDLE easHandle) 1095 { 1096 EAS_INT index; 1097 EAS_RESULT result = EAS_SUCCESS; 1098 1099 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Clear_Queue\n"); */ } 1100 1101 /* pause all playing streams */ 1102 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 1103 { 1104 if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) 1105 { 1106 result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[index].streamHandle); 1107 if (result != EAS_SUCCESS) 1108 return result; 1109 1110 easHandle->jetHandle->segQueue[index].state = JET_STATE_PAUSED; 1111 } 1112 } 1113 1114 /* close all streams */ 1115 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 1116 { 1117 if (easHandle->jetHandle->segQueue[index].streamHandle != NULL) 1118 { 1119 result = JET_CloseSegment(easHandle, index); 1120 if (result != EAS_SUCCESS) 1121 return result; 1122 } 1123 } 1124 1125 /* clear all clips */ 1126 for (index = 0; index < JET_MUTE_QUEUE_SIZE ; index++) 1127 { 1128 easHandle->jetHandle->muteQueue[index] = 0; 1129 } 1130 1131 easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; 1132 easHandle->jetHandle->playSegment = easHandle->jetHandle->queueSegment = 0; 1133 return result; 1134 } 1135 1136