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