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 int i; 522 523 /* close any open files */ 524 result = JET_CloseFile(easHandle); 525 526 /* free allocated data */ 527 for(i = 0 ; i < easHandle->jetHandle->numLibraries ; i++) { 528 if(easHandle->jetHandle->libHandles[i] != NULL) { 529 EAS_HWFree(easHandle->hwInstData, easHandle->jetHandle->libHandles[i]); 530 easHandle->jetHandle->libHandles[i] = NULL; 531 } 532 } 533 534 EAS_HWFree(easHandle->hwInstData, easHandle->jetHandle); 535 easHandle->jetHandle = NULL; 536 return result; 537 } 538 539 /*---------------------------------------------------------------------------- 540 * JET_Status() 541 *---------------------------------------------------------------------------- 542 * Returns current status 543 *---------------------------------------------------------------------------- 544 */ 545 EAS_PUBLIC EAS_RESULT JET_Status (EAS_DATA_HANDLE easHandle, S_JET_STATUS *pStatus) 546 { 547 S_JET_SEGMENT *pSeg; 548 549 pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; 550 if (pSeg->streamHandle != NULL) 551 { 552 pStatus->currentUserID = pSeg->userID; 553 pStatus->segmentRepeatCount = pSeg->repeatCount; 554 } 555 else 556 { 557 pStatus->currentUserID = -1; 558 pStatus->segmentRepeatCount = 0; 559 } 560 561 pStatus->paused = !(easHandle->jetHandle->flags & JET_FLAGS_PLAYING); 562 pStatus->numQueuedSegments = easHandle->jetHandle->numQueuedSegments; 563 pStatus->currentPlayingSegment = easHandle->jetHandle->playSegment; 564 pStatus->currentQueuedSegment = easHandle->jetHandle->queueSegment; 565 if (pSeg->streamHandle != NULL) 566 { 567 EAS_RESULT result; 568 EAS_I32 location ; 569 if ((result = EAS_GetLocation(easHandle, pSeg->streamHandle, &location)) == EAS_SUCCESS) 570 if(location != 0) 571 { 572 pStatus->location = location; 573 } 574 } 575 return EAS_SUCCESS; 576 } 577 578 /*---------------------------------------------------------------------------- 579 * JET_GetEvent() 580 *---------------------------------------------------------------------------- 581 * Checks for application events 582 *---------------------------------------------------------------------------- 583 */ 584 EAS_PUBLIC EAS_BOOL JET_GetEvent (EAS_DATA_HANDLE easHandle, EAS_U32 *pEventRaw, S_JET_EVENT *pEvent) 585 { 586 EAS_U32 jetEvent; 587 EAS_BOOL gotEvent; 588 589 /* process event queue */ 590 gotEvent = JET_ReadQueue(easHandle->jetHandle->appEventQueue, 591 &easHandle->jetHandle->appEventQueueRead, 592 easHandle->jetHandle->appEventQueueWrite, 593 APP_EVENT_QUEUE_SIZE, &jetEvent); 594 595 if (gotEvent) 596 { 597 if (pEventRaw != NULL) 598 *pEventRaw = jetEvent; 599 600 if (pEvent != NULL) 601 JET_ParseEvent(jetEvent, pEvent); 602 } 603 604 return gotEvent; 605 } 606 607 /*---------------------------------------------------------------------------- 608 * JET_QueueSegment() 609 *---------------------------------------------------------------------------- 610 * Queue a segment for playback 611 *---------------------------------------------------------------------------- 612 */ 613 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) 614 { 615 EAS_FILE_HANDLE fileHandle; 616 EAS_RESULT result; 617 S_JET_SEGMENT *p; 618 619 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_QueueSegment segNum=%d, queue=%d\n", segmentNum, easHandle->jetHandle->queueSegment); */ } 620 621 /* make sure it's a valid segment */ 622 if (segmentNum >= easHandle->jetHandle->numSegments) 623 return EAS_ERROR_PARAMETER_RANGE; 624 625 /* make sure it's a valid DLS */ 626 if (libNum >= easHandle->jetHandle->numLibraries) 627 return EAS_ERROR_PARAMETER_RANGE; 628 629 /* check to see if queue is full */ 630 p = &easHandle->jetHandle->segQueue[easHandle->jetHandle->queueSegment]; 631 if (p->streamHandle != NULL) 632 return EAS_ERROR_QUEUE_IS_FULL; 633 634 /* initialize data */ 635 p->userID = userID; 636 p->repeatCount = (EAS_I16) repeatCount; 637 p->transpose = (EAS_I8) transpose; 638 p->libNum = (EAS_I8) libNum; 639 p->muteFlags = muteFlags; 640 p->state = JET_STATE_CLOSED; 641 642 /* open the file */ 643 result = EAS_OpenJETStream(easHandle, easHandle->jetHandle->jetFileHandle, easHandle->jetHandle->segmentOffsets[segmentNum], &p->streamHandle); 644 if (result != EAS_SUCCESS) 645 return result; 646 p->state = JET_STATE_OPEN; 647 648 /* if less than SEG_QUEUE_DEPTH segments queued up, prepare file for playback */ 649 if (++easHandle->jetHandle->numQueuedSegments < SEG_QUEUE_DEPTH) 650 { 651 result = JET_PrepareSegment(easHandle, easHandle->jetHandle->queueSegment); 652 if (result != EAS_SUCCESS) 653 return result; 654 } 655 656 /* create duplicate file handle */ 657 result = EAS_HWDupHandle(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &fileHandle); 658 if (result != EAS_SUCCESS) 659 return result; 660 661 easHandle->jetHandle->jetFileHandle = fileHandle; 662 easHandle->jetHandle->queueSegment = (EAS_U8) JET_NextSegment(easHandle->jetHandle->queueSegment); 663 return result; 664 } 665 666 /*---------------------------------------------------------------------------- 667 * JET_Play() 668 *---------------------------------------------------------------------------- 669 * Starts playback of the file 670 *---------------------------------------------------------------------------- 671 */ 672 EAS_PUBLIC EAS_RESULT JET_Play (EAS_DATA_HANDLE easHandle) 673 { 674 EAS_RESULT result; 675 EAS_INT index; 676 EAS_INT count = 0; 677 678 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Play\n"); */ } 679 680 /* sanity check */ 681 if (easHandle->jetHandle->flags & JET_FLAGS_PLAYING) 682 return EAS_ERROR_NOT_VALID_IN_THIS_STATE; 683 684 /* resume all paused streams */ 685 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 686 { 687 if (((index == easHandle->jetHandle->playSegment) && (easHandle->jetHandle->segQueue[index].state == JET_STATE_READY)) || 688 (easHandle->jetHandle->segQueue[index].state == JET_STATE_PAUSED)) 689 { 690 result = JET_StartPlayback(easHandle, index); 691 if (result != EAS_SUCCESS) 692 return result; 693 count++; 694 } 695 } 696 697 /* if no streams are playing, return error */ 698 if (!count) 699 return EAS_ERROR_QUEUE_IS_EMPTY; 700 701 easHandle->jetHandle->flags |= JET_FLAGS_PLAYING; 702 return EAS_SUCCESS; 703 } 704 705 /*---------------------------------------------------------------------------- 706 * JET_Pause() 707 *---------------------------------------------------------------------------- 708 * Pauses playback of the file 709 *---------------------------------------------------------------------------- 710 */ 711 EAS_PUBLIC EAS_RESULT JET_Pause (EAS_DATA_HANDLE easHandle) 712 { 713 EAS_RESULT result; 714 EAS_INT index; 715 EAS_INT count = 0; 716 717 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Pause\n"); */ } 718 719 /* sanity check */ 720 if ((easHandle->jetHandle->flags & JET_FLAGS_PLAYING) == 0) 721 return EAS_ERROR_NOT_VALID_IN_THIS_STATE; 722 723 /* pause all playing streams */ 724 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 725 { 726 if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) 727 { 728 result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle); 729 if (result != EAS_SUCCESS) 730 return result; 731 easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].state = JET_STATE_PAUSED; 732 count++; 733 } 734 } 735 736 /* if no streams are paused, return error */ 737 if (!count) 738 return EAS_ERROR_QUEUE_IS_EMPTY; 739 740 easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; 741 return EAS_SUCCESS; 742 } 743 744 /*---------------------------------------------------------------------------- 745 * JET_SetMuteFlags() 746 *---------------------------------------------------------------------------- 747 * Change the state of the mute flags 748 *---------------------------------------------------------------------------- 749 */ 750 EAS_PUBLIC EAS_RESULT JET_SetMuteFlags (EAS_DATA_HANDLE easHandle, EAS_U32 muteFlags, EAS_BOOL sync) 751 { 752 S_JET_SEGMENT *pSeg; 753 754 /* get pointer to current segment */ 755 pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; 756 757 /* unsynchronized mute, set flags and return */ 758 if (!sync) 759 { 760 if (pSeg->streamHandle == NULL) 761 return EAS_ERROR_QUEUE_IS_EMPTY; 762 pSeg->muteFlags = muteFlags; 763 return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) muteFlags); 764 } 765 766 767 /* check for valid stream state */ 768 if (pSeg->state == JET_STATE_CLOSED) 769 return EAS_ERROR_QUEUE_IS_EMPTY; 770 771 /* save mute flags */ 772 pSeg->muteFlags = muteFlags; 773 774 /* if repeating segment, set mute update flag */ 775 if (sync) 776 pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; 777 return EAS_SUCCESS; 778 } 779 780 /*---------------------------------------------------------------------------- 781 * JET_SetMuteFlag() 782 *---------------------------------------------------------------------------- 783 * Change the state of a single mute flag 784 *---------------------------------------------------------------------------- 785 */ 786 EAS_PUBLIC EAS_RESULT JET_SetMuteFlag (EAS_DATA_HANDLE easHandle, EAS_INT trackNum, EAS_BOOL muteFlag, EAS_BOOL sync) 787 { 788 S_JET_SEGMENT *pSeg; 789 EAS_U32 trackMuteFlag; 790 791 792 /* setup flag */ 793 if ((trackNum < 0) || (trackNum > 31)) 794 return EAS_ERROR_PARAMETER_RANGE; 795 trackMuteFlag = (1 << trackNum); 796 797 /* get pointer to current segment */ 798 pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; 799 800 /* unsynchronized mute, set flags and return */ 801 if (!sync) 802 { 803 if (pSeg->streamHandle == NULL) 804 return EAS_ERROR_QUEUE_IS_EMPTY; 805 if (muteFlag) 806 pSeg->muteFlags |= trackMuteFlag; 807 else 808 pSeg->muteFlags &= ~trackMuteFlag; 809 return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 810 } 811 812 813 /* check for valid stream state */ 814 if (pSeg->state == JET_STATE_CLOSED) 815 return EAS_ERROR_QUEUE_IS_EMPTY; 816 817 /* save mute flags and set mute update flag */ 818 if (muteFlag) 819 pSeg->muteFlags |= trackMuteFlag; 820 else 821 pSeg->muteFlags &= ~trackMuteFlag; 822 pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; 823 return EAS_SUCCESS; 824 } 825 826 /*---------------------------------------------------------------------------- 827 * JET_TriggerClip() 828 *---------------------------------------------------------------------------- 829 * Unmute a track and then mute it when it is complete. If a clip 830 * is already playing, change mute event to a trigger event. The 831 * JET_Event function will not mute the clip, but will allow it 832 * to continue playing through the next clip. 833 * 834 * NOTE: We use bit 7 to indicate an entry in the queue. For a 835 * small queue, it is cheaper in both memory and CPU cycles to 836 * scan the entire queue for non-zero events than keep enqueue 837 * and dequeue indices. 838 *---------------------------------------------------------------------------- 839 */ 840 EAS_PUBLIC EAS_RESULT JET_TriggerClip (EAS_DATA_HANDLE easHandle, EAS_INT clipID) 841 { 842 EAS_INT i; 843 EAS_INT index = -1; 844 845 /* check for valid clipID */ 846 if ((clipID < 0) || (clipID > 63)) 847 return EAS_ERROR_PARAMETER_RANGE; 848 849 /* set active flag */ 850 clipID |= JET_CLIP_ACTIVE_FLAG; 851 852 /* Reverse the search so that we get the first empty element */ 853 for (i = JET_MUTE_QUEUE_SIZE-1; i >= 0 ; i--) 854 { 855 if (easHandle->jetHandle->muteQueue[i] == clipID) 856 { 857 index = i; 858 break; 859 } 860 if (easHandle->jetHandle->muteQueue[i] == 0) 861 index = i; 862 } 863 if (index < 0) 864 return EAS_ERROR_QUEUE_IS_FULL; 865 866 easHandle->jetHandle->muteQueue[index] = (EAS_U8) clipID | JET_CLIP_TRIGGER_FLAG; 867 return EAS_SUCCESS; 868 } 869 870 /*---------------------------------------------------------------------------- 871 * JET_Process() 872 *---------------------------------------------------------------------------- 873 * Called during EAS_Render to process stream states 874 *---------------------------------------------------------------------------- 875 */ 876 EAS_PUBLIC EAS_RESULT JET_Process (EAS_DATA_HANDLE easHandle) 877 { 878 S_JET_SEGMENT *pSeg; 879 EAS_STATE state; 880 EAS_INT index; 881 EAS_INT playIndex; 882 EAS_RESULT result = EAS_SUCCESS; 883 EAS_BOOL endOfLoop = EAS_FALSE; 884 EAS_BOOL startNextSegment = EAS_FALSE; 885 EAS_BOOL prepareNextSegment = EAS_FALSE; 886 EAS_U32 jetEvent; 887 888 /* process event queue */ 889 while (JET_ReadQueue(easHandle->jetHandle->jetEventQueue, 890 &easHandle->jetHandle->jetEventQueueRead, 891 easHandle->jetHandle->jetEventQueueWrite, 892 JET_EVENT_QUEUE_SIZE, &jetEvent)) 893 { 894 S_JET_EVENT event; 895 #ifdef DEBUG_JET 896 JET_DumpEvent("JET_Process", jetEvent); 897 #endif 898 JET_ParseEvent(jetEvent, &event); 899 900 /* check for end of loop */ 901 if ((event.controller == JET_EVENT_MARKER) && 902 (event.value == JET_MARKER_LOOP_END) && 903 (easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle != NULL)) 904 endOfLoop = EAS_TRUE; 905 } 906 907 /* check state of all streams */ 908 index = playIndex = easHandle->jetHandle->playSegment; 909 for (;;) 910 { 911 pSeg = &easHandle->jetHandle->segQueue[index]; 912 if (pSeg->state != JET_STATE_CLOSED) 913 { 914 915 /* get playback state */ 916 result = EAS_State(easHandle, pSeg->streamHandle, &state); 917 if (result != EAS_SUCCESS) 918 return result; 919 920 /* process state */ 921 switch (pSeg->state) 922 { 923 /* take action if this segment is stopping */ 924 case JET_STATE_PLAYING: 925 if (endOfLoop || (state == EAS_STATE_STOPPING) || (state == EAS_STATE_STOPPED)) 926 { 927 /* handle repeats */ 928 if (pSeg->repeatCount != 0) 929 { 930 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render repeating segment %d\n", index); */ } 931 result = EAS_Locate(easHandle, pSeg->streamHandle, 0, EAS_FALSE); 932 if (result != EAS_SUCCESS) 933 return result; 934 if (pSeg->repeatCount > 0) 935 pSeg->repeatCount--; 936 937 /* update mute flags if necessary */ 938 if (pSeg->flags & JET_SEG_FLAG_MUTE_UPDATE) 939 { 940 result = EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 941 if (result != EAS_SUCCESS) 942 return result; 943 pSeg->flags &= ~JET_SEG_FLAG_MUTE_UPDATE; 944 } 945 946 } 947 /* no repeat, start next segment */ 948 else 949 { 950 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render stopping queue %d\n", index); */ } 951 startNextSegment = EAS_TRUE; 952 pSeg->state = JET_STATE_STOPPING; 953 easHandle->jetHandle->playSegment = (EAS_U8) JET_NextSegment(index); 954 } 955 } 956 break; 957 958 /* if playback has stopped, close the segment */ 959 case JET_STATE_STOPPING: 960 if (state == EAS_STATE_STOPPED) 961 { 962 result = JET_CloseSegment(easHandle, index); 963 if (result != EAS_SUCCESS) 964 return result; 965 } 966 break; 967 968 case JET_STATE_READY: 969 if (startNextSegment) 970 { 971 result = JET_StartPlayback(easHandle, index); 972 if (result != EAS_SUCCESS) 973 return result; 974 startNextSegment = EAS_FALSE; 975 prepareNextSegment = EAS_TRUE; 976 } 977 break; 978 979 case JET_STATE_OPEN: 980 if (prepareNextSegment) 981 { 982 result = JET_PrepareSegment(easHandle, index); 983 if (result != EAS_SUCCESS) 984 return result; 985 prepareNextSegment = EAS_FALSE; 986 } 987 break; 988 989 case JET_STATE_PAUSED: 990 break; 991 992 default: 993 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "JET_Render: Unexpected segment state %d\n", pSeg->state); */ } 994 break; 995 } 996 } 997 998 /* increment index */ 999 index = JET_NextSegment(index); 1000 if (index == playIndex) 1001 break; 1002 } 1003 1004 /* if out of segments, clear playing flag */ 1005 if (easHandle->jetHandle->numQueuedSegments == 0) 1006 easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; 1007 1008 return result; 1009 } 1010 1011 /*---------------------------------------------------------------------------- 1012 * JET_Event() 1013 *---------------------------------------------------------------------------- 1014 * Called from MIDI parser when data of interest is received 1015 *---------------------------------------------------------------------------- 1016 */ 1017 void JET_Event (EAS_DATA_HANDLE easHandle, EAS_U32 segTrack, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) 1018 { 1019 EAS_U32 event; 1020 1021 if (easHandle->jetHandle == NULL) 1022 return; 1023 1024 /* handle triggers */ 1025 if (controller == JET_EVENT_TRIGGER_CLIP) 1026 { 1027 S_JET_SEGMENT *pSeg; 1028 EAS_INT i; 1029 EAS_U32 muteFlag; 1030 1031 for (i = 0; i < JET_MUTE_QUEUE_SIZE; i++) 1032 { 1033 /* search for event in queue */ 1034 if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_ID_MASK) == (value & JET_CLIP_ID_MASK)) 1035 { 1036 /* get segment pointer and mute flag */ 1037 pSeg = &easHandle->jetHandle->segQueue[segTrack >> JET_EVENT_SEG_SHIFT]; 1038 muteFlag = 1 << ((segTrack & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT); 1039 1040 /* un-mute the track */ 1041 if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_TRIGGER_FLAG) && ((value & 0x40) > 0)) 1042 { 1043 pSeg->muteFlags &= ~muteFlag; 1044 easHandle->jetHandle->muteQueue[i] &= ~JET_CLIP_TRIGGER_FLAG; 1045 } 1046 1047 /* mute the track */ 1048 else 1049 { 1050 EAS_U32 beforeMute ; 1051 beforeMute = pSeg->muteFlags ; 1052 pSeg->muteFlags |= muteFlag; 1053 if (beforeMute != pSeg->muteFlags) 1054 easHandle->jetHandle->muteQueue[i] = 0; 1055 } 1056 EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 1057 return; 1058 } 1059 } 1060 return; 1061 } 1062 1063 /* generic event stuff */ 1064 event = (channel << JET_EVENT_CHAN_SHIFT) | (controller << JET_EVENT_CTRL_SHIFT) | value; 1065 1066 /* write to app queue, translate queue index to segment number */ 1067 if ((controller >= easHandle->jetHandle->config.appEventRangeLow) && (controller <= easHandle->jetHandle->config.appEventRangeHigh)) 1068 { 1069 1070 event |= easHandle->jetHandle->segQueue[(segTrack & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT].userID << JET_EVENT_SEG_SHIFT; 1071 #ifdef DEBUG_JET 1072 JET_DumpEvent("JET_Event[app]", event); 1073 #endif 1074 JET_WriteQueue(easHandle->jetHandle->appEventQueue, 1075 &easHandle->jetHandle->appEventQueueWrite, 1076 easHandle->jetHandle->appEventQueueRead, 1077 APP_EVENT_QUEUE_SIZE, 1078 event); 1079 } 1080 1081 /* write to JET queue */ 1082 else if ((controller >= JET_EVENT_LOW) && (controller <= JET_EVENT_HIGH)) 1083 { 1084 event |= segTrack; 1085 #ifdef DEBUG_JET 1086 JET_DumpEvent("JET_Event[jet]", event); 1087 #endif 1088 JET_WriteQueue(easHandle->jetHandle->jetEventQueue, 1089 &easHandle->jetHandle->jetEventQueueWrite, 1090 easHandle->jetHandle->jetEventQueueRead, 1091 JET_EVENT_QUEUE_SIZE, 1092 event); 1093 } 1094 } 1095 1096 /*---------------------------------------------------------------------------- 1097 * JET_Clear_Queue() 1098 *---------------------------------------------------------------------------- 1099 * Clears the queue and stops play without a complete shutdown 1100 *---------------------------------------------------------------------------- 1101 */ 1102 EAS_RESULT JET_Clear_Queue(EAS_DATA_HANDLE easHandle) 1103 { 1104 EAS_INT index; 1105 EAS_RESULT result = EAS_SUCCESS; 1106 1107 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Clear_Queue\n"); */ } 1108 1109 /* pause all playing streams */ 1110 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 1111 { 1112 if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) 1113 { 1114 result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[index].streamHandle); 1115 if (result != EAS_SUCCESS) 1116 return result; 1117 1118 easHandle->jetHandle->segQueue[index].state = JET_STATE_PAUSED; 1119 } 1120 } 1121 1122 /* close all streams */ 1123 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 1124 { 1125 if (easHandle->jetHandle->segQueue[index].streamHandle != NULL) 1126 { 1127 result = JET_CloseSegment(easHandle, index); 1128 if (result != EAS_SUCCESS) 1129 return result; 1130 } 1131 } 1132 1133 /* clear all clips */ 1134 for (index = 0; index < JET_MUTE_QUEUE_SIZE ; index++) 1135 { 1136 easHandle->jetHandle->muteQueue[index] = 0; 1137 } 1138 1139 easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; 1140 easHandle->jetHandle->playSegment = easHandle->jetHandle->queueSegment = 0; 1141 return result; 1142 } 1143 1144