• 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                 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 */
JET_OpenFile(EAS_DATA_HANDLE easHandle,EAS_FILE_LOCATOR locator)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 */
JET_GetAppData(EAS_DATA_HANDLE easHandle,EAS_I32 * pAppDataOffset,EAS_I32 * pAppDataSize)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 */
JET_CloseFile(EAS_DATA_HANDLE easHandle)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 */
JET_Init(EAS_DATA_HANDLE easHandle,const S_JET_CONFIG * pConfig,EAS_INT configSize)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 */
JET_Shutdown(EAS_DATA_HANDLE easHandle)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 */
JET_Status(EAS_DATA_HANDLE easHandle,S_JET_STATUS * pStatus)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 */
JET_GetEvent(EAS_DATA_HANDLE easHandle,EAS_U32 * pEventRaw,S_JET_EVENT * pEvent)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 */
JET_QueueSegment(EAS_DATA_HANDLE easHandle,EAS_INT segmentNum,EAS_INT libNum,EAS_INT repeatCount,EAS_INT transpose,EAS_U32 muteFlags,EAS_U8 userID)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 */
JET_Play(EAS_DATA_HANDLE easHandle)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 */
JET_Pause(EAS_DATA_HANDLE easHandle)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 */
JET_SetMuteFlags(EAS_DATA_HANDLE easHandle,EAS_U32 muteFlags,EAS_BOOL sync)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 */
JET_SetMuteFlag(EAS_DATA_HANDLE easHandle,EAS_INT trackNum,EAS_BOOL muteFlag,EAS_BOOL sync)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 */
JET_TriggerClip(EAS_DATA_HANDLE easHandle,EAS_INT clipID)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 */
JET_Process(EAS_DATA_HANDLE easHandle)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 */
JET_Event(EAS_DATA_HANDLE easHandle,EAS_U32 segTrack,EAS_U8 channel,EAS_U8 controller,EAS_U8 value)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 */
JET_Clear_Queue(EAS_DATA_HANDLE easHandle)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