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