home *** CD-ROM | disk | FTP | other *** search
/ Dream 44 / Amiga_Dream_44.iso / Linux / Apps / xanim.tgz / xanim / xanim27064 / xa_ipc.c < prev    next >
C/C++ Source or Header  |  1997-01-26  |  34KB  |  1,225 lines

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