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