1
2 /*
3 * xa_ipc.c
4 *
5 * Copyright (C) 1995-1998,1999 by Mark Podlipec.
6 * All rights reserved.
7 *
8 * This software may be freely used, copied and redistributed without
9 * fee for non-commerical purposes provided that this copyright
10 * notice is preserved intact on all copies.
11 *
12 * There is no warranty or other guarantee of fitness of this software.
13 * It is provided solely "as is". The author disclaims all
14 * responsibility and liability with respect to this software's usage
15 * or its effect upon hardware or computer systems.
16 *
17 */
18 /****************
19 * Rev History
20 *
21 * 03Jun95 - Created
22 * *****96 - did some stuff
23 * *****97 - did a little more
24 * *****98 - wished I could rewrite it
25 * 21Feb99 - Change AUDIO_ON to be AUDIO_PREP then AUDIO_ON
26 *
27 *******************************/
28
29
30 #include "xanim.h"
31 #include <Intrinsic.h>
32 #include <StringDefs.h>
33 #include <Shell.h>
34 #include <sys/signal.h>
35
36 #ifdef XA_SOCKET
37 #include <sys/socket.h>
38 #endif
39
40 #ifdef XA_SELECT
41 #include <sys/select.h>
42 #endif
43
44 #ifdef VMS
45 #include <lib$routines.h>
46 #include <starlet.h>
47 #ifdef R3_INTRINSICS
48 typedef void *XtPointer;
49 #endif
50 #endif
51
52 #include "xa_ipc.h"
53
54 XtAppContext theAudContext;
55 Display *theAudDisp;
56 xaULONG xa_audio_present;
57 xaULONG xa_audio_status;
58 XA_AUD_FLAGS *audiof;
59
60
61 #ifdef XA_AUDIO
62
63 /* POD NOTE: Check for NOFILE defined in parms.h??? */
64 #ifndef FD_SETSIZE
65 #define FD_SETSIZE 64
66 #endif
67
68 static xaULONG audio_debug_flag = xaFALSE;
69 xaLONG xa_child_last_time = 0;
70 int xa_audio_parent_pid = -1;
71
72 #define AUD_DEBUG if (audio_debug_flag == xaTRUE)
73
74
75 extern xaULONG xa_audio_hard_buff; /* AUDIO DOMAIN */
76 extern xaLONG xa_av_time_off;
77 extern void New_Merged_Audio_Output();
78 extern int xa_aud_fd;
79 extern xaUBYTE *xa_audcodec_buf;
80 extern xaULONG xa_audcodec_maxsize;
81 extern xaULONG xa_kludge2_dvi;
82 extern xaULONG xa_kludge900_aud;
83
84 /**** Extern xa_audio Functions *****/
85 extern void XA_Audio_Setup();
86 extern xaULONG (*XA_Audio_Init)();
87 extern void (*XA_Audio_Kill)();
88 extern void (*XA_Audio_Off)();
89 extern void (*XA_Audio_Prep)();
90 extern void (*XA_Audio_On)();
91 extern xaULONG (*XA_Closest_Freq)();
92 extern void (*XA_Set_Output_Port)();
93 extern void (*XA_Speaker_Tog)();
94 extern void (*XA_Headphone_Tog)();
95 extern void (*XA_LineOut_Tog)();
96 void XA_Audio_Init_Snd();
97 extern xaULONG XA_IPC_Sound();
98 extern xaLONG XA_Time_Read();
99 extern void XA_Read_Audio_Delta();
100
101
102 XA_AUD_HDR *xa_aud_hdr_start,*xa_aud_hdr_cur;
103 xaULONG xa_aud_hdr_num = 0;
104
105 void XA_Child_Loop();
106 void XA_Child_BOFL();
107 void XA_Child_Dies();
108 void XA_Child_Dies1();
109
110 xaULONG XA_IPC_Receive();
111 xaULONG XA_IPC_Send();
112 void XA_Audio_Child();
113 xaULONG XA_Video_Send2_Audio();
114 xaULONG XA_Video_Receive_Ack();
115 xaULONG XA_Audio_Receive_Video_CMD();
116 xaUBYTE *XA_Audio_Receive_Video_Buf();
117 xaULONG XA_Audio_Send_ACK();
118 xaULONG XA_Child_Find_File();
119 void XA_IPC_Reset_AV_Time();
120 void Free_SNDs();
121
122 extern XA_SND *xa_snd_cur;
123 extern xaLONG xa_time_audio;
124 extern xaULONG xa_timelo_audio;
125
126 static xaULONG xa_ipc_cmd_id = 1;
127
128 int xa_audio_fd[2]; /* audio child reads this, video writes this */
129 int xa_video_fd[2]; /* video reads this, audio child writes this */
130
131 xaLONG xa_audio_child = -1;
132
133 /************ XAnim Audio Child Code ***********************************/
134
135 /***************************************
136 * Routine for sending a buffer across the pipe. Handles partial writes
137 * caused to interrupts, full buffers, etc.
138 *
139 * ? Implement Timeout ?
140 **************/
XA_IPC_Send(fd,p,len,who)141 xaULONG XA_IPC_Send(fd,p,len,who)
142 int fd;
143 char *p;
144 int len;
145 int who;
146 { while(len > 0)
147 { int ret;
148 ret = write( fd, p, len );
149 if (ret < 0)
150 { AUD_DEBUG fprintf(stderr,"IPC(%d) Send ERR: %d\n",who,errno);
151 return(XA_IPC_ERR);
152 }
153 else { len -= ret; p += ret; }
154 }
155 return(XA_IPC_OK);
156 }
157
158 /***************************************
159 * Routine for receiving a buffer across the pipe. Handles partial reads
160 * caused to interrupts, empty buffers, etc.
161 *
162 * ? Implement Select ?
163 **************/
XA_IPC_Receive(fd,p,len,timeout,who)164 xaULONG XA_IPC_Receive(fd,p,len,timeout,who)
165 int fd;
166 char *p;
167 int len;
168 xaLONG timeout;
169 int who;
170 { xaLONG cur_time,ack_time;
171
172 cur_time = ack_time = XA_Time_Read();
173 ack_time += timeout;
174 do
175 { int ret;
176 ret = read( fd, p, len);
177 if (ret < 0)
178 { AUD_DEBUG fprintf(stderr,"IPC(%d) Receive ERR %d\n",who,errno);
179 return(XA_IPC_ERR);
180 }
181 else /* ?POD overrun ever possible??? */
182 { len -= ret; if (len <= 0) break;
183 p += ret;
184 }
185 cur_time = XA_Time_Read();
186 } while(cur_time < ack_time);
187
188 if (len != 0)
189 { AUD_DEBUG fprintf(stderr,"IPC(%d) Receive TimeOut %dms\n",who,timeout);
190 return(XA_IPC_TOD);
191 }
192
193 return(XA_IPC_OK);
194 }
195
196 /***************************************
197 * This routine blocks until something is ready on fd or
198 * until a timeout occurrs.
199 *
200 * Timeout is in milliseconds.
201 **************/
XA_IPC_Select(fd,timeout,who)202 xaULONG XA_IPC_Select(fd,timeout,who)
203 int fd;
204 xaLONG timeout;
205 int who;
206 { int ret,tt_sec,tt_usec;
207 int width = FD_SETSIZE;
208 fd_set readfds, writefds, exceptfds;
209 struct timeval t_timeout;
210
211 tt_sec = timeout / 1000;
212 tt_usec = timeout - (tt_sec * 1000);
213 tt_usec *= 1000;
214
215 /* AUD_DEBUG fprintf(stderr,"tt_sec %d tt_usec %d\n",tt_sec,tt_usec); */
216
217 FD_ZERO(&readfds);
218 FD_SET( fd , &readfds);
219 FD_ZERO(&writefds);
220 FD_ZERO(&exceptfds);
221 t_timeout.tv_sec = tt_sec;
222 t_timeout.tv_usec = tt_usec;
223
224 ret = select(width, &readfds, &writefds, &exceptfds, &t_timeout);
225
226 if (ret < 0) AUD_DEBUG fprintf(stderr,"AUD select ERR: %d\n",errno);
227 return(ret);
228 }
229
230 /***************************************
231 * Routine for having the Video Process receive keep alive message.
232 *
233 * ack_flag is number of ms to wait for ACK.
234 *********/
XA_Video_Receive_Ack(ack_flag)235 xaULONG XA_Video_Receive_Ack(ack_flag)
236 xaULONG ack_flag;
237 {
238 XA_IPC_HDR ipc_ack;
239 xaULONG ret;
240
241 /*** Read ACK */
242 ret = XA_IPC_Receive(xa_video_fd[XA_FD_READ],((char *)(&ipc_ack)),
243 (sizeof(XA_IPC_HDR)),ack_flag,XA_IAM_VIDEO);
244 if (ret != XA_IPC_OK)
245 { AUD_DEBUG fprintf(stderr,"Vid chunk Ack Err\n"); return(xaFALSE); }
246 return(xaTRUE);
247 }
248
249 /***************************************
250 * Routine for having the Video Process send a Command with
251 * optional Command Acknowledgement and option data buffer.
252 *
253 * ack_flag is number of ms to wait for ACK. If 0, then no ACK is checked
254 * for.
255 **************/
XA_Video_Send2_Audio(cmd,buf,buf_len,value,ack_flag,ack_val)256 xaULONG XA_Video_Send2_Audio(cmd,buf,buf_len,value,ack_flag,ack_val)
257 xaULONG cmd;
258 xaUBYTE *buf;
259 xaULONG buf_len;
260 xaULONG value;
261 xaULONG ack_flag;
262 xaULONG *ack_val;
263 { XA_IPC_HDR ipc_cmd,ipc_ack;
264 xaULONG ret;
265 xaLONG len;
266 char *p;
267
268 /*** Setup Command */
269 ipc_cmd.cmd = cmd;
270 ipc_cmd.time = XA_Time_Read();
271 ipc_cmd.len = buf_len;
272 ipc_cmd.value = value;
273 ipc_cmd.id = xa_ipc_cmd_id;
274 xa_ipc_cmd_id++;
275
276 /*** SEND IPC Command */
277 ret = XA_IPC_Send( xa_audio_fd[XA_FD_WRITE], ((char *)(&ipc_cmd)),
278 (sizeof(XA_IPC_HDR)), XA_IAM_VIDEO );
279 if (ret == XA_IPC_ERR)
280 { AUD_DEBUG fprintf(stderr,"Vid Send Cmd Err\n"); return(xaFALSE); }
281
282
283 /* SEND Data if Any */
284 p = (char *)(buf);
285 len = buf_len;
286 while(len > 0)
287 { int sel_ret,tlen = len;
288
289 if (tlen > XA_IPC_CHUNK) tlen = XA_IPC_CHUNK;
290 AUD_DEBUG fprintf(stderr,"VID IPC Sendin Chunk tlen %d\n",tlen);
291 ret = XA_IPC_Send( xa_audio_fd[XA_FD_WRITE], p, tlen, XA_IAM_VIDEO );
292 if (ret == XA_IPC_ERR)
293 { AUD_DEBUG fprintf(stderr,"Vid Send Buf Err\n"); return(xaFALSE); }
294 p += tlen;; len -= tlen;
295
296 /*** wait for ACK */
297 sel_ret = XA_IPC_Select(xa_video_fd[XA_FD_READ], ack_flag,XA_IAM_VIDEO);
298 if (sel_ret <= 0)
299 {
300 AUD_DEBUG fprintf(stderr,"VID: chunk Ack Timeout/err: cmd %x %d\n",cmd,sel_ret);
301 return(xaFALSE);
302 }
303
304 /*** Read ACK */
305 do
306 {
307 ret = XA_IPC_Receive(xa_video_fd[XA_FD_READ],((char *)(&ipc_ack)),
308 (sizeof(XA_IPC_HDR)),ack_flag,XA_IAM_VIDEO);
309 if (ret != XA_IPC_OK)
310 { AUD_DEBUG fprintf(stderr,"Vid chunk Ack Err\n"); return(xaFALSE); }
311 } while(ipc_ack.cmd == XA_IPC_BOFL);
312 AUD_DEBUG fprintf(stderr,"VID IPC Sent Chunk OK\n");
313 }
314
315 /*** Look For ACK */
316 if (ack_flag)
317 { int sel_ret = XA_IPC_Select(xa_video_fd[XA_FD_READ], ack_flag,XA_IAM_VIDEO);
318 if (sel_ret <= 0)
319 {
320 AUD_DEBUG fprintf(stderr,"VID: Ack Timeout/err: cmd %x %d\n",cmd,sel_ret);
321 return(xaFALSE);
322 }
323
324 do
325 {
326 ret = XA_IPC_Receive(xa_video_fd[XA_FD_READ],((char *)(&ipc_ack)),
327 (sizeof(XA_IPC_HDR)),ack_flag,XA_IAM_VIDEO);
328 if (ret == XA_IPC_ERR)
329 {AUD_DEBUG fprintf(stderr,"Vid IPC Ack Err\n"); return(xaFALSE);}
330 else if (ret == XA_IPC_TOD)
331 {AUD_DEBUG fprintf(stderr,"Vid IPC Ack Timeout\n"); return(xaFALSE);}
332 } while(ipc_ack.cmd == XA_IPC_BOFL);
333
334 if (ipc_cmd.id != ipc_ack.id)
335 {
336 AUD_DEBUG fprintf(stderr,"VID IPC ID mismatch %d %d cmd %x\n",
337 ipc_cmd.id,ipc_ack.id,ipc_cmd.cmd);
338 return(xaFALSE);
339 }
340 if (ack_val) *ack_val = ipc_ack.value;
341 }
342
343 AUD_DEBUG fprintf(stderr,"VID IPC Success %d %u cmd %x\n",
344 ipc_cmd.time,ipc_ack.time,ipc_cmd.cmd);
345 return(xaTRUE);
346 }
347
348 /***************************************
349 * Accept Command from Video Process. Returns CMD on success
350 * or XA_IPC_ERR on failure.
351 *
352 **************/
XA_Audio_Receive_Video_CMD(ipc_cmd,timeout)353 xaULONG XA_Audio_Receive_Video_CMD(ipc_cmd,timeout)
354 XA_IPC_HDR *ipc_cmd;
355 xaLONG timeout;
356 { xaULONG ret;
357
358 ret = XA_IPC_Receive(xa_audio_fd[XA_FD_READ], ((char *)(ipc_cmd)),
359 (sizeof(XA_IPC_HDR)),timeout, XA_IAM_AUDIO );
360 if (ret == XA_IPC_ERR)
361 { AUD_DEBUG fprintf(stderr,"AUD Receive CMD Err\n"); return(XA_IPC_ERR); }
362 else if (ret == XA_IPC_TOD)
363 { AUD_DEBUG fprintf(stderr,"AUD Receive CMD TOD\n"); return(XA_IPC_TOD); }
364
365 AUD_DEBUG fprintf(stderr,"AUD SUCCESS! cmd %x len %d id %d\n",
366 ipc_cmd->cmd,ipc_cmd->len,ipc_cmd->id);
367 return(XA_IPC_OK);
368 }
369
370
371 /***************************************
372 * Accept Buffer from Video Process. Returns buff_len on success
373 * or 0 on failure.
374 *
375 **************/
XA_Audio_Receive_Video_Buf(len,timeout)376 xaUBYTE *XA_Audio_Receive_Video_Buf(len,timeout)
377 xaULONG len; /* len of buffer being sent (from ipc_cmd.len) */
378 xaLONG timeout;
379 { int blen;
380 xaUBYTE *b,*p;
381
382 b = (xaUBYTE *)malloc( len );
383 if (b == 0) { AUD_DEBUG fprintf(stderr,"AUD Rx BUF: malloc err\n"); return(0); }
384
385 p = b;
386 blen = len;
387 while(blen > 0)
388 { int ret,tlen;
389 ret = XA_IPC_Select(xa_audio_fd[XA_FD_READ], 500,XA_IAM_AUDIO);
390 if (ret <= 0) { free(b); return(0); }
391
392 tlen = blen; if (tlen > XA_IPC_CHUNK) tlen = XA_IPC_CHUNK;
393 ret = read( xa_audio_fd[XA_FD_READ], p, tlen);
394 if (ret != tlen) /* POD improve: make while() etc */
395 { AUD_DEBUG fprintf(stderr,"read err %d %d\n",ret,tlen); free(b); return(0); }
396 p += tlen;
397 blen -= tlen;
398 XA_Audio_Send_ACK(XA_IPC_OK,0,0);
399 xa_child_last_time = XA_Time_Read();
400 }
401 return(b);
402 }
403
404
405 /***************************************
406 * This routines sends an Acknowledgement back the Video Process.
407 *
408 **************/
XA_Audio_Send_ACK(ack,id,value)409 xaULONG XA_Audio_Send_ACK(ack,id,value)
410 xaULONG ack;
411 xaULONG id;
412 xaULONG value;
413 { XA_IPC_HDR ipc_ack;
414 xaULONG ret;
415
416 /****************** Send ACK Back to Video */
417 ipc_ack.cmd = ack;
418 ipc_ack.time = XA_Time_Read();
419 ipc_ack.len = 0;
420 ipc_ack.id = id;
421 ipc_ack.value = value;
422 ret = XA_IPC_Send( xa_video_fd[XA_FD_WRITE], ((char *)(&ipc_ack)),
423 (sizeof(XA_IPC_HDR)), XA_IAM_AUDIO );
424 if (ret == XA_IPC_ERR)
425 { AUD_DEBUG fprintf(stderr,"AUD Send ACK Err\n");
426 fprintf(stderr,"Audio_Send_ACK IPC ERR: dying\n");
427 XA_Child_Dies((int)(0));
428 return(XA_IPC_ERR);
429 }
430 if (ack == XA_IPC_ACK_ERR)
431 {
432 AUD_DEBUG fprintf(stderr,"Sent XA_IPC_ACK_ERR, now dyin\n");
433 XA_Child_Dies((int)(0)); /* terminate audio process */
434 }
435 return(ack);
436 }
437
438
439 /***************************************
440 * This routines cleans up after the Child and then
441 * exits.
442 *
443 **************/
XA_Child_Dies(dummy)444 void XA_Child_Dies(dummy)
445 int dummy;
446 { XA_AUD_HDR *aud_hdr;
447
448 AUD_DEBUG fprintf(stderr,"CHILD IS DYING\n");
449 aud_hdr = xa_aud_hdr_start;
450 if (aud_hdr) xa_aud_hdr_start->prev->next = 0; /* break loop */
451 while(aud_hdr)
452 { XA_AUD_HDR *tmp_hdr = aud_hdr->next;
453 /* FREE (aud_hdr->snd) loop */
454 if (aud_hdr->filename) free(aud_hdr->filename);
455 free(aud_hdr);
456 aud_hdr = tmp_hdr;
457 }
458 if (audiof)
459 {
460 if (audiof->device) free(audiof->device);
461 free(audiof);
462 }
463 XtDestroyApplicationContext(theAudContext);
464 AUD_DEBUG fprintf(stderr,"CHILD IS DEAD\n");
465 exit(0);
466 }
467
468 /***************************************
469 * This routine prints out a message and then calls XA_Child_Dies.
470 *
471 **************/
XA_Child_Dies1(s)472 void XA_Child_Dies1(s)
473 char *s;
474 {
475 AUD_DEBUG fprintf(stderr,"CHILD: %s\n",s);
476 XA_Child_Dies((int)(0));
477 }
478
479 /***************************************
480 * This routine returns a XA_AUD_HDR structure.
481 * and removes it from the loop.
482 *
483 **************/
Return_Aud_Hdr(aud_hdr)484 XA_AUD_HDR *Return_Aud_Hdr(aud_hdr)
485 XA_AUD_HDR *aud_hdr;
486 { XA_AUD_HDR *tmp_hdr;
487 AUD_DEBUG fprintf(stderr,"RETURN AUD HDR\n");
488 if ((aud_hdr==0) || (xa_aud_hdr_start==0))
489 XA_Child_Dies1("Return_Anim_Hdr err");
490 xa_aud_hdr_num--;
491 if (xa_aud_hdr_num == 0)
492 {
493 xa_aud_hdr_start = 0;
494 tmp_hdr = 0;
495 }
496 else /* removed aud_hdr from the loop */
497 {
498 tmp_hdr = aud_hdr->prev;
499 tmp_hdr->next = aud_hdr->next;
500 aud_hdr->next->prev = tmp_hdr;
501 }
502 if (aud_hdr->filename) free(aud_hdr->filename);
503 free(aud_hdr);
504 return(tmp_hdr);
505 }
506
Free_SNDs(snd)507 void Free_SNDs(snd)
508 XA_SND *snd;
509 { while (snd)
510 { XA_SND *tmp = snd;
511 if (snd->snd) { free(snd->snd); snd->snd = 0; }
512 snd = snd->next;
513 free(tmp);
514 }
515 }
516
517
518 /***************************************
519 * This routine allocates a XA_AUD_HDR structure.
520 * aud_file is assumed to be consumable.
521 *
522 **************/
Get_Aud_Hdr(aud_hdr,num)523 XA_AUD_HDR *Get_Aud_Hdr(aud_hdr,num)
524 XA_AUD_HDR *aud_hdr;
525 xaULONG num;
526 {
527 XA_AUD_HDR *temp_hdr;
528 temp_hdr = (XA_AUD_HDR *)malloc( sizeof(XA_AUD_HDR) );
529 if (temp_hdr == 0) XA_Child_Dies1("Get_AUD_Hdr: malloc failed\n");
530
531 temp_hdr->num = num;
532 temp_hdr->filename = 0;
533 temp_hdr->max_faud_size = 0;
534 temp_hdr->first_snd = 0;
535 temp_hdr->last_snd = 0;
536
537 if (aud_hdr == 0)
538 {
539 xa_aud_hdr_start = temp_hdr;
540 temp_hdr->next = temp_hdr;
541 temp_hdr->prev = temp_hdr;
542 }
543 else
544 {
545 temp_hdr->prev = aud_hdr;
546 temp_hdr->next = aud_hdr->next;
547 aud_hdr->next = temp_hdr;
548 xa_aud_hdr_start->prev = temp_hdr;
549 }
550 return(temp_hdr);
551 }
552
553
554 /***************************************
555 *
556 *
557 **************/
XA_Audio_Child()558 void XA_Audio_Child()
559 { int argc = 0;
560 xa_aud_hdr_start = xa_aud_hdr_cur = 0;
561 xa_aud_hdr_num = 0;
562
563 audiof = (XA_AUD_FLAGS *)malloc( sizeof(XA_AUD_FLAGS) );
564 if (audiof==0) XA_Child_Dies1("audiof malloc err");
565
566 xa_audio_parent_pid = getppid();
567
568 /* don't init */
569 audiof->enable = xaFALSE;
570 audiof->mute = xaFALSE;
571 audiof->newvol = xaTRUE;
572 audiof->divtest = 2;
573 audiof->fromfile = xaFALSE;
574 audiof->bufferit = xaFALSE;
575
576 audiof->port = DEFAULT_XA_AUDIO_PORT;
577 audiof->volume = 0;
578 audiof->playrate = 0;
579 audiof->device = 0;
580
581 signal(SIGINT,XA_Child_Dies);
582 signal(SIGPIPE,XA_Child_Dies);
583
584 XtToolkitInitialize();
585 theAudContext = XtCreateApplicationContext();
586 /* do we need a Display? */
587 theAudDisp = XtOpenDisplay(theAudContext, NULL, "xanimaud", "XAnimAud",
588 NULL,0,&argc,0);
589 if (theAudDisp == NULL) { TheEnd1("Unable to open display\n"); }
590
591 /* POD DEBUGGING PURPOSES */
592 AUD_DEBUG fprintf(stderr,"CHILD IS AWAKE\n");
593
594 XtAppAddInput(theAudContext, xa_audio_fd[XA_FD_READ],
595 (XtPointer)XtInputReadMask,
596 (XtInputCallbackProc)XA_Child_Loop, 0);
597
598 /* Tell Video We're alive */
599 XA_Audio_Send_ACK(XA_IPC_OK,0,0);
600
601 /* Have Child check for Mommy/Daddy once in a while.
602 * That way if they kick off and the Child is orphaned, it can join them.
603 */
604 XtAppAddTimeOut(theAudContext,5000,(XtTimerCallbackProc)XA_Child_BOFL,
605 (XtPointer)(NULL));
606
607 XtAppMainLoop(theAudContext);
608
609 XA_Child_Dies((int)(0));
610 }
611
XA_Child_BOFL()612 void XA_Child_BOFL()
613 { xaLONG now = XA_Time_Read();
614
615 AUD_DEBUG fprintf(stderr,"CHILD_BOFL now %d last %d ppid %d\n",
616 now,xa_child_last_time,xa_audio_parent_pid);
617 /* 24 expiration fail safe */
618 if ( (now - xa_child_last_time) > 86400000) XA_Child_Dies1("Parents??");
619
620 /* Mom? Dad? every 5 seconds */
621 if ( (now - xa_child_last_time) > 8000)
622 { int ppid = getppid();
623 if (ppid != xa_audio_parent_pid) XA_Child_Dies1("Parents??");
624 }
625 XtAppAddTimeOut(theAudContext,5000, (XtTimerCallbackProc)XA_Child_BOFL,
626 (XtPointer)(NULL));
627 }
628
629 /***************************************
630 *
631 *
632 **************/
XA_Child_Loop(w,fin,id)633 void XA_Child_Loop(w,fin,id)
634 XtPointer w;
635 int *fin;
636 XtInputId *id;
637 { int ret;
638 XA_IPC_HDR ipc_cmd;
639 xaUBYTE *ipc_buff;
640
641 AUD_DEBUG fprintf(stderr,"LoopED\n");
642
643 /* Technically we KNOW *fin is xa_audio_fd[XA_FD_READ] */
644
645 ret = XA_Audio_Receive_Video_CMD(&ipc_cmd, 5000);
646 if (ret == XA_IPC_ERR)
647 {
648 XtRemoveInput(*id);
649 }
650 else if (ret == XA_IPC_OK)
651 {
652 switch( ipc_cmd.cmd )
653 {
654 /* send back status = STOPPED */
655 case XA_IPC_AUD_SETUP:
656 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_SETUP\n");
657 XA_Audio_Setup();
658 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xa_audio_status);
659 break;
660
661 case XA_IPC_AUD_INIT:
662 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_INIT\n");
663 if (xa_audio_present == XA_AUDIO_UNK) XA_Audio_Init();
664 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xa_audio_present);
665 break;
666
667 case XA_IPC_AUD_KILL:
668 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_KILL\n");
669 XA_Audio_Kill();
670 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xa_audio_status);
671 break;
672
673 /* solely for returning audio status */
674 case XA_IPC_GET_STATUS:
675 AUD_DEBUG fprintf(stderr,"AUD IPC: GET_STATUS\n");
676 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xa_audio_status);
677 break;
678
679 case XA_IPC_GET_PRESENT:
680 AUD_DEBUG fprintf(stderr,"AUD IPC: GET_PRESENT\n");
681 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xa_audio_present);
682 break;
683
684 case XA_IPC_AUD_PREP:
685 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_PREP %x\n",(xaULONG)xa_snd_cur);
686 XA_Audio_Prep();
687 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xa_audio_status);
688 break;
689
690 case XA_IPC_AUD_ON:
691 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_ON %x\n",(xaULONG)xa_snd_cur);
692 XA_Audio_On();
693 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xa_audio_status);
694 break;
695
696 case XA_IPC_AUD_OFF:
697 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_OFF\n");
698 XA_Audio_Off(ipc_cmd.value);
699 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xa_audio_status);
700 break;
701
702 case XA_IPC_AUD_PORT:
703 audiof->port = ipc_cmd.value;
704 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_PORT\n");
705 if (XA_Set_Output_Port) XA_Set_Output_Port(ipc_cmd.value);
706 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
707 break;
708
709 case XA_IPC_AUD_STOG:
710 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_STOG\n");
711 XA_Speaker_Tog(ipc_cmd.value);
712 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
713 break;
714
715 case XA_IPC_AUD_HTOG:
716 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_HTOG\n");
717 XA_Headphone_Tog(ipc_cmd.value);
718 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
719 break;
720
721 case XA_IPC_AUD_LTOG:
722 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_LTOG\n");
723 XA_LineOut_Tog(ipc_cmd.value);
724 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
725 break;
726
727 case XA_IPC_GET_CFREQ:
728 { xaULONG hfreq = ipc_cmd.value;
729 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_CFREQ %x freq %d\n",
730 (xaULONG)(XA_Closest_Freq),hfreq);
731 hfreq = XA_Closest_Freq(hfreq);
732 AUD_DEBUG fprintf(stderr,"CFREQ: hfreq = %d\n",hfreq);
733 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,hfreq);
734 }
735 break;
736
737 /*POD NOTE: CFREQ must be called before this */
738 case XA_IPC_GET_BSIZE:
739 { AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_BSIZE\n");
740 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xa_audio_hard_buff);
741 }
742 break;
743
744 case XA_IPC_FILE:
745 AUD_DEBUG fprintf(stderr,"AUD IPC: received FILE %d\n",ipc_cmd.value);
746 xa_aud_hdr_cur = Get_Aud_Hdr(xa_aud_hdr_cur,ipc_cmd.value);
747 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
748 break;
749
750 /*************************
751 * This Command sets xa_aud_hdr_cur to Audio File num
752 * and then changes/sets the filename to incoming buffer
753 ********/
754 case XA_IPC_FNAME:
755 AUD_DEBUG fprintf(stderr,"AUD FNAME: %d\n",ipc_cmd.value);
756 if (ipc_cmd.len)
757 { int file_ret = XA_Child_Find_File(ipc_cmd.value,0);
758 ipc_buff = XA_Audio_Receive_Video_Buf(ipc_cmd.len,500);
759 /* if no such file or couldn't read name - err and exit */
760 if ( (ipc_buff == 0) || (file_ret == xaNOFILE) )
761 { ipc_buff = 0;
762 XtRemoveInput(*id);
763 fprintf(stderr,"AUD FNAME: buf %x fnum %d fret %d\n",
764 (xaULONG)ipc_buff, ipc_cmd.value, file_ret);
765 XA_Audio_Send_ACK(XA_IPC_ACK_ERR,ipc_cmd.id,0);
766 break;
767 }
768 AUD_DEBUG fprintf(stderr,"AUD FNAME: %s \n",ipc_buff);
769
770 /** Add/replace name in current audio header */
771 if (xa_aud_hdr_cur->filename) free(xa_aud_hdr_cur->filename);
772 xa_aud_hdr_cur->filename = (char *)ipc_buff; ipc_buff = 0;
773 ipc_cmd.len = 0; /* we've used it */
774 }
775 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
776 break;
777
778 /* Merges passed in file with previous file */
779 case XA_IPC_MERGEFILE:
780 AUD_DEBUG fprintf(stderr,"AUD IPC: rcvd MERGEFILE %d\n",ipc_cmd.value);
781 { XA_AUD_HDR *prev_hdr = xa_aud_hdr_cur;
782 XA_Child_Find_File(ipc_cmd.value,0); /* POD add check for err */
783 /* Free previous audio if any */
784 if (prev_hdr->first_snd) Free_SNDs(prev_hdr->first_snd);
785 if (prev_hdr->filename) free(prev_hdr->filename);
786 /* copy selected portions */
787 prev_hdr->filename = xa_aud_hdr_cur->filename;
788 prev_hdr->max_faud_size = xa_aud_hdr_cur->max_faud_size;
789 prev_hdr->first_snd = xa_aud_hdr_cur->first_snd;
790 prev_hdr->last_snd = xa_aud_hdr_cur->last_snd;
791 prev_hdr->init_aud = xa_aud_hdr_cur->init_aud;
792 /* Free up current one */
793 xa_aud_hdr_cur = Return_Aud_Hdr(xa_aud_hdr_cur);
794 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
795 }
796 break;
797
798
799 case XA_IPC_UNFILE:
800 AUD_DEBUG fprintf(stderr,"AUD IPC: rcvd UNFILE %d\n",ipc_cmd.value);
801 if ( XA_Child_Find_File(ipc_cmd.value,0) == xaNOFILE)
802 { XtRemoveInput(*id);
803 fprintf(stderr,"AUD IPC: UNFILE no such file %d\n",ipc_cmd.value);
804 XA_Audio_Send_ACK(XA_IPC_ACK_ERR,ipc_cmd.id,0); /* err and exit */
805 break;
806 }
807 /* Find_File set's xa_aud_hdr_cur correctly above - assume it's
808 * the last one. */
809 xa_aud_hdr_cur = Return_Aud_Hdr(xa_aud_hdr_cur);
810 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
811 break;
812
813 case XA_IPC_PLAY_FILE:
814 { xaULONG ok;
815 AUD_DEBUG fprintf(stderr,"AUD IPC: received PLAY_FILE\n");
816 if (xa_audio_present==XA_AUDIO_OK)
817 ok = XA_Child_Find_File(ipc_cmd.value,0);
818 if (ok == xaTRUE)
819 {
820 if (xa_aud_fd>=0) { close(xa_aud_fd); xa_aud_fd = -1; }
821 if (xa_aud_hdr_cur->filename)
822 {
823 if ( (xa_aud_fd=open(xa_aud_hdr_cur->filename,O_RDONLY,NULL)) < 0)
824 {
825 fprintf(stderr,"AUD IPC: Open file %s for audio err\n",
826 xa_aud_hdr_cur->filename);
827 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xaFALSE);
828 break;
829 }
830 }
831 /*POD ?? Is buffer only used when playing from a file??? */
832 if ((xa_aud_hdr_cur->max_faud_size) && (xa_audcodec_buf==0))
833 { xa_audcodec_buf = (xaUBYTE *)malloc( xa_audcodec_maxsize );
834 if (xa_audcodec_buf==0) /* audio fatal */
835 { XtRemoveInput(*id);
836 XA_Audio_Send_ACK(XA_IPC_ACK_ERR,ipc_cmd.id,xaFALSE);
837 break;
838 }
839 }
840 if (xa_snd_cur->fpos >= 0)
841 {
842 xa_snd_cur->snd = xa_audcodec_buf;
843 XA_Read_Audio_Delta(xa_aud_fd,xa_snd_cur->fpos,
844 xa_snd_cur->tot_bytes,xa_audcodec_buf);
845 }
846 }
847 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,ok);
848 }
849 break;
850
851 case XA_IPC_N_FILE:
852 { xaULONG ok;
853 AUD_DEBUG fprintf(stderr,"AUD IPC: received N_FILE %d\n",ipc_cmd.value);
854 if (xa_audio_present==XA_AUDIO_OK)
855 ok = XA_Child_Find_File(ipc_cmd.value,0);
856 else ok = xaNOFILE;
857 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,ok);
858 }
859 break;
860
861 case XA_IPC_P_FILE:
862 { xaULONG ok;
863 AUD_DEBUG fprintf(stderr,"AUD IPC: received P_FILE\n");
864 if (xa_audio_present==XA_AUDIO_OK)
865 ok = XA_Child_Find_File(ipc_cmd.value,1);
866 else ok = xaNOFILE;
867 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,ok);
868 }
869 break;
870
871 case XA_IPC_SND_INIT:
872 {
873 AUD_DEBUG fprintf(stderr,"AUD IPC: SND_INIT\n");
874 XA_Audio_Init_Snd(xa_snd_cur);
875 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
876 }
877 break;
878
879 case XA_IPC_SND_ADD:
880 { XA_SND *new_snd = 0;
881 AUD_DEBUG fprintf(stderr,"AUD IPC: SND_ADD\n");
882 if (ipc_cmd.len)
883 { xaULONG sret;
884
885 if (ipc_cmd.value != xa_aud_hdr_cur->num) /* for different file */
886 {
887 sret = XA_Child_Find_File(ipc_cmd.value,1);
888 if (sret == xaNOFILE)
889 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xaFALSE);
890 }
891
892 new_snd = (XA_SND *)
893 XA_Audio_Receive_Video_Buf(ipc_cmd.len,500);
894 if (new_snd) sret = XA_IPC_Sound(xa_aud_hdr_cur,new_snd);
895 else sret = 0;
896 ipc_cmd.len = 0;
897 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,sret);
898 }
899 else XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xaFALSE);
900
901 /* SND_BUF MUST follow */
902 XA_Audio_Receive_Video_CMD(&ipc_cmd, 5000);
903 if (ipc_cmd.cmd != XA_IPC_SND_BUF)
904 XA_Child_Dies1("SND_BUF Did NOT follow SND_ADD\n");
905 AUD_DEBUG fprintf(stderr,"AUD IPC: SND_BUF\n");
906 if (ipc_cmd.len)
907 { xaULONG sret = xaFALSE;
908 if (new_snd) new_snd->snd =
909 (xaUBYTE *)XA_Audio_Receive_Video_Buf(ipc_cmd.len,500);
910 if (new_snd->snd) sret = xaTRUE;
911 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,sret);
912 ipc_cmd.len = 0;
913 }
914 else
915 {
916 new_snd->snd = 0;
917 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,xaTRUE);
918 }
919 }
920 break;
921
922 case XA_IPC_SET_AUDBUFF:
923 AUD_DEBUG fprintf(stderr,"AUD IPC: SET_AUDBUFF\n");
924 xa_aud_hdr_cur->max_faud_size = ipc_cmd.value;
925 if (xa_aud_hdr_cur->max_faud_size > xa_audcodec_maxsize)
926 xa_audcodec_maxsize = xa_aud_hdr_cur->max_faud_size;
927 xa_av_time_off = ipc_cmd.value;
928 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
929 break;
930
931 case XA_IPC_SET_KLUDGE2:
932 AUD_DEBUG fprintf(stderr,"AUD IPC: SET_KLUDGE2\n");
933 xa_kludge2_dvi = ipc_cmd.value;
934 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
935 break;
936
937 case XA_IPC_SET_KLUDGE900:
938 AUD_DEBUG fprintf(stderr,"AUD IPC: SET_KLUDGE900\n");
939 xa_kludge900_aud = ipc_cmd.value;
940 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
941 break;
942
943 case XA_IPC_VID_TIME:
944 AUD_DEBUG fprintf(stderr,"AUD IPC: VID_TIME\n");
945 xa_av_time_off = ipc_cmd.value;
946 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
947 break;
948
949 case XA_IPC_RST_TIME:
950 { xaULONG tt = XA_Time_Read();
951 AUD_DEBUG fprintf(stderr,"AUD IPC: RST_TIME time %d\n",tt);
952 XA_IPC_Reset_AV_Time(ipc_cmd.value);
953 tt = XA_Time_Read();
954 AUD_DEBUG fprintf(stderr,"AUD IPC: time end %d\n",tt);
955 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
956 }
957 break;
958
959 case XA_IPC_AUD_ENABLE:
960 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_ENABLE\n");
961 audiof->enable = ipc_cmd.value;
962 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
963 break;
964
965 case XA_IPC_AUD_MUTE:
966 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_MUTE\n");
967 audiof->mute = ipc_cmd.value;
968 audiof->newvol = xaTRUE;
969 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
970 break;
971
972 case XA_IPC_AUD_VOL:
973 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_VOL\n");
974 audiof->volume = ipc_cmd.value;
975 audiof->newvol = xaTRUE;
976 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
977 break;
978
979 case XA_IPC_AUD_RATE:
980 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_RATE\n");
981 audiof->playrate = ipc_cmd.value;
982 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
983 break;
984
985 case XA_IPC_AUD_DEV:
986 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_DEV\n");
987 if (ipc_cmd.len)
988 {
989 ipc_buff = XA_Audio_Receive_Video_Buf(ipc_cmd.len,500);
990 if (ipc_buff)
991 { AUD_DEBUG fprintf(stderr,"DEVICE: %s \n",ipc_buff);
992 audiof->device = (char *)(ipc_buff);
993 ipc_buff = 0;
994 }
995 else { AUD_DEBUG fprintf(stderr,"FILE: err\n"); }
996 ipc_cmd.len = 0; /* indicate we've read it */
997 }
998 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
999 break;
1000
1001 case XA_IPC_AUD_FFLAG:
1002 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_FFLAG\n");
1003 audiof->fromfile = ipc_cmd.value;
1004 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
1005 break;
1006
1007 case XA_IPC_AUD_BFLAG:
1008 AUD_DEBUG fprintf(stderr,"AUD IPC: AUD_BFLAG\n");
1009 audiof->bufferit = ipc_cmd.value;
1010 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
1011 break;
1012
1013 case XA_IPC_ERR:
1014 XtRemoveInput(*id);
1015 XA_Audio_Send_ACK(XA_IPC_ACK_ERR,ipc_cmd.id,0); /* err and exit */
1016 break;
1017
1018 case XA_IPC_HELLO:
1019 AUD_DEBUG fprintf(stderr,"AUD IPC: received Hello\n");
1020 XA_Audio_Send_ACK(XA_IPC_ACK_OK,ipc_cmd.id,0);
1021 break;
1022
1023 case XA_IPC_EXIT:
1024 AUD_DEBUG fprintf(stderr,"AUD IPC: received EXIT\n");
1025 XtRemoveInput(*id);
1026 XA_Audio_Send_ACK(XA_IPC_ACK_BYE,ipc_cmd.id,0);
1027 XA_Child_Dies((int)(0));
1028 break;
1029
1030 case XA_IPC_BOFL:
1031 AUD_DEBUG fprintf(stderr,"AUD IPC: received BOFL\n");
1032 /* No ACK needed */
1033 xa_child_last_time = XA_Time_Read();
1034 break;
1035
1036 default:
1037 AUD_DEBUG fprintf(stderr,"AUD IPC: unknown cmd %d\n",ipc_cmd.cmd);
1038 XtRemoveInput(*id);
1039 XA_Audio_Send_ACK(XA_IPC_ACK_ERR,ipc_cmd.id,0); /* err and exit */
1040 break;
1041 }
1042 /* Flush len if no command uses it */
1043 if (ipc_cmd.len)
1044 {
1045 ipc_buff = XA_Audio_Receive_Video_Buf(ipc_cmd.len,500);
1046 free(ipc_buff); ipc_buff = 0;
1047 XtRemoveInput(*id);
1048 XA_Audio_Send_ACK(XA_IPC_ACK_ERR,ipc_cmd.id,0); /* err and exit */
1049 } else ipc_buff = 0;
1050 } /* valid input */
1051 }
1052
1053 /*********************************
1054 * This routine sets up the xa_audio_fd and xa_video_fd pipes, then
1055 * forks off the Audio Child process.
1056 *
1057 * + The Parent returns(xaTRUE) on success, xaFALSE on failure.
1058 * + The Child calls XA_Audio_Child().
1059 *
1060 ****************/
XA_Give_Birth()1061 xaULONG XA_Give_Birth()
1062 { int ret;
1063 #ifndef XA_SOCKET
1064 ret = pipe( xa_audio_fd );
1065 if (ret) { AUD_DEBUG fprintf(stderr,"PIPE for audio failed: %d\n",errno); }
1066 else
1067 {
1068 ret = pipe( xa_video_fd );
1069 if (ret) { AUD_DEBUG fprintf(stderr,"PIPE for video failed: %d\n",errno); }
1070 else
1071 {
1072 #else
1073 {
1074 { int sv[2];
1075 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
1076 if (ret) { fprintf(stderr,"IPC socketpair failed %d\n",errno);
1077 return(xaFALSE);
1078 }
1079 xa_audio_fd[0] = sv[1]; /* audio reads */
1080 xa_video_fd[1] = sv[1]; /* audio writes */
1081
1082 xa_video_fd[0] = sv[0]; /* video reads */
1083 xa_audio_fd[1] = sv[0]; /* video writes */
1084 #endif
1085 xa_audio_child = fork();
1086 if (xa_audio_child == 0) /* I am the Audio Child */
1087 {
1088 AUD_DEBUG fprintf(stderr,"I am the Child\n");
1089 XA_Audio_Child();
1090 exit(0);
1091 }
1092 else if (xa_audio_child < 0) /* Still Born */
1093 {
1094 AUD_DEBUG fprintf(stderr,"Audio Child Still Born: %d\n",errno);
1095 }
1096 else /* I am the Video Parent */
1097 {
1098 AUD_DEBUG fprintf(stderr,"I am the Parent(child %d)\n",xa_audio_child);
1099 return(xaTRUE);
1100 }
1101 }
1102 }
1103 return(xaFALSE);
1104 }
1105
1106 /*********************************
1107 * Move along Audio Header til num is matched.
1108 * returns xaTRUE if found AND has valid snd.
1109 * returns xaNOFILE if no file has that num.
1110 * returns xaFALSE if file found, but no audio attached.
1111 * Else returns xaFALSE.
1112 *
1113 * Set's global variable xa_snd_cur
1114 ****************/
1115 xaULONG XA_Child_Find_File(num,flag)
1116 xaULONG num;
1117 xaULONG flag; /* 0 means next, 1 means prev */
1118 { XA_AUD_HDR *cur = xa_aud_hdr_cur;
1119 do
1120 {
1121 AUD_DEBUG fprintf(stderr,"num %d cnum %d cur %x n/p %x %x hdr %x\n",
1122 num, cur->num, (xaULONG)cur, (xaULONG)cur->next, (xaULONG)cur->prev,
1123 (xaULONG) xa_aud_hdr_cur);
1124 if (cur->num == num)
1125 {
1126 xa_aud_hdr_cur = cur;
1127 xa_snd_cur = cur->first_snd;
1128 if (xa_snd_cur) return(xaTRUE);
1129 else return(xaFALSE);
1130 }
1131 cur = (flag == 0)?(cur->next):(cur->prev);
1132 } while(cur != xa_aud_hdr_cur);
1133 return(xaNOFILE);
1134 }
1135
1136 /*********************************
1137 *
1138 ****************/
1139 void XA_IPC_Reset_AV_Time(vid_time)
1140 xaLONG vid_time;
1141 { int xflag = xaFALSE;
1142
1143 if (xa_snd_cur==0) { AUD_DEBUG fprintf(stderr,"AA\n"); return; }
1144 XA_Audio_Init_Snd(xa_snd_cur);
1145 /* Move to the correct snd chunk */
1146 while(xflag == xaFALSE)
1147 { xaLONG snd_time = xa_snd_cur->snd_time;
1148 if (snd_time > vid_time)
1149 { XA_SND *p_snd = xa_snd_cur->prev;
1150 AUD_DEBUG fprintf(stderr,"s>v %d %d\n",snd_time,vid_time);
1151 if (p_snd) xa_snd_cur = p_snd;
1152 else xflag = xaTRUE;
1153 }
1154 else if (snd_time < vid_time)
1155 { XA_SND *n_snd = xa_snd_cur->next;
1156 AUD_DEBUG fprintf(stderr,"s<v %d %d\n",snd_time,vid_time);
1157 if (n_snd)
1158 {
1159 if (n_snd->snd_time <= vid_time) xa_snd_cur = n_snd;
1160 else xflag = xaTRUE;
1161 }
1162 else xflag = xaTRUE;
1163 }
1164 else
1165 {
1166 AUD_DEBUG fprintf(stderr,"s=v %d %d\n",snd_time,vid_time);
1167 xflag = xaTRUE;
1168 }
1169 } /* end while xflag */
1170
1171 /* Move within the snd chunk - HAVE NOP FLAG */
1172 if (xa_snd_cur)
1173 { XA_SND *shdr = xa_snd_cur;
1174 /* read in from file if needed */
1175 if (xa_snd_cur->fpos >= 0)
1176 {
1177 xa_snd_cur->snd = xa_audcodec_buf;
1178 XA_Read_Audio_Delta(xa_aud_fd,xa_snd_cur->fpos,
1179 xa_snd_cur->tot_bytes,xa_audcodec_buf);
1180 }
1181 { xaULONG tmp_cnt; xaLONG diff;
1182
1183 /* time diff in ms */
1184 diff = (vid_time - shdr->snd_time); if (diff < 0) diff = 0;
1185 /* calc num of samples in that time frame */
1186 tmp_cnt = (diff * shdr->ifreq) / 1000;
1187 if (tmp_cnt & 0x01) tmp_cnt--; /* make multiple of 2 for ADPCM */
1188 /* Init snd_hdr */
1189 XA_Audio_Init_Snd(xa_snd_cur);
1190 if (tmp_cnt) /* not at beginning */
1191 { char *garb; /* play sound into garb buffer */
1192 garb = (char *)malloc(4 * tmp_cnt);
1193 if (garb)
1194 { diff = tmp_cnt - xa_snd_cur->delta(xa_snd_cur,garb,0,tmp_cnt);
1195 free(garb);
1196 if (diff != 0) fprintf(stderr,"AV Warn: rst sync err %x\n",diff);
1197 }
1198 }
1199 }
1200 xa_time_audio = vid_time;
1201 xa_timelo_audio = 0;
1202 } /* end of valid xa_snd_cur */
1203 }
1204
1205 void XA_IPC_Close_Pipes()
1206 {
1207 #ifdef XA_SOCKET
1208 if (xa_audio_fd[0] >= 0) { close(xa_audio_fd[0]); xa_audio_fd[0] = -1; }
1209 if (xa_audio_fd[1] >= 0) { close(xa_audio_fd[1]); xa_audio_fd[1] = -1; }
1210 xa_video_fd[0] = -1;
1211 xa_video_fd[1] = -1;
1212 #else
1213 if (xa_audio_fd[0] >= 0) { close(xa_audio_fd[0]); xa_audio_fd[0] = -1; }
1214 if (xa_audio_fd[1] >= 0) { close(xa_audio_fd[1]); xa_audio_fd[1] = -1; }
1215 if (xa_video_fd[0] >= 0) { close(xa_video_fd[0]); xa_video_fd[0] = -1; }
1216 if (xa_video_fd[1] >= 0) { close(xa_video_fd[1]); xa_video_fd[1] = -1; }
1217 #endif
1218 }
1219
1220 void XA_IPC_Set_Debug(value)
1221 xaULONG value;
1222 {
1223 audio_debug_flag = value;
1224 xa_debug = value;
1225 }
1226
1227 #else
1228
1229 /* prevents complaints from certain AR compilers */
1230 void XA_IPC_DUMMY(c,a,b)
1231 xaULONG *c,a,b;
1232 {
1233 *c = a + b;
1234 }
1235 #endif
1236
1237