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