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