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 */ 42static const S_JET_CONFIG jetDefaultConfig = 43{ 44 JET_EVENT_APP_LOW, 45 JET_EVENT_APP_HIGH 46}; 47 48/* function prototypes */ 49extern EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value); 50extern EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream); 51extern 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*/ 59EAS_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*/ 75static 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*/ 90EAS_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*/ 103EAS_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*/ 126EAS_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*/ 145EAS_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*/ 158static 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*/ 207static 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*/ 234EAS_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*/ 257static 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 easHandle->jetHandle->numSegments = (EAS_U8) temp; 286 break; 287 288 case INFO_NUM_DLS_CHUNKS: 289 easHandle->jetHandle->numLibraries = (EAS_U8) temp; 290 break; 291 292 case INFO_JET_VERSION: 293 /* check major version number */ 294 if ((temp & 0xff000000) != (JET_VERSION & 0xff000000)) 295 return EAS_ERROR_INCOMPATIBLE_VERSION; 296 break; 297 298 default: 299 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized JET info type 0x%08x", infoType); */ } 300 break; 301 } 302 303 chunkSize -= 8; 304 } 305 306 /* allocate pointers for chunks to follow */ 307 308 return result; 309} 310 311/*---------------------------------------------------------------------------- 312 * JET_OpenFile() 313 *---------------------------------------------------------------------------- 314 * Opens a JET content file for playback 315 *---------------------------------------------------------------------------- 316*/ 317EAS_PUBLIC EAS_RESULT JET_OpenFile (EAS_DATA_HANDLE easHandle, EAS_FILE_LOCATOR locator) 318{ 319 EAS_RESULT result; 320 EAS_U32 chunkType; 321 EAS_I32 pos; 322 EAS_I32 chunkSize; 323 EAS_INT smfChunkNum; 324 EAS_INT dlsChunkNum; 325 EAS_I32 dataSize = 0; /* make lint happy */ 326 327 /* make sure that we don't have an open file */ 328 if (easHandle->jetHandle->jetFileHandle != NULL) 329 return EAS_ERROR_FILE_ALREADY_OPEN; 330 331 /* open the media file */ 332 result = EAS_HWOpenFile(easHandle->hwInstData, locator, &easHandle->jetHandle->jetFileHandle, EAS_FILE_READ); 333 if (result != EAS_SUCCESS) 334 return result; 335 336 /* check header */ 337 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkType, EAS_TRUE); 338 if (result == EAS_SUCCESS) 339 { 340 if (chunkType != JET_HEADER_TAG) 341 { 342 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "File is not JET format\n"); */ } 343 result = EAS_ERROR_UNRECOGNIZED_FORMAT; 344 } 345 } 346 /* get the file data size */ 347 if (result == EAS_SUCCESS) 348 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &dataSize, EAS_FALSE); 349 350 /* parse through the file to find contents */ 351 smfChunkNum = dlsChunkNum = 0; 352 pos = chunkSize = 8; 353 while ((result == EAS_SUCCESS) && (pos < dataSize)) 354 { 355 356 /* offset to chunk data */ 357 result = EAS_HWFileSeek(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos); 358 if (result != EAS_SUCCESS) 359 break; 360 361 /* get chunk size and type */ 362 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkType, EAS_TRUE); 363 if (result != EAS_SUCCESS) 364 break; 365 366 result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkSize, EAS_FALSE); 367 if (result != EAS_SUCCESS) 368 break; 369 pos += 8; 370 371 switch (chunkType) 372 { 373 case JET_INFO_CHUNK: 374 result = JetParseInfoChunk(easHandle, pos, chunkSize); 375 break; 376 377 case JET_SMF_CHUNK: 378 if (smfChunkNum < easHandle->jetHandle->numSegments) 379 easHandle->jetHandle->segmentOffsets[smfChunkNum++] = pos; 380 else 381 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring extraneous SMF chunk"); */ } 382 break; 383 384 case JET_DLS_CHUNK: 385 if (dlsChunkNum < easHandle->jetHandle->numLibraries) 386 result = DLSParser(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos, &easHandle->jetHandle->libHandles[dlsChunkNum++]); 387 else 388 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring extraneous DLS chunk"); */ } 389 break; 390 391 case JET_APP_DATA_CHUNK: 392 easHandle->jetHandle->appDataOffset = pos; 393 easHandle->jetHandle->appDataSize = chunkSize; 394 break; 395 396 case INFO_JET_COPYRIGHT: 397 break; 398 399 default: 400 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized JET chunk type 0x%08x", chunkType); */ } 401 break; 402 } 403 404 /* offset to next chunk */ 405 pos += chunkSize; 406 } 407 408 /* close file if something went wrong */ 409 if (result != EAS_SUCCESS) 410 EAS_HWCloseFile(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle); 411 412 return result; 413} 414 415/*---------------------------------------------------------------------------- 416 * JET_GetAppData() 417 *---------------------------------------------------------------------------- 418 * Returns location and size of application data in the JET file 419 *---------------------------------------------------------------------------- 420*/ 421EAS_RESULT JET_GetAppData (EAS_DATA_HANDLE easHandle, EAS_I32 *pAppDataOffset, EAS_I32 *pAppDataSize) 422{ 423 424 /* check for app chunk */ 425 if (easHandle->jetHandle->appDataSize == 0) 426 { 427 *pAppDataOffset = *pAppDataSize = 0; 428 return EAS_FAILURE; 429 } 430 431 /* return app data */ 432 *pAppDataOffset = easHandle->jetHandle->appDataOffset; 433 *pAppDataSize = easHandle->jetHandle->appDataSize; 434 return EAS_SUCCESS; 435} 436 437/*---------------------------------------------------------------------------- 438 * JET_CloseFile() 439 *---------------------------------------------------------------------------- 440 * Closes a JET content file and releases associated resources 441 *---------------------------------------------------------------------------- 442*/ 443EAS_PUBLIC EAS_RESULT JET_CloseFile (EAS_DATA_HANDLE easHandle) 444{ 445 EAS_INT index; 446 EAS_RESULT result = EAS_SUCCESS; 447 448 /* close open streams */ 449 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 450 { 451 if (easHandle->jetHandle->segQueue[index].streamHandle != NULL) 452 { 453 result = JET_CloseSegment(easHandle, index); 454 if (result != EAS_SUCCESS) 455 break; 456 } 457 } 458 459 /* close the main file handle */ 460 if ((result == EAS_SUCCESS) && (easHandle->jetHandle->jetFileHandle != NULL)) 461 { 462 result = EAS_HWCloseFile(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle); 463 if (result == EAS_SUCCESS) 464 easHandle->jetHandle->jetFileHandle = NULL; 465 } 466 return result; 467} 468 469/*---------------------------------------------------------------------------- 470 * JET_Init() 471 *---------------------------------------------------------------------------- 472 * Initializes the JET library, allocates memory, etc. Call 473 * JET_Shutdown to de-allocate memory. 474 *---------------------------------------------------------------------------- 475*/ 476EAS_PUBLIC EAS_RESULT JET_Init (EAS_DATA_HANDLE easHandle, const S_JET_CONFIG *pConfig, EAS_INT configSize) 477{ 478 S_JET_DATA *pJet; 479 EAS_U8 flags = 0; 480 481 /* sanity check */ 482 if (easHandle == NULL) 483 return EAS_ERROR_HANDLE_INTEGRITY; 484 if (easHandle->jetHandle != NULL) 485 return EAS_ERROR_FEATURE_ALREADY_ACTIVE; 486 if (pConfig == NULL) 487 pConfig = &jetDefaultConfig; 488 489 /* allocate the JET data object */ 490 pJet = EAS_HWMalloc(easHandle->hwInstData, sizeof(S_JET_DATA)); 491 if (pJet == NULL) 492 return EAS_ERROR_MALLOC_FAILED; 493 494 /* initialize JET data structure */ 495 EAS_HWMemSet(pJet, 0, sizeof(S_JET_DATA)); 496 easHandle->jetHandle = pJet; 497 pJet->flags = flags; 498 499 /* copy config data */ 500 if (configSize > (EAS_INT) sizeof(S_JET_CONFIG)) 501 configSize = sizeof(S_JET_CONFIG); 502 EAS_HWMemCpy(&pJet->config, pConfig, configSize); 503 return EAS_SUCCESS; 504} 505 506/*---------------------------------------------------------------------------- 507 * JET_Shutdown() 508 *---------------------------------------------------------------------------- 509 * Frees any memory used by the JET library 510 *---------------------------------------------------------------------------- 511*/ 512EAS_PUBLIC EAS_RESULT JET_Shutdown (EAS_DATA_HANDLE easHandle) 513{ 514 EAS_RESULT result; 515 516 /* close any open files */ 517 result = JET_CloseFile(easHandle); 518 519 /* free allocated data */ 520 EAS_HWFree(easHandle->hwInstData, easHandle->jetHandle); 521 easHandle->jetHandle = NULL; 522 return result; 523} 524 525/*---------------------------------------------------------------------------- 526 * JET_Status() 527 *---------------------------------------------------------------------------- 528 * Returns current status 529 *---------------------------------------------------------------------------- 530*/ 531EAS_PUBLIC EAS_RESULT JET_Status (EAS_DATA_HANDLE easHandle, S_JET_STATUS *pStatus) 532{ 533 S_JET_SEGMENT *pSeg; 534 535 pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; 536 if (pSeg->streamHandle != NULL) 537 { 538 pStatus->currentUserID = pSeg->userID; 539 pStatus->segmentRepeatCount = pSeg->repeatCount; 540 } 541 else 542 { 543 pStatus->currentUserID = -1; 544 pStatus->segmentRepeatCount = 0; 545 } 546 547 pStatus->paused = !(easHandle->jetHandle->flags & JET_FLAGS_PLAYING); 548 pStatus->numQueuedSegments = easHandle->jetHandle->numQueuedSegments; 549 pStatus->currentPlayingSegment = easHandle->jetHandle->playSegment; 550 pStatus->currentQueuedSegment = easHandle->jetHandle->queueSegment; 551 if (pSeg->streamHandle != NULL) 552 { 553 EAS_RESULT result; 554 EAS_I32 location ; 555 if ((result = EAS_GetLocation(easHandle, pSeg->streamHandle, &location)) == EAS_SUCCESS) 556 if(location != 0) 557 { 558 pStatus->location = location; 559 } 560 } 561 return EAS_SUCCESS; 562} 563 564/*---------------------------------------------------------------------------- 565 * JET_GetEvent() 566 *---------------------------------------------------------------------------- 567 * Checks for application events 568 *---------------------------------------------------------------------------- 569*/ 570EAS_PUBLIC EAS_BOOL JET_GetEvent (EAS_DATA_HANDLE easHandle, EAS_U32 *pEventRaw, S_JET_EVENT *pEvent) 571{ 572 EAS_U32 jetEvent; 573 EAS_BOOL gotEvent; 574 575 /* process event queue */ 576 gotEvent = JET_ReadQueue(easHandle->jetHandle->appEventQueue, 577 &easHandle->jetHandle->appEventQueueRead, 578 easHandle->jetHandle->appEventQueueWrite, 579 APP_EVENT_QUEUE_SIZE, &jetEvent); 580 581 if (gotEvent) 582 { 583 if (pEventRaw != NULL) 584 *pEventRaw = jetEvent; 585 586 if (pEvent != NULL) 587 JET_ParseEvent(jetEvent, pEvent); 588 } 589 590 return gotEvent; 591} 592 593/*---------------------------------------------------------------------------- 594 * JET_QueueSegment() 595 *---------------------------------------------------------------------------- 596 * Queue a segment for playback 597 *---------------------------------------------------------------------------- 598*/ 599EAS_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) 600{ 601 EAS_FILE_HANDLE fileHandle; 602 EAS_RESULT result; 603 S_JET_SEGMENT *p; 604 605 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_QueueSegment segNum=%d, queue=%d\n", segmentNum, easHandle->jetHandle->queueSegment); */ } 606 607 /* make sure it's a valid segment */ 608 if (segmentNum >= easHandle->jetHandle->numSegments) 609 return EAS_ERROR_PARAMETER_RANGE; 610 611 /* make sure it's a valid DLS */ 612 if (libNum >= easHandle->jetHandle->numLibraries) 613 return EAS_ERROR_PARAMETER_RANGE; 614 615 /* check to see if queue is full */ 616 p = &easHandle->jetHandle->segQueue[easHandle->jetHandle->queueSegment]; 617 if (p->streamHandle != NULL) 618 return EAS_ERROR_QUEUE_IS_FULL; 619 620 /* initialize data */ 621 p->userID = userID; 622 p->repeatCount = (EAS_I16) repeatCount; 623 p->transpose = (EAS_I8) transpose; 624 p->libNum = (EAS_I8) libNum; 625 p->muteFlags = muteFlags; 626 p->state = JET_STATE_CLOSED; 627 628 /* open the file */ 629 result = EAS_OpenJETStream(easHandle, easHandle->jetHandle->jetFileHandle, easHandle->jetHandle->segmentOffsets[segmentNum], &p->streamHandle); 630 if (result != EAS_SUCCESS) 631 return result; 632 p->state = JET_STATE_OPEN; 633 634 /* if less than SEG_QUEUE_DEPTH segments queued up, prepare file for playback */ 635 if (++easHandle->jetHandle->numQueuedSegments < SEG_QUEUE_DEPTH) 636 { 637 result = JET_PrepareSegment(easHandle, easHandle->jetHandle->queueSegment); 638 if (result != EAS_SUCCESS) 639 return result; 640 } 641 642 /* create duplicate file handle */ 643 result = EAS_HWDupHandle(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &fileHandle); 644 if (result != EAS_SUCCESS) 645 return result; 646 647 easHandle->jetHandle->jetFileHandle = fileHandle; 648 easHandle->jetHandle->queueSegment = (EAS_U8) JET_NextSegment(easHandle->jetHandle->queueSegment); 649 return result; 650} 651 652/*---------------------------------------------------------------------------- 653 * JET_Play() 654 *---------------------------------------------------------------------------- 655 * Starts playback of the file 656 *---------------------------------------------------------------------------- 657*/ 658EAS_PUBLIC EAS_RESULT JET_Play (EAS_DATA_HANDLE easHandle) 659{ 660 EAS_RESULT result; 661 EAS_INT index; 662 EAS_INT count = 0; 663 664 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Play\n"); */ } 665 666 /* sanity check */ 667 if (easHandle->jetHandle->flags & JET_FLAGS_PLAYING) 668 return EAS_ERROR_NOT_VALID_IN_THIS_STATE; 669 670 /* resume all paused streams */ 671 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 672 { 673 if (((index == easHandle->jetHandle->playSegment) && (easHandle->jetHandle->segQueue[index].state == JET_STATE_READY)) || 674 (easHandle->jetHandle->segQueue[index].state == JET_STATE_PAUSED)) 675 { 676 result = JET_StartPlayback(easHandle, index); 677 if (result != EAS_SUCCESS) 678 return result; 679 count++; 680 } 681 } 682 683 /* if no streams are playing, return error */ 684 if (!count) 685 return EAS_ERROR_QUEUE_IS_EMPTY; 686 687 easHandle->jetHandle->flags |= JET_FLAGS_PLAYING; 688 return EAS_SUCCESS; 689} 690 691/*---------------------------------------------------------------------------- 692 * JET_Pause() 693 *---------------------------------------------------------------------------- 694 * Pauses playback of the file 695 *---------------------------------------------------------------------------- 696*/ 697EAS_PUBLIC EAS_RESULT JET_Pause (EAS_DATA_HANDLE easHandle) 698{ 699 EAS_RESULT result; 700 EAS_INT index; 701 EAS_INT count = 0; 702 703 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Pause\n"); */ } 704 705 /* sanity check */ 706 if ((easHandle->jetHandle->flags & JET_FLAGS_PLAYING) == 0) 707 return EAS_ERROR_NOT_VALID_IN_THIS_STATE; 708 709 /* pause all playing streams */ 710 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 711 { 712 if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) 713 { 714 result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle); 715 if (result != EAS_SUCCESS) 716 return result; 717 easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].state = JET_STATE_PAUSED; 718 count++; 719 } 720 } 721 722 /* if no streams are paused, return error */ 723 if (!count) 724 return EAS_ERROR_QUEUE_IS_EMPTY; 725 726 easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; 727 return EAS_SUCCESS; 728} 729 730/*---------------------------------------------------------------------------- 731 * JET_SetMuteFlags() 732 *---------------------------------------------------------------------------- 733 * Change the state of the mute flags 734 *---------------------------------------------------------------------------- 735*/ 736EAS_PUBLIC EAS_RESULT JET_SetMuteFlags (EAS_DATA_HANDLE easHandle, EAS_U32 muteFlags, EAS_BOOL sync) 737{ 738 S_JET_SEGMENT *pSeg; 739 740 /* get pointer to current segment */ 741 pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; 742 743 /* unsynchronized mute, set flags and return */ 744 if (!sync) 745 { 746 if (pSeg->streamHandle == NULL) 747 return EAS_ERROR_QUEUE_IS_EMPTY; 748 pSeg->muteFlags = muteFlags; 749 return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) muteFlags); 750 } 751 752 753 /* check for valid stream state */ 754 if (pSeg->state == JET_STATE_CLOSED) 755 return EAS_ERROR_QUEUE_IS_EMPTY; 756 757 /* save mute flags */ 758 pSeg->muteFlags = muteFlags; 759 760 /* if repeating segment, set mute update flag */ 761 if (sync) 762 pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; 763 return EAS_SUCCESS; 764} 765 766/*---------------------------------------------------------------------------- 767 * JET_SetMuteFlag() 768 *---------------------------------------------------------------------------- 769 * Change the state of a single mute flag 770 *---------------------------------------------------------------------------- 771*/ 772EAS_PUBLIC EAS_RESULT JET_SetMuteFlag (EAS_DATA_HANDLE easHandle, EAS_INT trackNum, EAS_BOOL muteFlag, EAS_BOOL sync) 773{ 774 S_JET_SEGMENT *pSeg; 775 EAS_U32 trackMuteFlag; 776 777 778 /* setup flag */ 779 if ((trackNum < 0) || (trackNum > 31)) 780 return EAS_ERROR_PARAMETER_RANGE; 781 trackMuteFlag = (1 << trackNum); 782 783 /* get pointer to current segment */ 784 pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; 785 786 /* unsynchronized mute, set flags and return */ 787 if (!sync) 788 { 789 if (pSeg->streamHandle == NULL) 790 return EAS_ERROR_QUEUE_IS_EMPTY; 791 if (muteFlag) 792 pSeg->muteFlags |= trackMuteFlag; 793 else 794 pSeg->muteFlags &= ~trackMuteFlag; 795 return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 796 } 797 798 799 /* check for valid stream state */ 800 if (pSeg->state == JET_STATE_CLOSED) 801 return EAS_ERROR_QUEUE_IS_EMPTY; 802 803 /* save mute flags and set mute update flag */ 804 if (muteFlag) 805 pSeg->muteFlags |= trackMuteFlag; 806 else 807 pSeg->muteFlags &= ~trackMuteFlag; 808 pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; 809 return EAS_SUCCESS; 810} 811 812/*---------------------------------------------------------------------------- 813 * JET_TriggerClip() 814 *---------------------------------------------------------------------------- 815 * Unmute a track and then mute it when it is complete. If a clip 816 * is already playing, change mute event to a trigger event. The 817 * JET_Event function will not mute the clip, but will allow it 818 * to continue playing through the next clip. 819 * 820 * NOTE: We use bit 7 to indicate an entry in the queue. For a 821 * small queue, it is cheaper in both memory and CPU cycles to 822 * scan the entire queue for non-zero events than keep enqueue 823 * and dequeue indices. 824 *---------------------------------------------------------------------------- 825*/ 826EAS_PUBLIC EAS_RESULT JET_TriggerClip (EAS_DATA_HANDLE easHandle, EAS_INT clipID) 827{ 828 EAS_INT i; 829 EAS_INT index = -1; 830 831 /* check for valid clipID */ 832 if ((clipID < 0) || (clipID > 63)) 833 return EAS_ERROR_PARAMETER_RANGE; 834 835 /* set active flag */ 836 clipID |= JET_CLIP_ACTIVE_FLAG; 837 838 /* Reverse the search so that we get the first empty element */ 839 for (i = JET_MUTE_QUEUE_SIZE-1; i >= 0 ; i--) 840 { 841 if (easHandle->jetHandle->muteQueue[i] == clipID) 842 { 843 index = i; 844 break; 845 } 846 if (easHandle->jetHandle->muteQueue[i] == 0) 847 index = i; 848 } 849 if (index < 0) 850 return EAS_ERROR_QUEUE_IS_FULL; 851 852 easHandle->jetHandle->muteQueue[index] = (EAS_U8) clipID | JET_CLIP_TRIGGER_FLAG; 853 return EAS_SUCCESS; 854} 855 856/*---------------------------------------------------------------------------- 857 * JET_Process() 858 *---------------------------------------------------------------------------- 859 * Called during EAS_Render to process stream states 860 *---------------------------------------------------------------------------- 861*/ 862EAS_PUBLIC EAS_RESULT JET_Process (EAS_DATA_HANDLE easHandle) 863{ 864 S_JET_SEGMENT *pSeg; 865 EAS_STATE state; 866 EAS_INT index; 867 EAS_INT playIndex; 868 EAS_RESULT result = EAS_SUCCESS; 869 EAS_BOOL endOfLoop = EAS_FALSE; 870 EAS_BOOL startNextSegment = EAS_FALSE; 871 EAS_BOOL prepareNextSegment = EAS_FALSE; 872 EAS_U32 jetEvent; 873 874 /* process event queue */ 875 while (JET_ReadQueue(easHandle->jetHandle->jetEventQueue, 876 &easHandle->jetHandle->jetEventQueueRead, 877 easHandle->jetHandle->jetEventQueueWrite, 878 JET_EVENT_QUEUE_SIZE, &jetEvent)) 879 { 880 S_JET_EVENT event; 881#ifdef DEBUG_JET 882 JET_DumpEvent("JET_Process", jetEvent); 883#endif 884 JET_ParseEvent(jetEvent, &event); 885 886 /* check for end of loop */ 887 if ((event.controller == JET_EVENT_MARKER) && 888 (event.value == JET_MARKER_LOOP_END) && 889 (easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle != NULL)) 890 endOfLoop = EAS_TRUE; 891 } 892 893 /* check state of all streams */ 894 index = playIndex = easHandle->jetHandle->playSegment; 895 for (;;) 896 { 897 pSeg = &easHandle->jetHandle->segQueue[index]; 898 if (pSeg->state != JET_STATE_CLOSED) 899 { 900 901 /* get playback state */ 902 result = EAS_State(easHandle, pSeg->streamHandle, &state); 903 if (result != EAS_SUCCESS) 904 return result; 905 906 /* process state */ 907 switch (pSeg->state) 908 { 909 /* take action if this segment is stopping */ 910 case JET_STATE_PLAYING: 911 if (endOfLoop || (state == EAS_STATE_STOPPING) || (state == EAS_STATE_STOPPED)) 912 { 913 /* handle repeats */ 914 if (pSeg->repeatCount != 0) 915 { 916 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render repeating segment %d\n", index); */ } 917 result = EAS_Locate(easHandle, pSeg->streamHandle, 0, EAS_FALSE); 918 if (result != EAS_SUCCESS) 919 return result; 920 if (pSeg->repeatCount > 0) 921 pSeg->repeatCount--; 922 923 /* update mute flags if necessary */ 924 if (pSeg->flags & JET_SEG_FLAG_MUTE_UPDATE) 925 { 926 result = EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 927 if (result != EAS_SUCCESS) 928 return result; 929 pSeg->flags &= ~JET_SEG_FLAG_MUTE_UPDATE; 930 } 931 932 } 933 /* no repeat, start next segment */ 934 else 935 { 936 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render stopping queue %d\n", index); */ } 937 startNextSegment = EAS_TRUE; 938 pSeg->state = JET_STATE_STOPPING; 939 easHandle->jetHandle->playSegment = (EAS_U8) JET_NextSegment(index); 940 } 941 } 942 break; 943 944 /* if playback has stopped, close the segment */ 945 case JET_STATE_STOPPING: 946 if (state == EAS_STATE_STOPPED) 947 { 948 result = JET_CloseSegment(easHandle, index); 949 if (result != EAS_SUCCESS) 950 return result; 951 } 952 break; 953 954 case JET_STATE_READY: 955 if (startNextSegment) 956 { 957 result = JET_StartPlayback(easHandle, index); 958 if (result != EAS_SUCCESS) 959 return result; 960 startNextSegment = EAS_FALSE; 961 prepareNextSegment = EAS_TRUE; 962 } 963 break; 964 965 case JET_STATE_OPEN: 966 if (prepareNextSegment) 967 { 968 result = JET_PrepareSegment(easHandle, index); 969 if (result != EAS_SUCCESS) 970 return result; 971 prepareNextSegment = EAS_FALSE; 972 } 973 break; 974 975 case JET_STATE_PAUSED: 976 break; 977 978 default: 979 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "JET_Render: Unexpected segment state %d\n", pSeg->state); */ } 980 break; 981 } 982 } 983 984 /* increment index */ 985 index = JET_NextSegment(index); 986 if (index == playIndex) 987 break; 988 } 989 990 /* if out of segments, clear playing flag */ 991 if (easHandle->jetHandle->numQueuedSegments == 0) 992 easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; 993 994 return result; 995} 996 997/*---------------------------------------------------------------------------- 998 * JET_Event() 999 *---------------------------------------------------------------------------- 1000 * Called from MIDI parser when data of interest is received 1001 *---------------------------------------------------------------------------- 1002*/ 1003void JET_Event (EAS_DATA_HANDLE easHandle, EAS_U32 segTrack, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) 1004{ 1005 EAS_U32 event; 1006 1007 if (easHandle->jetHandle == NULL) 1008 return; 1009 1010 /* handle triggers */ 1011 if (controller == JET_EVENT_TRIGGER_CLIP) 1012 { 1013 S_JET_SEGMENT *pSeg; 1014 EAS_INT i; 1015 EAS_U32 muteFlag; 1016 1017 for (i = 0; i < JET_MUTE_QUEUE_SIZE; i++) 1018 { 1019 /* search for event in queue */ 1020 if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_ID_MASK) == (value & JET_CLIP_ID_MASK)) 1021 { 1022 /* get segment pointer and mute flag */ 1023 pSeg = &easHandle->jetHandle->segQueue[segTrack >> JET_EVENT_SEG_SHIFT]; 1024 muteFlag = 1 << ((segTrack & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT); 1025 1026 /* un-mute the track */ 1027 if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_TRIGGER_FLAG) && ((value & 0x40) > 0)) 1028 { 1029 pSeg->muteFlags &= ~muteFlag; 1030 easHandle->jetHandle->muteQueue[i] &= ~JET_CLIP_TRIGGER_FLAG; 1031 } 1032 1033 /* mute the track */ 1034 else 1035 { 1036 EAS_U32 beforeMute ; 1037 beforeMute = pSeg->muteFlags ; 1038 pSeg->muteFlags |= muteFlag; 1039 if (beforeMute != pSeg->muteFlags) 1040 easHandle->jetHandle->muteQueue[i] = 0; 1041 } 1042 EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); 1043 return; 1044 } 1045 } 1046 return; 1047 } 1048 1049 /* generic event stuff */ 1050 event = (channel << JET_EVENT_CHAN_SHIFT) | (controller << JET_EVENT_CTRL_SHIFT) | value; 1051 1052 /* write to app queue, translate queue index to segment number */ 1053 if ((controller >= easHandle->jetHandle->config.appEventRangeLow) && (controller <= easHandle->jetHandle->config.appEventRangeHigh)) 1054 { 1055 1056 event |= easHandle->jetHandle->segQueue[(segTrack & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT].userID << JET_EVENT_SEG_SHIFT; 1057#ifdef DEBUG_JET 1058 JET_DumpEvent("JET_Event[app]", event); 1059#endif 1060 JET_WriteQueue(easHandle->jetHandle->appEventQueue, 1061 &easHandle->jetHandle->appEventQueueWrite, 1062 easHandle->jetHandle->appEventQueueRead, 1063 APP_EVENT_QUEUE_SIZE, 1064 event); 1065 } 1066 1067 /* write to JET queue */ 1068 else if ((controller >= JET_EVENT_LOW) && (controller <= JET_EVENT_HIGH)) 1069 { 1070 event |= segTrack; 1071#ifdef DEBUG_JET 1072 JET_DumpEvent("JET_Event[jet]", event); 1073#endif 1074 JET_WriteQueue(easHandle->jetHandle->jetEventQueue, 1075 &easHandle->jetHandle->jetEventQueueWrite, 1076 easHandle->jetHandle->jetEventQueueRead, 1077 JET_EVENT_QUEUE_SIZE, 1078 event); 1079 } 1080} 1081 1082/*---------------------------------------------------------------------------- 1083 * JET_Clear_Queue() 1084 *---------------------------------------------------------------------------- 1085 * Clears the queue and stops play without a complete shutdown 1086 *---------------------------------------------------------------------------- 1087*/ 1088EAS_RESULT JET_Clear_Queue(EAS_DATA_HANDLE easHandle) 1089{ 1090 EAS_INT index; 1091 EAS_RESULT result = EAS_SUCCESS; 1092 1093 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Clear_Queue\n"); */ } 1094 1095 /* pause all playing streams */ 1096 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 1097 { 1098 if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) 1099 { 1100 result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[index].streamHandle); 1101 if (result != EAS_SUCCESS) 1102 return result; 1103 1104 easHandle->jetHandle->segQueue[index].state = JET_STATE_PAUSED; 1105 } 1106 } 1107 1108 /* close all streams */ 1109 for (index = 0; index < SEG_QUEUE_DEPTH; index++) 1110 { 1111 if (easHandle->jetHandle->segQueue[index].streamHandle != NULL) 1112 { 1113 result = JET_CloseSegment(easHandle, index); 1114 if (result != EAS_SUCCESS) 1115 return result; 1116 } 1117 } 1118 1119 /* clear all clips */ 1120 for (index = 0; index < JET_MUTE_QUEUE_SIZE ; index++) 1121 { 1122 easHandle->jetHandle->muteQueue[index] = 0; 1123 } 1124 1125 easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; 1126 easHandle->jetHandle->playSegment = easHandle->jetHandle->queueSegment = 0; 1127 return result; 1128} 1129 1130