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