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