1 
2 /*
3  * xa_audio.c
4  *
5  * Copyright (C) 1994-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 /***************************************************************************
20  * Fixes (Most are sent in by beta testers for which I'm grateful)
21  *
22  *	   - Linux: jixer should be mixer.
23  *	   - Linux: Added 8 bit converison routines.
24  *	   - Solaris audioio.h in include/sys not include/sun.
25  * 3Aug94  - Signals Suck. Use XtAppAddTimeOut instead.
26  * 4Aug94  - Linux 8 bit init incorrectly returning XA_AUDIO_SIGNED_1M.
27  *           Now it's XA_AUDIO_LINEAR_1M.
28  * 4Aug94  - Solaris opening ioctl using devtype instead of type and
29  *	     type should be audio_device_t (missing _t before).
30  * 4Aug94  - Linux: ioctl call to set volume was be reference only. It's
31  *	     now properly #ifdef'd depending on XA_LINUX_NEWER_SND.
32  * 5Aug94  - Linux: volume ioctl uses SOUND_MIXER_VOLUME now. Did try
33  *	     SOUND_MIXER_PCM, but some machines didn't like that.
34  * 8Aug94  - All: added XA_Audio_Pause routine for those devices that
35  *	     support pause/resume. Much better that having to flush it.
36  *	   - Solaris: XA_SOLARIS should've been SOLARIS. was causing
37  *	     core dumps etc.
38  *	   - ALL(but only affects Solaris): Solaris doesn't like writes to
39  *	     the audio buffer that aren't multiples of it's size. Is this
40  *	     the problem with SGI's? Anyways UpdateRing now enforces this.
41  *	   - Sparc: Detects if audio device is already in use and continues
42  *	     on without it. Before it used to hang until audio was freed.
43  *	   - Sparc: Volume turned off when flushing and then back on after.
44  *	     Gets rid of clicks/pops when exiting.
45  * 10Aug94 - Fixed problem with SGI machines. Samples not bytes and
46  * 	   - SIGNED_2MB not LINEAR_2MB.
47  * 10Aug94 - Change volume to 0-100%. May have broken them all. :^)
48  * 11Aug94 - Added code for HP9000/700 series. Have no clue if it works.
49  * 31Aug94 - Linux: Finally got the linux docs. I'm not querying the device
50  *	     to see what volume channel to use.
51  * 12Sep94 - SPARC 5: now look for CS4231 Audio devices. Should be treated
52  *	     the same as  Sparc 10's DBRI device.
53  * 21Sep94 - ALL: Closest_Freq() must have ifreq be signed in order for the
54  *           comparison's to be done correctly.
55  * 22Sep94 - Screw Pausing for now. Will put back later if deemed necessary.
56  * 27Sep94 - HP: found serious typo bug that caused the Audio Ring buffers
57  *	     to be overwritten by a large amount, trashing all sorts of
58  *	     memory and causing much grief. Thanks to John Atwood for
59  *	     helping find this one.
60  * 13Oct94 - SGI: really change LINEAR_2MB to be SIGNED_2MB this time. Arrgh.
61  * 26Oct94 - Added code to support NAS 1.2 p1
62  *					- Bob Phillips (bobp@syl.nj.nec.com)
63  * 28Oct94 - Added code to support NEC EWS 4800/330 - NEC
64  *					- Bob Phillips (bobp@syl.nj.nec.com)
65  * 02Nov94 - AF hardware type was set to 16 bit little endian, yet the AF
66  *	     library was told to expect native endian. This didn't work
67  *	     on Suns(nor would it on other big endian machines).
68  *	                        - Andrzej Filinski <andrzej+@POP.CS.CMU.EDU>
69  * 13Nov94 - NAS: fine tuned code for less drop out. Fixed up stop/start
70  *	     problems(echos).
71  * 13Jan95 - SGI: sgi volume is exponentional, not linear - Paul Close
72  * 19Jan95 - Sparc: Older Sparc can only have 1 audio output at a time
73  *           and not 0. This made it impossible to enable the headphones
74  *	     because the code would first try turning off the speaker and
75  *	     take an error.
76  * 30Jan95 - SONY: added support for Sony NEWS-5000 workstations - code
77  *	     written by Kazushi Yoshida.
78  * 16Mar95 - Finished remodified audio/vidoe sync code to handle more
79  *           compute intensive video(large frame or jpeg/mpeg)
80  * 17Mar95 - Merged Audio_Outputs into one routine so I didn't have to
81  *           keep modifying all of them(95% of the code was the same).
82  * 17Mar95 - Fixed bug in NAS audio that caused memory corruption after
83  *           an "unable to Toggle" error.
84  * 17Mar95 - Added Audio support for IBM AIX S6000 machines -
85  *		Code written by jeffk@watson.ibm.com (Jeff Kusnitz)
86  * 06Apr95 - Added Audio support for directly using HP's Audio Device
87  *		rather than going through all the upper audio library
88  *		layers. (HPDEV) Code written by Tobias Bading.
89  * 10Apr95 - Fixed bug where when Audio finished before Video, it wasn't
90  *	     being turned off before being turned on during the next loop
91  *	     or for the next animation.
92  * 10Apr95 - Fixed where hard_buff size was being set larger than the
93  *	     allocated buffer size for the following machines(Linux/AIX.
94  *           (All sorts of bad behavior - core's dumps etc).
95  * 10Apr95 - Fixed MS ADPCM bug when 11Khx and 22Khz ADPCM freq were scaled
96  *	     to 8Khz.
97  * 30Apr95 - Added audio support for Digital Alpha workstations
98  *           running MMS (morris@zko.dec.com)
99  * 11May95 - Added Audio support for NetBSD - written by Roland C Dowdeswell.
100  * 13Jun95 - SONY: modified for SVR4/NEWS-OS 6.x machines
101  *	     by Takashi Hagiwara, Sony Corporation (hagiwara@sm.sony.co.jp)
102  * 04Sep95 - SOLARIS: replaced SOLARIS define with SVR4. see what happens.
103  * 12Apr96 - HPDEV: occasionally audio device reports busy when trying to
104  *           set the sample rate. Now loop on this condition.
105  * 25Nov96 - HP AServer. Code fixed up by Steve Waterworth.
106  * 18Mar97 - Linux patch by Corey Minyard improves video/audio syncing on
107  *           some soundcards by using SNDCTL_DSP_SETFRAGMENT.
108  * 25Sep97 - Kevin Hildebrand recommended using AUDIO_ENCODING_SLINEAR
109  *           for NetBSD audio. Jarkko Torppa also reported this.
110  * 02Jan98 - SETFRAGMENT patch was causing 1/2 second delay on start on my
111  *	     linux system. Temporarily backing patch out til I can further
112  *	     debug it.  search for SETFRAG if you want to put it back in.
113  * 27Apr98 - Updates to NetBSD audio init code from Charles Hannum.
114  * 21Feb99 - Added routine *_Audio_Prep  to hide initialization delays
115  *	     when starting audio.
116  * 02Mar99 - Linux: Change XA_LINUX_NEWER_SND TO OLDER_SND to avoid confusion.
117  *
118  ****************************************************************************/
119 
120 
121 /****************************************************************************/
122 /**************** AUDIO DOCUMENTATION ***************************************/
123 /****************************************************************************/
124 /*
125  In order to support other machines type - XXX, the following routines must
126  be created and should be inside an #ifdef XA_XXX_AUDIO.
127 
128  Currently Needed Routines:
129  -----------------------------------
130    void  XA_Audio_Setup()
131    void  XXX_Audio_Init()
132    void  XXX_Audio_Kill()
133    void  XXX_Audio_Off()
134    void  XXX_Audio_Prep()
135    void  XXX_Audio_On()
136    xaULONG XXX_Closest_Freq(target_freq)
137    void  XXX_Set_Audio_Out(flag)   slowly replacing toggles
138    void  XXX_Speaker_Tog(flag)
139    void  XXX_Headphone_Tog(flag)
140    void  XXX_LineOut_Tog(flag)
141    void  XXX_Audio_Output()
142 
143  Currently Optional Routines:
144  -----------------------------------
145    XXX_Adjust_Volume(volume)
146 
147  NOTES: Currently stereo isn't supported. It could/can/will be added
148  later.
149 
150  The routine XA_Audio_Setup is responsible for mapping these routines
151  to the same routines(with XXX replaced by XA). See the XA_Audio_Setup
152  in the Sun section.
153 
154  Also the Hardware Audio Type should be defined in xanim.h. See the
155  AUDIO SECTION of xanim.h. This is then used in XA_Add_Sound routine
156  to determine the correct audio codec routine to convert the anim's
157  audio format to the hardware's audio format.
158 (NOTE: moving toward asking hardware what it can support for each
159        type of audio. )
160 
161  Brief description of how XAnim does the sound(may not be correct or finished
162  at the time you read this :^)
163 
164  As XAnim intially parses through the animations, a link list of SND_HDR's
165  is created(with the XA_Add_Sound routine) and attached to that animation
166  (in it's ANIM_HDR). These SND_HDR's contain audio information/data as it
167  existed in the animation file(it may just have a file postion and length so
168  the audio data can be read into memory or it may have a buffer already
169  containing the audio data).
170 
171  XA_Add_Sound determines if the audio format is support and what routine
172  should be used to decompress the audio. It also determines the closest
173  hardware frequency(with XA_Closest_Freq) and calculates how much time
174  (ms and fractional ms) it will take to play a converted sample that
175  is xa_audio_hard_buf(set by XA_Closest_Freq) samples in size along
176  with other information.
177 
178  A Ring of Audio buffers is created at init time(by XA_Audio_Init).
179  The XA_Update_Ring routine fills these buffers with identical sized
180  chunks of converted audio. The fact they're the same size simplifies
181  the keeping of audio time(since each audio chunk takes exactly the
182  same amount of time-which has been pre-calculated). audio time is
183  used to keep the video in sync with the audio.
184 
185  XA_Update_Ring is called in XA_Audio_Prep() just before audio is
186  started up(by XA_Audio_On) and is called in XA_Audio_Output() after
187  a Audio Ring buffer has been sent to the audio device.
188 
189  XA_Update_Ring fills empty ring positions by walking along the list
190  of SND_HDRs, converting the anim's audio to the proper audio format
191  a chunk at a time. It does this by calling the audio codec function
192  for that SND_HDR. The audio codec function converts and moves a set
193  number of audio samples into the given ring buffer and then returns
194  how many bytes in size that is.
195 
196  XA_Audio_Output just has to look at the current audio ring pointer,
197  send that many bytes to the audio device, update the audio time,
198  move along the ring and then call XA_Update_Ring.
199 
200  I might make XA/XXX_Audio_Output generic and then make machine
201  specific sub portions of it. As more machine types are added this
202  might make more sense.
203 
204  ----
205 
206  NOTE: I'm moving toward a separate audio process, this allows
207        blocking when writing to the audio device.  However, the
208        audio device should be opened non-blocking so that
209        XAnim may continue on without audio if the audio device
210        is in use by another program.
211 
212  XA_Audio_Prep() should enable and prep the audio.
213 
214  XA_Audio_On() should actually start the audio.
215 
216  XA_Audio_Off() should stop the audio. Ideally this routine should
217  immediate stop audio and flush what ever information has piled
218  up. Unfortunately, many audio drivers are (deficient?) lacking
219  this support.
220 
221  XA_Audio_Init() opens the audio device and initializes the variables.
222  XA_Audio_Kill() closes the device and frees up any hardware specific
223  memory structures.
224 
225  ----
226  Mark Podlipec - podlipec@Baynetworks.com  or  podlipec@@shell.portal.com
227 */
228 
229 /* TOP */
230 
231 #include "xa_audio.h"
232 
233 /* POD note:  For opening audio device non-blocking. Should probably set it
234  * back to blocking after successful open, but ONLY if compiling with
235  * the audio child.
236  */
237 
238 #ifndef O_NDELAY
239 #ifdef O_NONBLOCK
240 #define O_NDELAY  O_NONBLOCK
241 #else
242 #define O_NDELAY 0
243 #endif
244 #endif
245 
246 extern XA_AUD_FLAGS *vaudiof;
247 extern xaULONG xa_vaudio_present;
248 extern XtAppContext  theAudContext;
249 
250 
251 /***************** ITIMER EXPERIMENTATION ********************************/
252 /* number of ms we let audio buffer get ahead of actual audio. */
253 xaLONG xa_out_time = 250; /* PODNOTE: this is actually reset later on */
254 xaULONG xa_out_init = 0;  /* number of initial audio ring bufs to write ahead*/
255 
256 /* 1000/XA_OUT_FREQADJ is number of extra itimer calls  */
257 #define XA_OUT_FREQADJ 1000
258 
259 /***************** XtAppAddTimeOut EXPERIMENTATION *************************/
260 XtIntervalId xa_interval_id = 0;
261 xaULONG        xa_interval_time = 1;
262 
263 extern Display	*theDisp;
264 extern xaULONG	xa_kludge900_aud;
265 
266 
267 /**** Non Hardware Specific Functions ************/
268 void XA_Audio_Init_Snd();
269 void Init_Audio_Ring();
270 void Kill_Audio_Ring();
271 void XA_Update_Ring();
272 void XA_Flush_Ring();
273 XA_SND *XA_Audio_Next_Snd();
274 void XA_Read_Audio_Delta();
275 xaLONG XA_Read_AV_Time();
276 extern xaLONG xa_time_now;
277 extern xaUBYTE *xa_audcodec_buf;
278 extern xaULONG xa_audcodec_maxsize;
279 extern int xa_aud_fd;
280 
281 
282 extern xaULONG XA_ADecode_PCMXM_PCM1M();
283 extern xaULONG XA_ADecode_PCM1M_PCM2M();
284 extern xaULONG XA_ADecode_DVIM_PCMxM();
285 extern xaULONG XA_ADecode_DVIS_PCMxM();
286 extern xaULONG XA_ADecode_IMA4M_PCMxM();
287 extern xaULONG XA_ADecode_IMA4S_PCMxM();
288 
289 
290 typedef struct AUDIO_RING_STRUCT
291 {
292   xaULONG time;
293   xaULONG timelo;
294   xaULONG len;
295   xaUBYTE *buf;
296   struct AUDIO_RING_STRUCT *next;
297 } XA_AUDIO_RING_HDR;
298 
299 XA_AUDIO_RING_HDR *xa_audio_ring = 0;
300 XA_AUDIO_RING_HDR *xa_audio_ring_t = 0;
301 
302 #define XA_AUDIO_MAX_RING_BUFF 2048
303 
304 /* NOTE: These must NOT be larger than XA_AUDIO_MAX_RING_BUFF above */
305 #define XA_HARD_BUFF_2K 2048
306 #define XA_HARD_BUFF_1K 1024
307 
308 
309 void Gen_Signed_2_uLaw();
310 void Gen_uLaw_2_Signed();
311 void Gen_aLaw_2_Signed();
312 void Gen_Arm_2_Signed();
313 
314 xaLONG  XA_uLaw_to_Signed();
315 xaUBYTE XA_Signed_To_uLaw();
316 xaULONG XA_Audio_Linear_To_AU();
317 
318 /*POD NOTE: Make these tables dynamically allocated */
319 /* Sun ULAW CONVERSION TABLES/ROUTINES */
320 xaUBYTE xa_sign_2_ulaw[256];
321 xaULONG xa_ulaw_2_sign[256];
322 xaULONG xa_alaw_2_sign[256];
323 
324 /* ARM VIDC MULAW CONVERSION TABLES/ROUTINES */
325 xaULONG xa_arm_2_signed[256];
326 
327 /* AUDIO CODEC DELTA ROUTINES */
328 xaULONG XA_Audio_1M_1M();
329 xaULONG XA_Audio_PCM1M_PCM2M();
330 xaULONG XA_Audio_PCM1S_PCM2M();
331 xaULONG XA_Audio_PCMXM_PCM1M();
332 xaULONG XA_Audio_PCMXS_PCM1M();
333 xaULONG XA_Audio_PCM2X_PCM2M();
334 
335 
336 /* AUDIO CODEC BUFFERING ROUTINES */
337 
338 extern xaULONG xa_audio_present;
339 extern xaULONG xa_audio_status;
340 
341 extern XA_SND *xa_snd_cur;
342 extern xaLONG  xa_time_audio;
343 extern xaLONG  xa_timelo_audio;
344 
345 extern XA_AUD_FLAGS *XAAUD;
346 /*
347 extern xaULONG xa_audio_mute;
348 extern xaLONG  xa_audio_volume;
349 extern xaULONG xa_audio_newvol;
350 extern double xa_audio_scale;
351 extern xaULONG xa_audio_buffer;
352 extern xaULONG xa_audio_playrate;
353 extern xaULONG xa_audio_divtest;  Z* testing only *Z
354 extern xaULONG xa_audio_port;
355 */
356 
357 xaULONG xa_vaudio_hard_buff = 0;		/* VID Domain snd chunk size */
358 
359 xaULONG xa_audio_hard_freq;		/* hardware frequency */
360 xaULONG xa_audio_hard_buff;		/* preferred snd chunk size */
361 xaULONG xa_audio_ring_size;		/* preferred num of ring entries */
362 xaULONG xa_audio_hard_type;		/* hardware sound encoding type */
363 xaULONG xa_audio_hard_bps;		/* hardware bytes per sample */
364 xaULONG xa_audio_hard_chans;		/* hardware number of chan. not yet */
365 xaULONG xa_audio_flushed = 0;
366 
367 void  XA_Audio_Setup();
368 void (*XA_Audio_Init)();
369 void (*XA_Audio_Kill)();
370 void (*XA_Audio_Off)();
371 void (*XA_Audio_Prep)();
372 void (*XA_Audio_On)();
373 void (*XA_Adjust_Volume)();
374 xaULONG (*XA_Closest_Freq)();
375 void  (*XA_Set_Output_Port)(); /* POD slowly replacing _Tog's */
376 void  (*XA_Speaker_Tog)();
377 void  (*XA_Headphone_Tog)();
378 void  (*XA_LineOut_Tog)();
379 
380 void New_Merged_Audio_Output();
381 
382 
383 /****************************************************************************/
384 /**************** NULL AUDIO DEFINED ROUTINES********************************/
385 /****************************************************************************/
386 /* useful for backing out audio when device opens fails, etc */
387 
388 void  XA_NoAudio_Nop();
389 xaULONG XA_NoAudio_Nop1();
390 void  XA_NoAudio_Nop2();
391 void  XA_Null_Audio_Setup();
392 
XA_Null_Audio_Setup()393 void XA_Null_Audio_Setup()
394 {
395   XA_Audio_Init		= XA_NoAudio_Nop;
396   XA_Audio_Kill		= XA_NoAudio_Nop;
397   XA_Audio_Off		= XA_NoAudio_Nop2;
398   XA_Audio_Prep		= XA_NoAudio_Nop;
399   XA_Audio_On		= XA_NoAudio_Nop;
400   XA_Closest_Freq	= XA_NoAudio_Nop1;
401   XA_Set_Output_Port	= XA_NoAudio_Nop2;
402   XA_Speaker_Tog	= XA_NoAudio_Nop;
403   XA_Headphone_Tog	= XA_NoAudio_Nop;
404   XA_LineOut_Tog	= XA_NoAudio_Nop;
405 
406   xa_snd_cur = 0;
407   xa_audio_present = XA_AUDIO_UNK;
408   xa_audio_status  = XA_AUDIO_STOPPED;
409   xa_audio_ring_size  = 8;
410 }
XA_NoAudio_Nop()411 void XA_NoAudio_Nop()				{ return; }
XA_NoAudio_Nop2(flag)412 void XA_NoAudio_Nop2(flag)	xaULONG flag;	{ return; }
XA_NoAudio_Nop1(num)413 xaULONG XA_NoAudio_Nop1(num)	xaULONG num;	{ return(0); }
414 
415 /****************************************************************************/
416 /**************** NO AUDIO DEFINED ROUTINES *********************************/
417 /****************************************************************************/
418 #ifndef XA_AUDIO
419 
420 void XA_No_Audio_Support();
421 
XA_Audio_Setup()422 void XA_Audio_Setup()
423 {
424   XA_Null_Audio_Setup();
425   XA_Audio_Init	= XA_No_Audio_Support;
426 }
427 
XA_No_Audio_Support()428 void XA_No_Audio_Support()
429 {
430   fprintf(stderr,"AUDIO SUPPORT NOT COMPILED IN THIS EXECUTABLE.\n");
431   return;
432 }
433 #endif
434 /****************************************************************************/
435 /******************* END OF NO AUDIO SPECIFIC ROUTINES **********************/
436 /****************************************************************************/
437 
438 
439 /****************************************************************************/
440 /**************** SPARC SPECIFIC ROUTINES ***********************************/
441 /****************************************************************************/
442 #ifdef XA_SPARC_AUDIO
443 
444 /******** START OF FIX SUN **********************************/
445 /* SINCE CC, GCC and SUN can't get their act together, let's do it
446  * for them. This is to fix some SERIOUS Bugs with Sun's include files.
447  *
448  * CC works fine with /usr/include/sys/ioccom.h, but not gnu's
449  * GCC works fine with it's version of Sun's ioccom.h, but not sun's
450  * You mix them up and your code doesn't run. ARGH!!!
451  */
452 
453 /* POD NOTE: We'll NOW HAVE TO RELY ON XA_???_AUDIO defines to determine
454  * SUN IO compatiblities. Wadda pain.
455  */
456 #ifndef SVR4    /* was SOLARIS */
457 
458 /* from sys/ioccom.h */
459 #undef _IO
460 #define _IO(x,y)        (_IOC_VOID|((x)<<8)|y)
461 #undef _IOR
462 #define _IOR(x,y,t)     (_IOC_OUT|((sizeof(t)&_IOCPARM_MASK)<<16)|((x)<<8)|y)
463 #undef _IOWR
464 #define _IOWR(x,y,t)    (_IOC_INOUT|((sizeof(t)&_IOCPARM_MASK)<<16)|((x)<<8)|y)
465 
466 /* from audioio.h  A = 0x41 */
467 #undef AUDIO_GETINFO
468 #define AUDIO_GETINFO   _IOR(0x41, 1, audio_info_t)
469 #undef AUDIO_SETINFO
470 #define AUDIO_SETINFO   _IOWR(0x41, 2, audio_info_t)
471 #undef AUDIO_DRAIN
472 #define AUDIO_DRAIN     _IO(0x41, 3)
473 #undef AUDIO_GETDEV
474 #define AUDIO_GETDEV    _IOR(0x41, 4, int)
475 
476 /* from stropts.h S = 0x53*/
477 #undef I_FLUSH
478 #define I_FLUSH         _IO(0x53,05)
479 /******** END OF FIX SUN **********************************/
480 #endif
481 
482 #ifndef AUDIO_ENCODING_LINEAR
483 #define AUDIO_ENCODING_LINEAR (3)
484 #endif
485 #ifndef AUDIO_ENCODING_ULAW
486 #define AUDIO_ENCODING_ULAW (3)
487 #endif
488 #ifndef AUDIO_DEV_UNKNOWN
489 #define AUDIO_DEV_UNKNOWN (0)
490 #endif
491 #ifndef AUDIO_DEV_AMD
492 #define AUDIO_DEV_AMD (1)
493 #endif
494 #ifndef AUDIO_SPEAKER
495 #define AUDIO_SPEAKER 0x01
496 #endif
497 #ifndef AUDIO_HEADPHONE
498 #define AUDIO_HEADPHONE 0x02
499 #endif
500 #ifndef AUDIO_LINE_OUT
501 #define AUDIO_LINE_OUT 0x04
502 #endif
503 #ifndef AUDIO_MIN_GAIN
504 #define AUDIO_MIN_GAIN (0)
505 #endif
506 #ifndef AUDIO_MAX_GAIN
507 #define AUDIO_MAX_GAIN (255)
508 #endif
509 
510 
511 void  Sparc_Audio_Init();
512 void  Sparc_Audio_Kill();
513 void  Sparc_Audio_Off();
514 void  Sparc_Audio_Prep();
515 void  Sparc_Audio_On();
516 void  Sparc_Adjust_Volume();
517 xaULONG Sparc_Closest_Freq();
518 void Sparc_Set_Output_Port();
519 void Sparc_Speaker_Toggle();
520 void Sparc_Headphone_Toggle();
521 
522 #define SPARC_MAX_VOL AUDIO_MAX_GAIN
523 #define SPARC_MIN_VOL AUDIO_MIN_GAIN
524 
525 static int devAudio;
526 static audio_info_t audio_info;
527 
528 
529 /********** XA_Audio_Setup **********************
530  *
531  * Also defines Sparc Specific variables.
532  *
533  *****/
XA_Audio_Setup()534 void XA_Audio_Setup()
535 {
536 
537   XA_Audio_Init		= Sparc_Audio_Init;
538   XA_Audio_Kill		= Sparc_Audio_Kill;
539   XA_Audio_Off		= Sparc_Audio_Off;
540   XA_Audio_Prep		= Sparc_Audio_Prep;
541   XA_Audio_On		= Sparc_Audio_On;
542   XA_Closest_Freq	= Sparc_Closest_Freq;
543   XA_Set_Output_Port	= Sparc_Set_Output_Port;
544   XA_Speaker_Tog	= Sparc_Speaker_Toggle;
545   XA_Headphone_Tog	= Sparc_Headphone_Toggle;
546   XA_LineOut_Tog	= Sparc_Headphone_Toggle;
547   XA_Adjust_Volume	= Sparc_Adjust_Volume;
548 
549   xa_snd_cur = 0;
550   xa_audio_present = XA_AUDIO_UNK;
551   xa_audio_status  = XA_AUDIO_STOPPED;
552   xa_audio_ring_size  = 8;
553 }
554 
555 
556 /********** Sparc_Audio_Init **********************
557  * Open /dev/audio and /dev/audioctl for Sparc's.
558  *
559  *****/
Sparc_Audio_Init()560 void Sparc_Audio_Init()
561 { int ret;
562 #ifdef SVR4	/* was SOLARIS */
563   audio_device_t type;
564 #else
565   int type;
566 #endif
567   DEBUG_LEVEL2 fprintf(stderr,"Sparc_Audio_Init\n");
568   if (xa_audio_present != XA_AUDIO_UNK) return;
569   devAudio = open("/dev/audio", O_WRONLY | O_NDELAY);
570   if (devAudio == -1)
571   {
572     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
573     else fprintf(stderr,"Audio_Init: Error %x opening audio device. - ",errno);
574     fprintf(stderr,"Will continue without audio\n");
575     xa_audio_present = XA_AUDIO_ERR;
576     return;
577   }
578   ret = ioctl(devAudio, AUDIO_GETDEV, &type);
579   /* POD NOTE: Sparc 5 has new audio device (CS4231) */
580 #ifdef SVR4	/* was SOLARIS */
581   if ( (   (strcmp(type.name, "SUNW,dbri"))   /* Not DBRI (SS10's) */
582         && (strcmp(type.name, "SUNW,CS4231")) /* and not CS4231 (SS5's) */
583         && (strcmp(type.name, "SUNW,sb16")))  /* and SoundBlaster 16 */
584       || ret) /* or ioctrl failed */
585 #else
586   if (ret || (type==AUDIO_DEV_UNKNOWN) || (type==AUDIO_DEV_AMD) )
587 #endif
588   { /* SPARC AU AUDIO */
589     DEBUG_LEVEL1 fprintf(stderr,"SPARC AMD AUDIO\n");
590     xa_audio_hard_type  = XA_AUDIO_SUN_AU;
591     xa_audio_hard_freq  = 8000;
592     xa_audio_hard_buff  = XA_HARD_BUFF_1K;             /* default buffer size */
593     xa_audio_hard_bps   = 1;
594     xa_audio_hard_chans = 1;
595     Gen_Signed_2_uLaw();
596   }
597   else /* DBRI or CS4231 or SB16 */
598   {
599     DEBUG_LEVEL1 fprintf(stderr,"SPARC DBRI or CS4231 or SB16 AUDIO\n");
600 #ifdef SVR4
601 #ifdef _LITTLE_ENDIAN
602     xa_audio_hard_type  = XA_AUDIO_SIGNED_2ML;
603 #else
604     xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB; /* default to this */
605 #endif
606 #else
607     xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
608 #endif
609     xa_audio_hard_freq  = 11025;
610     xa_audio_hard_buff  = XA_HARD_BUFF_1K;             /* default buffer size */
611     xa_audio_hard_bps   = 2;
612     xa_audio_hard_chans = 1;
613     AUDIO_INITINFO(&audio_info);
614 #ifdef SVR4	/* was SOLARIS */
615 /* POD-NOTE: Does this necessarily have to be 1024 (what the upper/lower
616  * limits???)
617  */
618     audio_info.play.buffer_size = XA_HARD_BUFF_1K;
619     xa_audio_hard_buff  = XA_HARD_BUFF_1K;   /* default buffer size */
620 #endif
621 
622 	/* POD NOTE: this is currently used for testing purposes */
623     switch(xa_kludge900_aud)
624     {
625       case 900:
626 fprintf(stderr,"Sun Audio: uLAW\n");
627 	xa_audio_hard_type  = XA_AUDIO_SUN_AU;
628 	xa_audio_hard_freq  = 8000;
629 	xa_audio_hard_bps   = 1;
630 	audio_info.play.sample_rate = 8000;
631 	audio_info.play.channels = 1;
632 	xa_audio_hard_bps   = 1;
633 	audio_info.play.encoding = AUDIO_ENCODING_ULAW;
634 	Gen_Signed_2_uLaw();
635 	break;
636       case 901:
637 fprintf(stderr,"Sun Audio: 8 bit PCM\n");
638 	audio_info.play.sample_rate = 11025;
639 	audio_info.play.precision = 8;
640 	audio_info.play.channels = 1;
641 	audio_info.play.encoding = AUDIO_ENCODING_LINEAR;
642 	break;
643       case 0:
644       default:
645 	audio_info.play.sample_rate = 11025;
646 	audio_info.play.precision = 16;
647 	audio_info.play.channels = 1;
648 	audio_info.play.encoding = AUDIO_ENCODING_LINEAR;
649 	break;
650     }
651 
652     ret = ioctl(devAudio, AUDIO_SETINFO, &audio_info);
653     if (ret)
654     {
655       fprintf(stderr,"AUDIO BRI FATAL ERROR %d\n",errno);
656       xa_audio_present = XA_AUDIO_ERR;
657       return;
658     }
659   }
660   xa_interval_id = 0;
661   xa_audio_present = XA_AUDIO_OK;
662   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
663   Init_Audio_Ring(xa_audio_ring_size,
664 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
665 }
666 
667 /********** Sparc_Audio_Kill **********************
668  * Close /dev/audio and /dev/audioctl.
669  *
670  *****/
Sparc_Audio_Kill()671 void Sparc_Audio_Kill()
672 {
673   /* TURN AUDIO OFF */
674   Sparc_Audio_Off(0);
675   xa_audio_present = XA_AUDIO_UNK;
676   /* SHUT THINGS DOWN  */
677   close(devAudio);
678   Kill_Audio_Ring();
679 }
680 
681 /********** Sparc_Audio_Off **********************
682  * Stop Audio Stream
683  *
684  *****/
Sparc_Audio_Off(flag)685 void Sparc_Audio_Off(flag)
686 xaULONG flag;
687 { long ret;
688 
689   if (xa_audio_status != XA_AUDIO_STARTED) return;
690 
691   /* SET FLAG TO STOP OUTPUT ROUTINE */
692   xa_audio_status = XA_AUDIO_STOPPED;
693 
694   /* TURN OFF SOUND ??? */
695   Sparc_Adjust_Volume(XA_AUDIO_MINVOL);
696 
697   /* FLUSH AUDIO DEVICE */
698   ret = ioctl(devAudio, I_FLUSH, FLUSHW);
699   if (ret == -1) fprintf(stderr,"Sparc Audio: off flush err %d\n",errno);
700 
701   xa_time_audio = -1;
702   xa_audio_flushed = 0;
703 
704   /* FLUSH AUDIO DEVICE AGAIN */
705   ret = ioctl(devAudio, I_FLUSH, FLUSHW);
706   if (ret == -1) fprintf(stderr,"Sparc Audio: off flush err %d\n",errno);
707 
708   /* RESTORE ORIGINAL VOLUME */
709   if (XAAUD->mute != xaTRUE) Sparc_Adjust_Volume(XAAUD->volume);
710 }
711 
712 /********** Sparc_Audio_Prep **********************
713  * Turn On Audio Stream.
714  *
715  *****/
Sparc_Audio_Prep()716 void Sparc_Audio_Prep()
717 {
718   DEBUG_LEVEL2
719   {
720     fprintf(stderr,"Sparc_Audio_Prep \n");
721   }
722   if (xa_audio_status == XA_AUDIO_STARTED) return;
723   else if (xa_audio_present != XA_AUDIO_OK) return;
724   else if (xa_snd_cur)
725   { int ret;
726 
727     /* CHANGE FREQUENCY IF NEEDED */
728     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
729     { audio_info_t a_info;
730       AUDIO_INITINFO(&a_info);
731       a_info.play.sample_rate = xa_snd_cur->hfreq;
732       ret = ioctl(devAudio, AUDIO_SETINFO, &a_info);
733       if (ret == -1) fprintf(stderr,"audio setfreq: freq %x errno %d\n",
734 						xa_snd_cur->hfreq, errno);
735       xa_audio_hard_freq = xa_snd_cur->hfreq;
736     }
737 
738     /* xa_snd_cur gets changes in Update_Ring() */
739     xa_out_time = 500;  /* keep audio fed 500ms ahead of video */
740     xa_out_init = xa_audio_ring_size - 1;
741     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
742     if (xa_interval_time == 0) xa_interval_time = 1;
743 
744 DEBUG_LEVEL1 fprintf(stderr,"ch_time %d out_time %d int time %d \n",xa_snd_cur->ch_time,xa_out_time,xa_interval_time);
745 
746     XA_Flush_Ring();
747     XA_Update_Ring(1000);
748     xa_audio_status = XA_AUDIO_PREPPED;
749   }
750 }
751 
752 /****-------------------------------------------------------------------****
753  *
754  ****-------------------------------------------------------------------****/
Sparc_Audio_On()755 void Sparc_Audio_On()
756 {
757   DEBUG_LEVEL2 fprintf(stderr,"Sparc_Audio_On \n");
758 
759   if (   (xa_snd_cur)
760       && (xa_audio_present == XA_AUDIO_OK)
761       && (xa_audio_status == XA_AUDIO_PREPPED) )
762   {
763     xa_audio_status = XA_AUDIO_STARTED;
764     xa_time_now = XA_Read_AV_Time();  /* get new time */
765     New_Merged_Audio_Output();
766   }
767 }
768 
769 
770 /********** Sparc_Closest_Freq **********************************************
771  *
772  * Global Variable Affect:
773  *   xaULONG xa_audio_hard_buff		must set but not larger than
774  *					XA_AUDIO_MAX_RING_BUF size
775  ****************************************************************************/
Sparc_Closest_Freq(ifreq)776 xaULONG Sparc_Closest_Freq(ifreq)
777 xaLONG ifreq;
778 {
779 
780 /* POD
781 fprintf(stderr,"Sparc_Closest_Freq: hardtype %x freq %d\n",
782 			xa_audio_hard_type,ifreq);
783 */
784 
785   if (xa_audio_hard_type==XA_AUDIO_SIGNED_2MB)
786   { static int valid[] = { 8000, 9600, 11025, 16000, 18900, 22050, 32000,
787 			      37800, 44100, 48000, 0};
788     xaLONG i = 0;
789     xaLONG best = 8000;
790 
791     xa_audio_hard_buff = XA_HARD_BUFF_1K;
792     while(valid[i])
793     {
794       if (xaABS(valid[i] - ifreq) < xaABS(best - ifreq)) best = valid[i];
795       i++;
796     }
797     return(best);
798   }
799   else return(8000);
800 }
801 
802 
803 /* Eventually merge everything to one */
Sparc_Set_Output_Port(aud_ports)804 void Sparc_Set_Output_Port(aud_ports)
805 xaULONG aud_ports;
806 { audio_info_t a_info;
807   xaLONG ret;
808   xaULONG sparc_ports = 0;
809   if (aud_ports & XA_AUDIO_PORT_INT)  sparc_ports |= AUDIO_SPEAKER;
810   if (aud_ports & XA_AUDIO_PORT_HEAD) sparc_ports |= AUDIO_HEADPHONE;
811   if (aud_ports & XA_AUDIO_PORT_EXT)  sparc_ports |= AUDIO_LINE_OUT;
812   AUDIO_INITINFO(&a_info);
813   a_info.play.port = sparc_ports;
814   ret = ioctl(devAudio, AUDIO_SETINFO, &a_info);
815   if (ret < 0) fprintf(stderr,"Audio: couldn't set speaker port %d\n",errno);
816 }
817 
818 /************* Sparc_Speaker_Toggle *****************************************
819  *
820  * flag = 0  turn speaker off
821  * flag = 1  turn speaker on
822  * flag = 2  toggle speaker
823  ****************************************************************************/
Sparc_Speaker_Toggle(flag)824 void Sparc_Speaker_Toggle(flag)
825 xaULONG flag;
826 {
827   switch(flag)
828   {
829     case  0: XAAUD->port &= ~XA_AUDIO_PORT_INT; break;
830     case  1: XAAUD->port |=  XA_AUDIO_PORT_INT; break;
831     default:  /* mutually exclusive set for now - never turn off */
832     { if ( !(XAAUD->port & XA_AUDIO_PORT_INT))
833 		XAAUD->port = XA_AUDIO_PORT_INT;
834     }
835   }
836   Sparc_Set_Output_Port(XAAUD->port);
837 }
838 
839 /************* Sparc_Headphone_Toggle *****************************************
840  *
841  * flag = 0  turn headphones off
842  * flag = 1  turn headphones on
843  * flag = 2  toggle headphones
844  ****************************************************************************/
Sparc_Headphone_Toggle(flag)845 void Sparc_Headphone_Toggle(flag)
846 xaULONG flag;
847 {
848   switch(flag)
849   {
850     case  0: XAAUD->port &= ~XA_AUDIO_PORT_HEAD; break;
851     case  1: XAAUD->port |=  XA_AUDIO_PORT_HEAD; break;
852     default:  /* mutually exclusive set for now - never turn off */
853     { if ( !(XAAUD->port & XA_AUDIO_PORT_HEAD))
854 		XAAUD->port = XA_AUDIO_PORT_HEAD;
855     }
856   }
857   Sparc_Set_Output_Port(XAAUD->port);
858 }
859 
860 
861 /********** Sparc_Adjust_Volume **********************
862  * Routine for Adjusting Volume on a Sparc
863  *
864  * Volume is in the range [0,XA_AUDIO_MAXVOL]
865  ****************************************************************************/
Sparc_Adjust_Volume(volume)866 void Sparc_Adjust_Volume(volume)
867 xaULONG volume;
868 { audio_info_t a_info;
869 
870   AUDIO_INITINFO(&a_info);
871   a_info.play.gain = SPARC_MIN_VOL +
872 	((volume * (SPARC_MAX_VOL - SPARC_MIN_VOL)) / XA_AUDIO_MAXVOL);
873   if (a_info.play.gain > SPARC_MAX_VOL) a_info.play.gain = SPARC_MAX_VOL;
874   ioctl(devAudio, AUDIO_SETINFO, &a_info);
875 }
876 #endif
877 /****************************************************************************/
878 /******************* END OF SPARC SPECIFIC ROUTINES *********************/
879 /****************************************************************************/
880 
881 /****************************************************************************/
882 /**************** S/6000  SPECIFIC ROUTINES *********************************/
883 /****************************************************************************/
884 #ifdef XA_AIX_AUDIO
885 
886 void  AIX_Audio_Init();
887 void  AIX_Audio_Kill();
888 void  AIX_Audio_Off();
889 void  AIX_Audio_Prep();
890 void  AIX_Audio_On();
891 
892 xaULONG AIX_Closest_Freq();
893 void  AIX_Speaker_Tog();
894 void  AIX_Headphone_Tog();
895 void  AIX_LineOut_Tog();
896 void  AIX_Adjust_Volume();
897 
898 
899 static int     devAudio;
900 static xaULONG   aix_audio_ports;
901 extern char  * xa_audio_device;
902 
903 /*----------------------------------------------------------------------------*/
904 /*                                                                            */
905 /*----------------------------------------------------------------------------*/
XA_Audio_Setup()906 void XA_Audio_Setup ( )
907 {
908   XA_Audio_Init		= AIX_Audio_Init;
909   XA_Audio_Kill		= AIX_Audio_Kill;
910   XA_Audio_Off		= AIX_Audio_Off;
911   XA_Audio_Prep		= AIX_Audio_Prep;
912   XA_Audio_On		= AIX_Audio_On;
913   XA_Closest_Freq	= AIX_Closest_Freq;
914   XA_Speaker_Tog	= AIX_Speaker_Tog;
915   XA_Headphone_Tog	= AIX_Headphone_Tog;
916   XA_LineOut_Tog	= AIX_LineOut_Tog;
917   XA_Adjust_Volume	= AIX_Adjust_Volume;
918 
919   xa_snd_cur = 0;
920   xa_audio_present = XA_AUDIO_UNK;
921   xa_audio_status = XA_AUDIO_STOPPED;
922   xa_audio_ring_size = 8;
923 }
924 
925 
926 /*----------------------------------------------------------------------------*/
927 /*                                                                            */
928 /*----------------------------------------------------------------------------*/
AIX_Audio_Init()929 void AIX_Audio_Init ( )
930 {
931   char         * devname;
932   audio_init     init;
933   audio_control  control;
934   audio_change   change;
935   int            rc;
936 
937   if ( xa_audio_present != XA_AUDIO_UNK )
938   {
939     return;
940   }
941 
942   devname = xa_audio_device;
943   if ( ( devAudio = open ( devname, O_WRONLY | O_NDELAY ) ) < 0 )
944   {
945     fprintf ( stderr, "AIX_Audio_Init: Open failed for '%s', errno = %d\n",
946               devname, errno );
947     xa_audio_present = XA_AUDIO_ERR;
948     return;
949   }
950 
951   /* Set the codec to some default values (the same ones the sun has   */
952   /* seem as good as any)                                              */
953 
954   xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
955   xa_audio_hard_freq  = 11025;
956   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
957   xa_audio_hard_bps   = 2;
958   xa_audio_hard_chans = 1;
959 
960   memset ( & init, '\0', sizeof ( init ) );
961 
962   init.srate =           11025;
963   init.mode =            PCM;
964   init.operation =       PLAY;
965   init.channels =        1;
966   init.flags =           BIG_ENDIAN | TWOS_COMPLEMENT;
967   init.bits_per_sample = 16;
968   init.bsize =           AUDIO_IGNORE;
969 
970   if ( ( rc = ioctl ( devAudio, AUDIO_INIT, & init ) ) < 0 )
971   {
972     fprintf ( stderr, "AIX_Audio_Init: AUDIO_INIT failed, errno = %d\n",
973               errno );
974   }
975 
976 
977   memset ( & control, '\0', sizeof ( control ) );
978   memset ( & change, '\0', sizeof ( change ) );
979 
980   aix_audio_ports = EXTERNAL_SPEAKER | INTERNAL_SPEAKER | OUTPUT_1;
981   aix_audio_ports = OUTPUT_1;
982 
983   change.balance       = 0x3fff0000;
984   change.balance_delay = 0;
985 
986   change.volume        = ( long ) ( 0x7fff << 16 );
987   change.volume_delay  = 0;
988 
989   change.input         = AUDIO_IGNORE;
990   change.output        = aix_audio_ports;
991   change.monitor       = AUDIO_IGNORE;
992   change.dev_info      = ( char * ) NULL;
993 
994   control.ioctl_request = AUDIO_CHANGE;
995   control.position =      0;
996   control.request_info =  ( char * ) & change;
997 
998   if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
999   {
1000     fprintf ( stderr, "AIX_Audio_Init: AUDIO_CONTROL failed, errno = %d\n",
1001               errno );
1002   }
1003 
1004   xa_interval_id = 0;
1005   xa_audio_present = XA_AUDIO_OK;
1006   Init_Audio_Ring ( xa_audio_ring_size,
1007                     ( XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps ) );
1008 }
1009 
1010 
1011 /*----------------------------------------------------------------------------*/
1012 /*                                                                            */
1013 /*----------------------------------------------------------------------------*/
AIX_Audio_Kill()1014 void AIX_Audio_Kill ( )
1015 {
1016   AIX_Audio_Off ( 0 );
1017   xa_audio_present = XA_AUDIO_UNK;
1018   close ( devAudio );
1019   Kill_Audio_Ring ( );
1020 }
1021 
1022 
1023 /*----------------------------------------------------------------------------*/
1024 /*                                                                            */
1025 /*----------------------------------------------------------------------------*/
AIX_Audio_Off()1026 void AIX_Audio_Off ( )
1027 {
1028   audio_control control;
1029   int           rc;
1030 
1031   if ( xa_audio_status != XA_AUDIO_STARTED )
1032   {
1033     return;
1034   }
1035 
1036   xa_audio_status = XA_AUDIO_STOPPED;
1037 
1038   memset ( & control, '\0', sizeof ( control ) );
1039 
1040   control.ioctl_request = AUDIO_STOP;
1041   control.request_info  = NULL;
1042   control.position      = 0;
1043 
1044   if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
1045   {
1046     fprintf ( stderr, "AIX_Audio_Off: AUDIO_STOP failed, errno = %d\n", errno );
1047   }
1048 
1049 #ifdef SOME_DAY
1050   if ( ( rc = ioctl ( devAudio, AUDIO_WAIT, NULL ) ) != 0 )
1051   {
1052     fprintf ( stderr, "AIX_Audio_Off: AUDIO_WAIT failed, errno = %d\n", errno );
1053   }
1054 #endif
1055 
1056   xa_time_audio = -1;
1057   xa_audio_flushed = 0;
1058 }
1059 
1060 
1061 /*----------------------------------------------------------------------------*/
1062 /*                                                                            */
1063 /*----------------------------------------------------------------------------*/
AIX_Audio_Prep()1064 void AIX_Audio_Prep( )
1065 {
1066   audio_control control;
1067   int           rc;
1068 
1069   if ( xa_audio_status == XA_AUDIO_STARTED ) return;
1070   if ( xa_audio_present != XA_AUDIO_OK ) return;
1071   if ( xa_snd_cur )
1072   {
1073     /* Change the frequency if needed */
1074     if ( xa_audio_hard_freq != xa_snd_cur->hfreq )
1075     {
1076       audio_init init;
1077 
1078       printf ( "AIX_Audio_Prep: setting frequency to %d\n", xa_snd_cur->hfreq );
1079 
1080       memset ( & init, '\0', sizeof ( init ) );
1081 
1082       init.srate           = xa_snd_cur->hfreq;
1083       init.mode            = PCM;
1084       init.operation       = PLAY;
1085       init.channels        = 1;
1086       init.flags           = BIG_ENDIAN | TWOS_COMPLEMENT;
1087       init.bits_per_sample = 16;
1088       init.bsize           = AUDIO_IGNORE;
1089 
1090       if ( ( rc = ioctl ( devAudio, AUDIO_INIT, & init ) ) < 0 )
1091       {
1092         fprintf ( stderr,
1093                   "AIX_Audio_Prep: AUDIO_INIT failed, rate = %d, errno = %d\n",
1094                   init.srate, errno );
1095       }
1096 
1097       xa_audio_hard_freq = xa_snd_cur->hfreq;
1098     }
1099 
1100     /* OLD xa_out_time = xa_snd_cur->ch_time * 4; */
1101     xa_out_time = 250;  /* keep audio fed 250ms ahead of video - may be 500*/
1102     xa_out_init = xa_audio_ring_size - 1;
1103     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
1104     if ( xa_interval_time == 0 ) xa_interval_time = 1;
1105 
1106     XA_Flush_Ring();
1107     XA_Update_Ring(1000);
1108 
1109     /* POD: The following 8 lines need to be before Merged_Audio_Output now */
1110     memset ( & control, '\0', sizeof ( control ) );
1111     control.ioctl_request = AUDIO_START;
1112     control.request_info  = NULL;
1113     control.position      = 0;
1114     if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
1115     {
1116       fprintf(stderr,"AIX_Audio_Prep: AUDIO_START failed, errno = %d\n", errno );
1117     }
1118     xa_audio_status = XA_AUDIO_PREPPED;
1119   }
1120 }
1121 
1122 
AIX_Audio_On()1123 void AIX_Audio_On()
1124 {
1125   if (   (xa_snd_cur)
1126       && (xa_audio_present == XA_AUDIO_OK)
1127       && (xa_audio_status == XA_AUDIO_PREPPED) )
1128   {
1129     xa_audio_status = XA_AUDIO_STARTED;
1130     xa_time_now = XA_Read_AV_Time();  /* get new time */
1131     New_Merged_Audio_Output();
1132   }
1133 }
1134 
1135 
1136 /*----------------------------------------------------------------------------*/
1137 /*                                                                            */
1138 /*----------------------------------------------------------------------------*/
AIX_Closest_Freq(ifreq)1139 xaULONG AIX_Closest_Freq ( ifreq )
1140 xaLONG ifreq;
1141 {
1142   static valid [ ] = {  8000,  9600, 11025, 16000, 18900,
1143                        22050, 32000, 37800, 44100, 48000, 0 };
1144   int  i = 0;
1145   xaLONG best = 8000;
1146 
1147   xa_audio_hard_buff = XA_HARD_BUFF_1K;
1148   while ( valid [ i ] )
1149   {
1150     if ( xaABS(valid[i] - ifreq) < xaABS(best - ifreq) )
1151     {
1152       best = valid [ i ];
1153     }
1154     i = i + 1;
1155   }
1156   return ( best );
1157 }
1158 
1159 
1160 /*----------------------------------------------------------------------------*/
1161 /*                                                                            */
1162 /*----------------------------------------------------------------------------*/
AIX_Output_Change(settings)1163 int AIX_Output_Change ( settings )
1164 xaULONG settings;
1165 {
1166   audio_control control;
1167   audio_change  change;
1168   int           rc;
1169 
1170   memset ( & control, '\0', sizeof ( control ) );
1171   memset ( & change, '\0', sizeof ( change ) );
1172 
1173   change.balance       = 0x3fff0000;
1174   change.balance_delay = 0;
1175 
1176   change.volume        = AUDIO_IGNORE;
1177   change.volume_delay  = AUDIO_IGNORE;
1178 
1179   change.input         = AUDIO_IGNORE;
1180   change.output        = settings;
1181   change.monitor       = AUDIO_IGNORE;
1182   change.dev_info      = ( char * ) NULL;
1183 
1184   control.ioctl_request = AUDIO_CHANGE;
1185   control.position      = 0;
1186   control.request_info  = ( char * ) & change;
1187 
1188   if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
1189   {
1190     fprintf ( stderr, "AIX_Output_Change: AUDIO_CONTROL failed, errno = %d\n",
1191               errno );
1192   }
1193   return ( rc );
1194 }
1195 
1196 
1197 /*----------------------------------------------------------------------------*/
1198 /*                                                                            */
1199 /*----------------------------------------------------------------------------*/
AIX_Speaker_Tog(flag)1200 void AIX_Speaker_Tog ( flag )
1201 xaULONG flag;
1202 {
1203   int  rc;
1204 
1205   switch ( flag )
1206   {
1207     case 0:
1208          aix_audio_ports &= ~INTERNAL_SPEAKER;
1209          break;
1210 
1211     case 1:
1212          aix_audio_ports |= INTERNAL_SPEAKER;
1213          break;
1214 
1215     default:
1216          aix_audio_ports ^= INTERNAL_SPEAKER;
1217          break;
1218   }
1219 
1220   if ( ( rc = AIX_Output_Change ( aix_audio_ports ) ) < 0 )
1221   {
1222     fprintf ( stderr,
1223 	"AIX_Speaker_Tog: AUDIO_CONTROL failed, errno = %d\n", errno );
1224   }
1225 }
1226 
1227 
1228 /*----------------------------------------------------------------------------*/
1229 /*                                                                            */
1230 /*----------------------------------------------------------------------------*/
AIX_Headphone_Tog(flag)1231 void AIX_Headphone_Tog ( flag )
1232 xaULONG flag;
1233 {
1234   int  rc;
1235 
1236   switch ( flag )
1237   {
1238     case 0:
1239          aix_audio_ports &= ~EXTERNAL_SPEAKER;
1240          break;
1241 
1242     case 1:
1243          aix_audio_ports |= EXTERNAL_SPEAKER;
1244          break;
1245 
1246     default:
1247          aix_audio_ports ^= EXTERNAL_SPEAKER;
1248          break;
1249   }
1250 
1251   if ( ( rc = AIX_Output_Change ( aix_audio_ports ) ) < 0 )
1252   {
1253     fprintf(stderr,
1254       "AIX_Headphone_Tog: AUDIO_CONTROL failed, errno = %d\n",errno);
1255   }
1256 }
1257 
1258 
1259 /*----------------------------------------------------------------------------*/
1260 /*                                                                            */
1261 /*----------------------------------------------------------------------------*/
AIX_LineOut_Tog(flag)1262 void AIX_LineOut_Tog ( flag )
1263 xaULONG flag;
1264 {
1265   int  rc;
1266 
1267   switch ( flag )
1268   {
1269     case 0:
1270          aix_audio_ports &= ~OUTPUT_1;
1271          break;
1272 
1273     case 1:
1274          aix_audio_ports |= OUTPUT_1;
1275          break;
1276 
1277     default:
1278          aix_audio_ports ^= OUTPUT_1;
1279          break;
1280   }
1281 
1282   if ( ( rc = AIX_Output_Change ( aix_audio_ports ) ) < 0 )
1283   {
1284     fprintf ( stderr, "AIX_LineOut_Tog: AUDIO_CONTROL failed, errno = %d\n",
1285               errno );
1286   }
1287 }
1288 
1289 /*----------------------------------------------------------------------------*/
1290 /*                                                                            */
1291 /*----------------------------------------------------------------------------*/
AIX_Adjust_Volume(volume)1292 void AIX_Adjust_Volume ( volume )
1293 xaULONG volume;
1294 {
1295   audio_control control;
1296   audio_change  change;
1297   float         percent;
1298   long          new_val;
1299   int           rc;
1300   float         base_vol = 0x7fff;
1301 
1302   memset ( & control, '\0', sizeof ( control ) );
1303   memset ( & change, '\0', sizeof ( change ) );
1304 
1305   if ( volume > XA_AUDIO_MAXVOL )
1306   {
1307     volume = XA_AUDIO_MAXVOL;
1308   }
1309 
1310   if ( volume < XA_AUDIO_MINVOL )
1311   {
1312     volume = XA_AUDIO_MINVOL;
1313   }
1314 
1315   percent = ( double ) volume / XA_AUDIO_MAXVOL;
1316   new_val = base_vol * percent;
1317   new_val = new_val << 16;
1318 
1319   change.balance       = AUDIO_IGNORE;
1320   change.balance_delay = AUDIO_IGNORE;
1321 
1322   change.volume        = new_val;
1323   change.volume_delay  = 0;
1324 
1325   change.input         = AUDIO_IGNORE;
1326   change.output        = AUDIO_IGNORE;
1327   change.monitor       = AUDIO_IGNORE;
1328   change.dev_info      = ( char * ) NULL;
1329 
1330   control.ioctl_request = AUDIO_CHANGE;
1331   control.position =      0;
1332   control.request_info =  ( char * ) & change;
1333 
1334   if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
1335   {
1336     fprintf ( stderr, "AIX_Audio_Init: AUDIO_CONTROL failed, errno = %d\n",
1337               errno );
1338   }
1339 
1340 }
1341 #endif
1342 
1343 /****************************************************************************/
1344 /**************** S/6000  SPECIFIC ROUTINES *********************************/
1345 /****************************************************************************/
1346 
1347 
1348 
1349 /****************************************************************************/
1350 /**************** NEC EWS SPECIFIC ROUTINES *********************************/
1351 /****************************************************************************/
1352 #ifdef XA_EWS_AUDIO
1353 
1354 /*
1355  * EWS port provided by Bob Phillips,
1356  *	bobp@syl.nj.nec.com
1357  * Heavily stolen from the Sparc port
1358  * Friday October 26, 1994
1359  */
1360 
1361 xaULONG ews_audio_ports = AUOUT_SP;
1362 
1363 void  EWS_Audio_Init();
1364 void  EWS_Audio_Kill();
1365 void  EWS_Audio_Off();
1366 void  EWS_Audio_Prep();
1367 void  EWS_Audio_On();
1368 void  EWS_Adjust_Volume();
1369 xaULONG EWS_Closest_Freq();
1370 void EWS_Speaker_Toggle();
1371 void EWS_Headphone_Toggle();
1372 
1373 /* EWS audio output volume is controlled with attenuation, not gain.
1374  * The upshot is that the control values run from 62 to 0, with low
1375  * numbers representing louder volumes.
1376  */
1377 
1378 static int devAudio;
1379 static struct AU_Volume audio_vol;
1380 static struct AU_Type audio_type;
1381 static struct AU_Line audio_line;
1382 static struct AU_Status audio_status;
1383 
1384 
1385 /********** XA_Audio_Setup **********************
1386  *
1387  * Also defines NEC Specific variables.
1388  *
1389  *****/
XA_Audio_Setup()1390 void XA_Audio_Setup()
1391 {
1392   XA_Audio_Init		= EWS_Audio_Init;
1393   XA_Audio_Kill		= EWS_Audio_Kill;
1394   XA_Audio_Off		= EWS_Audio_Off;
1395   XA_Audio_Prep		= EWS_Audio_Prep;
1396   XA_Audio_On		= EWS_Audio_On;
1397   XA_Closest_Freq	= EWS_Closest_Freq;
1398   XA_Set_Output_Port	= (void *)(0);
1399   XA_Speaker_Tog	= EWS_Speaker_Toggle;
1400   XA_Headphone_Tog	= EWS_Headphone_Toggle;
1401   XA_LineOut_Tog	= EWS_Headphone_Toggle;
1402   XA_Adjust_Volume	= EWS_Adjust_Volume;
1403 
1404 
1405   xa_snd_cur = 0;
1406   xa_audio_present = XA_AUDIO_UNK;
1407   xa_audio_status  = XA_AUDIO_STOPPED;
1408   xa_audio_ring_size  = 8;
1409 }
1410 
1411 
1412 /********** EWS_Audio_Init **********************
1413  * Open /dev/audio/audio on EWS.
1414  *
1415  *****/
EWS_Audio_Init()1416 void EWS_Audio_Init()
1417 { int ret;
1418   int type;
1419 
1420 
1421   DEBUG_LEVEL2 fprintf(stderr,"EWS_Audio_Init\n");
1422 /* The NEC EWS audio driver is very similar to the Sparc, but it does
1423  * not use an audio control device.  All ioctls are made directly to
1424  * the audio device.  Also, it does not support a wide variety of
1425  * ioctls.  In fact, it only supports
1426  * AUIOC_[SG]ETTYPE, AUIOC_[SG]ETLINE, AUIOC_[SG]ETVOLUME, and AUIOC_STATUS.
1427  * It doesn't support FLUSH, or any of the other funky Sparc ioctls
1428  */
1429   if (xa_audio_present != XA_AUDIO_UNK) return;
1430   devAudio = open("/dev/audio/audio", O_WRONLY | O_NDELAY);
1431   if (devAudio == -1)
1432   {
1433     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
1434     else fprintf(stderr,"Audio_Init: Error opening audio device. - ");
1435     fprintf(stderr,"Will continue without audio\n");
1436     xa_audio_present = XA_AUDIO_ERR;
1437     return;
1438   }
1439   DEBUG_LEVEL1 fprintf(stderr,"NEC EWS AUDIO\n");
1440     xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
1441     xa_audio_hard_freq  = AURATE11_0;
1442     xa_audio_hard_bps   = 2;
1443     xa_audio_hard_chans = 1;
1444     xa_audio_hard_buff  = XA_HARD_BUFF_1K;             /* default buffer size */
1445 
1446     audio_type.rate=AURATE11_0;
1447     audio_type.bit_type=AU_PCM16;
1448     audio_type.channel=AU_MONO;
1449     ret = ioctl(devAudio, AUIOC_SETTYPE, &audio_type);
1450     if (ret)
1451     {
1452       fprintf(stderr,"EWS: AUIOC_SETTYPE error %d\n",errno);
1453       xa_audio_present = XA_AUDIO_ERR;
1454       return;
1455     }
1456 
1457   xa_interval_id = 0;
1458   xa_audio_present = XA_AUDIO_OK;
1459   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
1460   Init_Audio_Ring(xa_audio_ring_size,
1461 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
1462 }
1463 
1464 /********** EWS_Audio_Kill **********************
1465  * Close /dev/audio/audio
1466  *
1467  *****/
EWS_Audio_Kill()1468 void EWS_Audio_Kill()
1469 {
1470   /* TURN AUDIO OFF */
1471   EWS_Audio_Off(0);
1472   xa_audio_present = XA_AUDIO_UNK;
1473   /* SHUT THINGS DOWN  */
1474   close(devAudio);
1475   Kill_Audio_Ring();
1476 }
1477 
1478 /********** EWS_Audio_Off **********************
1479  * Stop Audio Stream
1480  *
1481  *****/
EWS_Audio_Off(flag)1482 void EWS_Audio_Off(flag)
1483 xaULONG flag;
1484 { long ret;
1485 
1486   DEBUG_LEVEL1 fprintf(stderr,"EWS_Audio_Off\n");
1487   if (xa_audio_status != XA_AUDIO_STARTED) return;
1488 
1489   /* SET FLAG TO TELL FREE RUNNING OUTPUT ROUTINE */
1490   xa_audio_status = XA_AUDIO_STOPPED;
1491 
1492   /* The Sparc port flushes here.  We cannot. So, just nuke volume.
1493    */
1494   /* TURN OFF SOUND ??? */
1495   EWS_Adjust_Volume(XA_AUDIO_MINVOL);
1496 
1497 
1498   xa_time_audio = -1;
1499   xa_audio_flushed = 0;
1500 
1501 }
1502 
1503 /********** EWS_Audio_Prep **********************
1504  * Turn On Audio Stream.
1505  *
1506  *****/
EWS_Audio_Prep()1507 void EWS_Audio_Prep()
1508 {
1509   DEBUG_LEVEL2
1510     fprintf(stderr,"EWS_Audio_Prep \n");
1511   if (xa_audio_status == XA_AUDIO_STARTED) return;
1512   else if (xa_audio_present != XA_AUDIO_OK) return;
1513   else if (xa_snd_cur)
1514   { int ret;
1515 
1516     /* CHANGE FREQUENCY IF NEEDED */
1517     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
1518     {
1519 
1520       ret = ioctl(devAudio, AUIOC_GETTYPE, &audio_type);
1521       if (ret == -1) fprintf(stderr,"AUIOC_GETTYPE: errno %d\n",errno);
1522       audio_type.rate=EWS_Closest_Freq(xa_snd_cur->hfreq);
1523       ret = ioctl(devAudio, AUIOC_SETTYPE, &audio_type);
1524       if (ret == -1) fprintf(stderr,"AUIOC_SETTYPE: freq %x errno %d\n",
1525 						xa_snd_cur->hfreq, errno);
1526       xa_audio_hard_freq = xa_snd_cur->hfreq;
1527     }
1528     if (XAAUD->mute != xaTRUE) EWS_Adjust_Volume(XAAUD->volume);
1529 
1530     /* xa_snd_cur gets changes in Update_Ring() */
1531     xa_out_time = 250; /* keep audio fed 250ms ahead of video */
1532     xa_out_init = xa_audio_ring_size - 1;
1533     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
1534     if (xa_interval_time == 0) xa_interval_time = 1;
1535 
1536     XA_Flush_Ring();
1537     XA_Update_Ring(1000);
1538     xa_audio_status = XA_AUDIO_PREPPED;
1539   }
1540 }
1541 
1542 /****-------------------------------------------------------------------****
1543  *
1544  ****-------------------------------------------------------------------****/
EWS_Audio_On()1545 void EWS_Audio_On()
1546 {
1547   if (   (xa_snd_cur)
1548       && (xa_audio_present == XA_AUDIO_OK)
1549       && (xa_audio_status == XA_AUDIO_PREPPED) )
1550   {
1551     xa_audio_status = XA_AUDIO_STARTED;
1552     xa_time_now = XA_Read_AV_Time();  /* get new time */
1553     New_Merged_Audio_Output();
1554   }
1555 }
1556 
1557 
1558 
1559 /********** EWS_Closest_Freq **********************************************
1560  *
1561  * Global Variable Affect:
1562  *   xaULONG xa_audio_hard_buff		must set but not larger than
1563  *					XA_AUDIO_MAX_RING_BUF size
1564  ****************************************************************************/
EWS_Closest_Freq(ifreq)1565 xaULONG EWS_Closest_Freq(ifreq)
1566 xaLONG ifreq;
1567 {
1568   static int valid[] = { AURATE5_5, AURATE6_6, AURATE8_0,
1569 	AURATE9_6, AURATE11_0, AURATE16_0, AURATE18_9, AURATE22_1,
1570 	AURATE27_4, AURATE32_0, AURATE33_1, AURATE37_8, AURATE44_1,
1571 	AURATE48_0,0};
1572   xaLONG i = 0;
1573   xaLONG best = 8000;
1574 
1575   xa_audio_hard_buff = XA_HARD_BUFF_1K;
1576   while(valid[i])
1577   {
1578     if (xaABS(valid[i] - ifreq) < xaABS(best - ifreq)) best = valid[i];
1579     i++;
1580   }
1581   if (valid[i])
1582   {
1583     if (best >= 25000) xa_audio_hard_buff = XA_HARD_BUFF_2K;
1584     return(best);
1585   }
1586   else return(AURATE8_0);
1587 }
1588 
1589 /************* EWS_Speaker_Toggle *****************************************
1590  *
1591  * flag = 0  turn speaker off
1592  * flag = 1  turn speaker on
1593  * flag = 2  toggle speaker
1594  ****************************************************************************/
EWS_Speaker_Toggle(flag)1595 void EWS_Speaker_Toggle(flag)
1596 xaULONG flag;
1597 {
1598   xaULONG old_ports = ews_audio_ports;
1599   xaLONG ret;
1600 
1601   switch(flag)
1602   {
1603     case  0: ews_audio_ports &= ~AUOUT_SP; break;
1604     case  1: ews_audio_ports |=  AUOUT_SP; break;
1605     default: ews_audio_ports ^=  AUOUT_SP; break;
1606   }
1607   audio_line.outline = ews_audio_ports;
1608   ret = ioctl(devAudio, AUIOC_SETLINE, &audio_line);
1609   if (ret == -1)
1610   {
1611     fprintf(stderr,"Audio: couldn't toggle speaker %d\n",errno);
1612     ews_audio_ports = old_ports;
1613   }
1614 }
1615 
1616 /************* EWS_Headphone_Toggle *****************************************
1617  *
1618  * flag = 0  turn headphones off
1619  * flag = 1  turn headphones on
1620  * flag = 2  toggle headphones
1621  ****************************************************************************/
EWS_Headphone_Toggle(flag)1622 void EWS_Headphone_Toggle(flag)
1623 xaULONG flag;
1624 {
1625   xaULONG old_ports = ews_audio_ports;
1626   xaLONG ret;
1627   switch(flag)
1628   {
1629     case  0: ews_audio_ports &= ~AUOUT_PHONE; break;
1630     case  1: ews_audio_ports |=  AUOUT_PHONE; break;
1631     default: ews_audio_ports ^=  AUOUT_PHONE; break;
1632   }
1633   audio_line.outline = ews_audio_ports;
1634   ret = ioctl(devAudio, AUIOC_SETLINE, &audio_line);
1635   if (ret == -1)
1636   {
1637     fprintf(stderr,"Audio: couldn't toggle headphone %d\n",errno);
1638     ews_audio_ports = old_ports;
1639   }
1640 }
1641 
1642 
1643 /********** EWS_Adjust_Volume **********************
1644  * Routine for Adjusting Volume on EWS
1645  *
1646  * Volume is in the range [0,XA_AUDIO_MAXVOL]
1647  * EWS Output is a measure of attenuation, so it ranges from [62,0]
1648  ****************************************************************************/
EWS_Adjust_Volume(volume)1649 void EWS_Adjust_Volume(volume)
1650 xaULONG volume;
1651 {
1652   int vol;
1653   int ret;
1654 
1655   ret = ioctl(devAudio, AUIOC_GETVOLUME, &audio_vol);
1656   if (ret == -1)
1657   {
1658     fprintf(stderr,"Audio: couldn't get volume%d\n",errno);
1659     return;
1660   }
1661 
1662   vol= AUOUT_ATTEMAX-((volume*AUOUT_ATTEMAX)/XA_AUDIO_MAXVOL);
1663   audio_vol.out.left = audio_vol.out.right = vol;
1664   ret = ioctl(devAudio, AUIOC_SETVOLUME, &audio_vol);
1665   if (ret == -1)
1666   {
1667     fprintf(stderr,"Audio: couldn't set volume%d\n",errno);
1668   }
1669 
1670 }
1671 
1672 #endif
1673 /****************************************************************************/
1674 /******************* END OF NEC EWS SPECIFIC ROUTINES ***********************/
1675 /****************************************************************************/
1676 
1677 /****************************************************************************/
1678 /**************** SONY SPECIFIC ROUTINES ***********************************/
1679 /****************************************************************************/
1680 #ifdef	XA_SONY_AUDIO
1681 /*
1682  * SONY NEWS port provided by Kazushi Yoshida,
1683  *	30eem043@keyaki.cc.u-tokai.ac.jp
1684  * Heavily stolen from the Sparc port
1685  * Thu Jan 26, 1995
1686  *
1687  * SVR4/NEWS-OS 6.x port by Takashi Hagiwara, Sony Corporation
1688  * Add SB device check routine and some fixes
1689  *      hagiwara@sm.sony.co.jp
1690  */
1691 void Sony_Audio_Init();
1692 void Sony_Audio_Kill();
1693 void Sony_Audio_Off();
1694 void Sony_Audio_Prep();
1695 void Sony_Audio_On();
1696 void Sony_Adjust_Volume();
1697 xaULONG Sony_Closest_Freq();
1698 void Sony_Speaker_Toggle();
1699 void Sony_Headphone_Toggle();
1700 
1701 /*
1702  */
1703 static int sony_audio_rate1[] =  /* NWS-5000,4000 */
1704 	{ RATE8000, RATE9450, RATE11025, RATE12000, RATE16000,
1705 	  RATE18900, RATE22050, RATE24000, RATE32000, RATE37800,
1706 	  RATE44056, RATE44100, RATE48000, 0 } ;
1707 
1708 static int sony_audio_rate2[] =  /* NWS-3200, 3400, 3700, 3800 */
1709 	{ RATE8000, RATE9450, RATE18900, RATE37800, 0 } ;
1710 
1711 static int sony_audio_rate3[] =  /* NWS-3100 */
1712 	{ RATE8000, 0 } ;
1713 
1714 int sony_audio_buf_len ;
1715 static int devAudio;
1716 static struct sbparam	audio_info ;
1717 static int *sony_audio_rate;
1718 static int sony_max_vol, sony_min_vol;
1719 
1720 
1721 /********** XA_Audio_Setup **********************
1722 *
1723 * Also defines Sony Specific variables.
1724 *
1725 *****/
XA_Audio_Setup()1726 void XA_Audio_Setup()
1727 {
1728 	XA_Audio_Init		= Sony_Audio_Init;
1729 	XA_Audio_Kill		= Sony_Audio_Kill;
1730 	XA_Audio_Off		= Sony_Audio_Off;
1731 	XA_Audio_Prep		= Sony_Audio_Prep;
1732 	XA_Audio_On		= Sony_Audio_On;
1733 	XA_Closest_Freq		= Sony_Closest_Freq;
1734 	XA_Set_Output_Port	= (void *)(0);
1735 	XA_Speaker_Tog		= Sony_Speaker_Toggle;
1736 	XA_Headphone_Tog	= Sony_Headphone_Toggle;
1737 	XA_LineOut_Tog		= Sony_Headphone_Toggle;
1738 	XA_Adjust_Volume	= Sony_Adjust_Volume;
1739 
1740 
1741 	xa_snd_cur = 0;
1742 	xa_audio_present = XA_AUDIO_UNK;
1743 	xa_audio_status  = XA_AUDIO_STOPPED;
1744 	xa_audio_ring_size  = 8;
1745 }
1746 
1747 /********** Sony_Audio_Init **********************
1748 * Open /dev/sb.
1749 *
1750 *****/
Sony_Audio_Init()1751 void Sony_Audio_Init()
1752 {
1753 	int	ret;
1754 	int	type;
1755 	int 	sbtype;
1756 
1757 	DEBUG_LEVEL2 fprintf(stderr,"Sony_Audio_Init\n");
1758 
1759 	if (xa_audio_present != XA_AUDIO_UNK)
1760 		return;
1761 	devAudio = open("/dev/sb0", O_WRONLY | O_NDELAY);
1762 	if (devAudio == -1) {
1763 	  if (errno == EBUSY)
1764 		fprintf(stderr,"Audio_Init: Audio device is busy. - ");
1765 	  else
1766 		fprintf(stderr,"Audio_Init: Error opening audio device. - ");
1767 	  fprintf(stderr,"Will continue without audio\n");
1768 	  xa_audio_present = XA_AUDIO_ERR;
1769 	  return;
1770 	}
1771 
1772 	/* Under NEWS-OS 6.x SBIOCGETTYPE is supported by all machines. */
1773 	/* However, NEWS-OS 4.x SBIOCGETYPE is supported by only NEWS 5000 */
1774 	/* We should guess if SBUICGETTYPE would generate error,  */
1775 	/* that machine  would be NEWS-3xxxx */
1776 
1777 	if (ioctl(devAudio, SBIOCGETTYPE, (char *)&sbtype) < 0) {
1778 #ifdef SVR4
1779 		fprintf(stderr,"CANNOT GET SBTYPE ERROR %d\n",errno);
1780 #endif
1781 		sbtype = SBTYPE_AIF2;	/* I guess so */
1782 	}
1783 	switch(sbtype) {
1784 		case SBTYPE_AIF2:
1785 		case SBTYPE_AIF2_L:
1786 		case SBTYPE_AIF2_E:
1787 			sony_max_vol = 0;
1788 			sony_min_vol = -32;
1789 			sony_audio_rate = &sony_audio_rate2[0];
1790 			break;
1791 		case SBTYPE_AIF3:
1792 			sony_max_vol = 8;
1793 			sony_min_vol = -8;
1794 			sony_audio_rate = &sony_audio_rate3[0];
1795 			break;
1796 		case SBTYPE_AIF5:
1797 		case SBTYPE_AD1848:
1798 		default:
1799 			sony_max_vol = 16;
1800 			sony_min_vol = -16;
1801 			sony_audio_rate = &sony_audio_rate1[0];
1802 			break;
1803 	}
1804 
1805 	DEBUG_LEVEL1 fprintf(stderr,"SONY AMD AUDIO\n");
1806 
1807 	xa_audio_hard_type  = XA_AUDIO_SUN_AU;
1808 	xa_audio_hard_freq  = 8000;
1809 	xa_audio_hard_buff  = 1024;         /* default buffer size */
1810 	xa_audio_hard_bps   = 1;
1811 	xa_audio_hard_chans = 1;
1812 	Gen_Signed_2_uLaw() ;
1813 
1814 	audio_info.sb_mode    = LOGPCM ;
1815 	audio_info.sb_format  = 0 ;		/* was BSZ128 */
1816 	audio_info.sb_compress= MULAW ;
1817 	audio_info.sb_rate    = RATE8000 ;
1818 	audio_info.sb_channel = MONO ;
1819 	audio_info.sb_bitwidth= RES8B ;
1820 	audio_info.sb_emphasis= 0 ;		/* was EMPH_OFF */
1821 
1822 	ret = ioctl(devAudio, SBIOCSETPARAM, &audio_info);
1823 	if (ret) {
1824 		fprintf(stderr,"AUDIO BRI FATAL ERROR %d\n",errno);
1825 		TheEnd1("SONY AUDIO BRI FATAL ERROR\n");
1826 	}
1827 	ret = ioctl(devAudio, SBIOCGETPARAM, &audio_info);
1828 	if (ret == -1)
1829 		 fprintf(stderr,"Can't get audio_info %d\n",errno);
1830 	xa_interval_id = 0;
1831 	xa_audio_present = XA_AUDIO_OK;
1832 
1833 	DEBUG_LEVEL2 fprintf(stderr,"success \n");
1834 
1835 	Init_Audio_Ring(xa_audio_ring_size,
1836 		(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
1837 
1838 	sony_audio_buf_len = 32 * 1024 ; /* 4 sec... */
1839 }
1840 
1841 
1842 /********** Sony_Audio_Kill **********************
1843 * Close /dev/sb0.
1844 *
1845 *****/
Sony_Audio_Kill()1846 void Sony_Audio_Kill()
1847 {
1848   DEBUG_LEVEL1 fprintf(stderr,"Sony_Audio_Kill\n");
1849   /* TURN AUDIO OFF */
1850   Sony_Audio_Off(0);
1851   xa_audio_present = XA_AUDIO_UNK;
1852   /* SHUT THINGS DOWN  */
1853   close(devAudio);
1854   Kill_Audio_Ring();
1855 }
1856 
1857 /********** Sony_Audio_Off **********************
1858 * Stop Audio Stream
1859 *
1860 *****/
Sony_Audio_Off(flag)1861 void Sony_Audio_Off(flag)
1862 xaULONG flag;
1863 { long ret;
1864 
1865   DEBUG_LEVEL1 fprintf(stderr,"Sony_Audio_Off\n");
1866   if (xa_audio_status != XA_AUDIO_STARTED) return;
1867 
1868   /* SET FLAG TO TELL FREE RUNNING OUTPUT ROUTINE */
1869   xa_audio_status = XA_AUDIO_STOPPED;
1870 
1871   /* TURN OFF SOUND ??? */
1872   Sony_Adjust_Volume(XA_AUDIO_MINVOL);
1873 
1874   /* FLUSH AUDIO DEVICE */
1875   ret = ioctl(devAudio, SBIOCFLUSH, 0);
1876   if (ret == -1) fprintf(stderr,"Sony Audio: off flush err %d\n",errno);
1877 
1878   xa_time_audio = -1;
1879   xa_audio_flushed = 0;
1880 
1881   /* OK... Wait for Sound device */
1882   ret = ioctl(devAudio, SBIOCWAIT, 0);
1883 
1884   /* RESTORE ORIGINAL VOLUME */
1885   if (XAAUD->mute != xaTRUE) Sony_Adjust_Volume(XAAUD->volume);
1886 }
1887 
1888 /********** Sony_Audio_Prep **********************
1889 * Turn On Audio Stream.
1890 *
1891 *****/
Sony_Audio_Prep()1892 void Sony_Audio_Prep()
1893 { int ret ;
1894   struct sbparam a_info ;
1895 
1896   DEBUG_LEVEL1 fprintf(stderr,"SONY AUDIO ON\n");
1897 
1898   if (xa_audio_status == XA_AUDIO_STARTED) return;
1899   else if (xa_audio_present != XA_AUDIO_OK) return;
1900   else if (xa_snd_cur)
1901   {
1902     /* CHANGE FREQUENCY IF NEEDED */
1903     if( xa_audio_hard_freq != xa_snd_cur->hfreq )
1904     {
1905       a_info.sb_mode    = LOGPCM ;
1906       a_info.sb_format  = 0 ;
1907       a_info.sb_compress= MULAW ;
1908       a_info.sb_rate    = xa_snd_cur->hfreq ;
1909       a_info.sb_channel = MONO ;
1910       a_info.sb_bitwidth= RES8B ;
1911       a_info.sb_emphasis= 0 ;
1912       ret=ioctl(devAudio, SBIOCSETPARAM, &a_info);
1913       if( ret == -1 )fprintf(stderr,"audio set freq: freq %lf errno %d\n",
1914 					xa_snd_cur->hfreq, errno);
1915       xa_audio_hard_freq = xa_snd_cur->hfreq;
1916     }
1917 
1918     /* xa_snd_cur gets changes in Update_Ring() */
1919     xa_out_time = 250; /* keep audio fed 250ms ahead of video - could be 500*/
1920     xa_out_init = xa_audio_ring_size - 1;
1921     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
1922     if (xa_interval_time == 0) xa_interval_time = 1;
1923 
1924     XA_Flush_Ring();
1925     XA_Update_Ring(1000);
1926     xa_audio_status = XA_AUDIO_PREPPED;
1927   }
1928 }
1929 
1930 /****-------------------------------------------------------------------****
1931  *
1932  ****-------------------------------------------------------------------****/
Sony_Audio_On()1933 void Sony_Audio_On()
1934 {
1935   if (   (xa_snd_cur)
1936       && (xa_audio_present == XA_AUDIO_OK)
1937       && (xa_audio_status == XA_AUDIO_PREPPED) )
1938   {
1939     xa_audio_status = XA_AUDIO_STARTED;
1940     xa_time_now = XA_Read_AV_Time();  /* get new time */
1941     New_Merged_Audio_Output();
1942   }
1943 }
1944 
1945 /********** Sony_Closest_Freq **********************************************
1946 *
1947 ****************************************************************************/
Sony_Closest_Freq(ifreq)1948 xaULONG Sony_Closest_Freq(ifreq)
1949 xaLONG	ifreq;
1950 { xaLONG i = 0 ;
1951   xaLONG best = 8000 ;
1952 
1953   xa_audio_hard_buff = XA_HARD_BUFF_1K;
1954   while(sony_audio_rate[i])
1955   {
1956     if (xaABS(sony_audio_rate[i] - ifreq) < xaABS(best - ifreq))
1957 				best = sony_audio_rate[i];
1958     i++;
1959   }
1960   return(best);
1961 }
1962 /************* Sony_Speaker_Toggle *****************************************
1963 *
1964 * flag = 0  turn speaker off
1965 * flag = 1  turn speaker on
1966 * flag = 2  toggle speaker
1967 ****************************************************************************/
Sony_Speaker_Toggle(flag)1968 void Sony_Speaker_Toggle(flag)
1969 xaULONG flag;
1970 {
1971 	 /* do nothing */return ;
1972 }
1973 
1974 /************* Sony_Headphone_Toggle *****************************************
1975 *
1976 * flag = 0  turn headphones off
1977 * flag = 1  turn headphones on
1978 * flag = 2  toggle headphones
1979 ****************************************************************************/
Sony_Headphone_Toggle(flag)1980 void Sony_Headphone_Toggle(flag)
1981 xaULONG flag ;
1982 {
1983 	 /* do nothing */return ;
1984 }
1985 /********** Sony_Adjust_Volume **********************/
Sony_Adjust_Volume(volume)1986 void Sony_Adjust_Volume(volume)
1987 xaULONG volume;
1988 {
1989   struct sblevel 	gain;
1990   int			mflg;
1991   int			o_level;
1992   mflg = MUTE_OFF;
1993   ioctl(devAudio, SBIOCMUTE, &mflg);
1994   o_level = sony_min_vol +
1995                  ((volume * (sony_max_vol - sony_min_vol)) / XA_AUDIO_MAXVOL);
1996   if (o_level > sony_max_vol)	o_level = sony_max_vol;
1997   if (o_level < sony_min_vol)	o_level = sony_min_vol;
1998 
1999   if (o_level == sony_min_vol)
2000   {
2001     mflg = MUTE_ON;
2002     ioctl(devAudio, SBIOCMUTE, &mflg);
2003   }
2004   gain.sb_right = gain.sb_left = (o_level << 16);
2005   ioctl(devAudio, SBIOCSETOUTLVL, &gain);
2006 }
2007 #endif
2008 /****************************************************************************/
2009 /******************* END OF SONY SPECIFIC ROUTINES *********************/
2010 /****************************************************************************/
2011 
2012 
2013 /****************************************************************************/
2014 /**************** LINUX SPECIFIC ROUTINES *******************************/
2015 /****************************************************************************/
2016 #ifdef XA_LINUX_AUDIO
2017 
2018 
2019 void Linux_Audio_Init();
2020 void Linux_Audio_Kill();
2021 void Linux_Audio_Off();
2022 void Linux_Audio_Prep();
2023 void Linux_Audio_On();
2024 xaULONG Linux_Closest_Freq();
2025 void Linux_Speaker_Toggle();
2026 void Linux_Headphone_Toggle();
2027 void Linux_Adjust_Volume();
2028 xaULONG Linux_Read_Volume();
2029 
2030 int linux_vol_chan;
2031 
2032 #define LINUX_MAX_VOL (100)
2033 #define LINUX_MIN_VOL (0)
2034 
2035 int devAudio;
2036 int devMixer;
2037 
2038 /********** XA_Audio_Setup **********************
2039  * Sets up Linux specific Routines
2040  *****/
XA_Audio_Setup()2041 void XA_Audio_Setup()
2042 {
2043   XA_Audio_Init		= Linux_Audio_Init;
2044   XA_Audio_Kill		= Linux_Audio_Kill;
2045   XA_Audio_Off		= Linux_Audio_Off;
2046   XA_Audio_Prep		= Linux_Audio_Prep;
2047   XA_Audio_On		= Linux_Audio_On;
2048   XA_Closest_Freq	= Linux_Closest_Freq;
2049   XA_Set_Output_Port	= (void *)(0);
2050   XA_Speaker_Tog	= Linux_Speaker_Toggle;
2051   XA_Headphone_Tog	= Linux_Headphone_Toggle;
2052   XA_LineOut_Tog	= Linux_Headphone_Toggle;
2053   XA_Adjust_Volume	= Linux_Adjust_Volume;
2054 
2055   xa_snd_cur = 0;
2056   xa_audio_present = XA_AUDIO_UNK;
2057   xa_audio_status  = XA_AUDIO_STOPPED;
2058   xa_audio_ring_size  = 8;
2059   linux_vol_chan = SOUND_MIXER_VOLUME;  /* default */
2060 }
2061 
2062 /********** Linux_Audio_Init **********************
2063  * Init Linux Audio, init variables, open Audio Devices.
2064  *****/
Linux_Audio_Init()2065 void Linux_Audio_Init()
2066 { int ret,tmp;
2067   DEBUG_LEVEL2 fprintf(stderr,"Linux_Audio_Init\n");
2068 
2069   if (xa_audio_present != XA_AUDIO_UNK) return;
2070 
2071   devAudio = open(_FILE_DSP, O_WRONLY | O_NDELAY, 0);
2072   if (devAudio == -1)
2073   { fprintf(stderr,"Can't Open %s device\n",_FILE_DSP);
2074     xa_audio_present = XA_AUDIO_ERR;
2075     return;
2076   }
2077 
2078 #ifdef SNDCTL_DSP_SETFRAGMENT
2079   tmp = 0x0008000b; /* 8 2048 byte buffers */
2080 #ifdef XA_LINUX_OLDER_SND
2081   ret = ioctl(devAudio, SNDCTL_DSP_SETFRAGMENT, tmp);
2082 #else
2083   ret = ioctl(devAudio, SNDCTL_DSP_SETFRAGMENT, &tmp);
2084 #endif
2085 #else
2086   ret = 0;
2087 #endif
2088   if (ret == -1) fprintf(stderr,"Linux Audio: Error setting fragment size\n");
2089 
2090   ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
2091   /* SETUP SAMPLE SIZE */
2092   if (xa_kludge900_aud == 900) tmp = 8;  /* POD testing purposes */
2093   else tmp = 16;
2094 #ifdef SNDCTL_DSP_SAMPLESIZE
2095 #ifdef XA_LINUX_OLDER_SND
2096   ret = ioctl(devAudio, SNDCTL_DSP_SAMPLESIZE, tmp);
2097 #else
2098   ret = ioctl(devAudio, SNDCTL_DSP_SAMPLESIZE, &tmp);
2099 #endif
2100 #else
2101   ret = -1;
2102 #endif
2103   if ((ret == -1) || (tmp == 8)) xa_audio_hard_bps = 1;
2104   else xa_audio_hard_bps = 2;
2105 
2106 /* TESTING
2107 fprintf(stderr,"audio hard bps %d\n",xa_audio_hard_bps);
2108 */
2109 
2110   /* SETUP Mono/Stereo */
2111   tmp = 0;  /* mono(0) stereo(1) */
2112 #ifdef XA_LINUX_OLDER_SND
2113   ret = ioctl(devAudio, SNDCTL_DSP_STEREO, tmp);
2114 #else
2115   ret = ioctl(devAudio, SNDCTL_DSP_STEREO, &tmp);
2116 #endif
2117   if (ret == -1) fprintf(stderr,"Linux Audio: Error setting mono\n");
2118   xa_audio_hard_chans = 1;
2119 
2120   xa_audio_hard_freq  = 11025;  /* 22050 and sometimes 44100 */
2121   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
2122 
2123 #ifdef SNDCTL_DSP_GETBLKSIZE
2124 #ifdef XA_LINUX_OLDER_SND
2125   ret = ioctl(devAudio, SNDCTL_DSP_GETBLKSIZE, 0);
2126 #else
2127   ret = ioctl(devAudio, SNDCTL_DSP_GETBLKSIZE, &tmp);
2128 #endif
2129 #else
2130   ret = 0;
2131 #endif
2132   if (ret == -1) fprintf(stderr,"Linux Audio: Error getting buf size\n");
2133   /* POD NOTE: should probably do something with this value. :^) */
2134   /* Maybe XA_AUDIO_MAX_RING_BUFF should be a variable */
2135 
2136   ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
2137 
2138   devMixer = open(_FILE_MIXER,  O_RDONLY | O_NDELAY, 0);
2139   /* Mixer only present on SB Pro's and above */
2140   /* if not present then it's set to -1 and ignored later */
2141   /* THOUGHT: what about doing mixer ioctl to the /dev/dsp device??? */
2142   if (devMixer < 0) devMixer = devAudio;
2143    /* determine what volume settings exist */
2144   { int devices;
2145 #ifdef XA_LINUX_OLDER_SND
2146     devices = ioctl(devMixer, SOUND_MIXER_READ_DEVMASK, 0 );
2147     if (devices == -1) devices = 0;
2148 #else
2149     ret = ioctl(devMixer, SOUND_MIXER_READ_DEVMASK, &devices);
2150     if (ret == -1) devices = 0;
2151 #endif
2152     if (devices & (1 << SOUND_MIXER_PCM))
2153 		linux_vol_chan = SOUND_MIXER_PCM;
2154     else	linux_vol_chan = SOUND_MIXER_VOLUME;
2155   }
2156 
2157 /*
2158   XAAUD->volume = Linux_Read_Volume();
2159 */
2160 
2161   if (xa_audio_hard_bps == 1) xa_audio_hard_type  = XA_AUDIO_LINEAR_1M;
2162   else		xa_audio_hard_type  = XA_AUDIO_SIGNED_2ML;
2163 
2164   xa_interval_id = 0;
2165   xa_audio_present = XA_AUDIO_OK;
2166   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
2167   Init_Audio_Ring(xa_audio_ring_size,
2168 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
2169 }
2170 
2171 /********** Linux_Audio_Kill *************************************************
2172  * Stop Linux Audio and Close Linux Audio Devices. Free up memory.
2173  *
2174  *****************************************************************************/
Linux_Audio_Kill()2175 void Linux_Audio_Kill()
2176 {
2177   Linux_Audio_Off(0);
2178   xa_audio_present = XA_AUDIO_UNK;
2179   if ( (devMixer != -1) && (devMixer != devAudio)) close(devMixer);
2180   close(devAudio);
2181   Kill_Audio_Ring();
2182 }
2183 
2184 /********** Linux_Audio_Off *************************************************
2185  * Stop Linux Audio
2186  *
2187  *****************************************************************************/
Linux_Audio_Off(flag)2188 void Linux_Audio_Off(flag)
2189 xaULONG flag;
2190 {
2191   if (xa_audio_status != XA_AUDIO_STARTED) return;
2192   /* SET FLAG TO STOP OUTPUT ROUTINE */
2193   xa_audio_status = XA_AUDIO_STOPPED;
2194 
2195   ioctl(devAudio, SNDCTL_DSP_RESET, NULL);
2196 
2197   /* Linux_Adjust_Volume(XA_AUDIO_MINVOL); */
2198   /* ioctl(devAudio, SNDCTL_DSP_SYNC, NULL); */
2199   xa_time_audio = -1;
2200   xa_audio_flushed = 0;
2201   ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
2202   /* if (XAAUD->mute != xaTRUE) Linux_Adjust_Volume(XAAUD->volume); */
2203 
2204 }
2205 
2206 /********** Linux_Audio_Prep ***************************************************
2207  * Startup Linux Audio
2208  *
2209  *****************************************************************************/
Linux_Audio_Prep()2210 void Linux_Audio_Prep()
2211 {
2212   DEBUG_LEVEL2 fprintf(stderr,"Linux_Audio_Prep \n");
2213   if (xa_audio_status == XA_AUDIO_STARTED) return;
2214   else if (xa_audio_present != XA_AUDIO_OK) return;
2215   else if (xa_snd_cur)
2216   { int ret,tmp;
2217 
2218 
2219     Linux_Adjust_Volume(XA_AUDIO_MINVOL);
2220     ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
2221 
2222     /* CHANGE FREQUENCY */
2223     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
2224     {
2225       tmp = xa_snd_cur->hfreq;
2226 #ifdef XA_LINUX_OLDER_SND
2227       tmp = ioctl(devAudio, SNDCTL_DSP_SPEED, tmp);
2228 #else
2229       ret = ioctl(devAudio, SNDCTL_DSP_SPEED, &tmp);
2230 #endif
2231       if ((ret == -1) || (tmp != xa_snd_cur->hfreq))
2232 	fprintf(stderr,"Linux_Audio: err setting freq %x\n"
2233 						,xa_snd_cur->hfreq);
2234       xa_audio_hard_freq = xa_snd_cur->hfreq;
2235     }
2236     ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
2237     if (XAAUD->mute != xaTRUE) Linux_Adjust_Volume(XAAUD->volume);
2238 
2239     /* xa_snd_cur gets changes in Update_Ring() */
2240     xa_out_time = 250;  /* keep audio 250 ms ahead of video. could be 500ms */
2241     xa_out_init = xa_audio_ring_size - 1;
2242     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
2243     if (xa_interval_time == 0) xa_interval_time = 1;
2244 
2245     XA_Flush_Ring();
2246     XA_Update_Ring(1000);
2247     xa_audio_status = XA_AUDIO_PREPPED;
2248   }
2249 }
2250 
2251 /****-------------------------------------------------------------------****
2252  *
2253  ****-------------------------------------------------------------------****/
Linux_Audio_On()2254 void Linux_Audio_On()
2255 {
2256   DEBUG_LEVEL2 fprintf(stderr,"Linux_Audio_On\n");
2257   if (   (xa_snd_cur)
2258       && (xa_audio_present == XA_AUDIO_OK)
2259       && (xa_audio_status == XA_AUDIO_PREPPED) )
2260   {
2261     xa_audio_status = XA_AUDIO_STARTED;
2262     xa_time_now = XA_Read_AV_Time();  /* get new time */
2263     New_Merged_Audio_Output();
2264   }
2265 }
2266 
2267 /********** Linux_Closest_Freq **********************************************
2268  * Return closest support frequeny and set hard_buff.
2269  *
2270  *****************************************************************************/
Linux_Closest_Freq(ifreq)2271 xaULONG Linux_Closest_Freq(ifreq)
2272 xaLONG ifreq;	/* incoming frequency */
2273 { static int valid[] = {11025, 22050, 44100, 0};
2274   xaLONG i = 0;
2275   xaLONG tmp_freq,ofreq = ifreq;
2276 #ifndef XA_LINUX_OLDER_SND
2277   xaLONG ret;
2278 #endif
2279 
2280    /* search up for closest frequency */
2281   while(valid[i])
2282   {
2283     if (xaABS(valid[i] - ifreq) < xaABS(ofreq - ifreq)) ofreq = valid[i];
2284     i++;
2285   }
2286 
2287   tmp_freq = ofreq;
2288 #ifdef XA_LINUX_OLDER_SND
2289   tmp_freq = ioctl(devAudio, SNDCTL_DSP_SPEED, tmp_freq);
2290   if (tmp_freq == -1) tmp_freq = 0;
2291 #else
2292   ret = ioctl(devAudio, SNDCTL_DSP_SPEED, &tmp_freq);
2293   if (ret == -1) tmp_freq = 0;
2294 #endif
2295   if (tmp_freq) ofreq = tmp_freq;
2296 
2297   if (ofreq >= 25000) xa_audio_hard_buff = XA_HARD_BUFF_2K;
2298   else xa_audio_hard_buff = XA_HARD_BUFF_1K;
2299   return(ofreq);
2300 }
2301 
2302 /********** Linux_Speaker_Toggle **********************************************
2303  * Turn off/on/toggle Linux's Speaker(if possible)
2304  * flag= 0   1   2
2305  *****************************************************************************/
Linux_Speaker_Toggle(flag)2306 void Linux_Speaker_Toggle(flag)
2307 xaULONG flag;
2308 {
2309   return;
2310 }
2311 
2312 /********** Linux_Headphone_Toggle ********************************************
2313  * Turn off/on/toggle Linux's Headphone(if possible)
2314  * flag= 0   1   2
2315  *****************************************************************************/
Linux_Headphone_Toggle(flag)2316 void Linux_Headphone_Toggle(flag)
2317 xaULONG flag;
2318 {
2319   return;
2320 }
2321 
2322 /********** Linux_Adjust_Volume ***********************************************
2323  * Routine for Adjusting Volume on Linux
2324  *
2325  *****************************************************************************/
Linux_Adjust_Volume(volume)2326 void Linux_Adjust_Volume(volume)
2327 xaULONG volume;
2328 { xaULONG adj_volume;
2329 
2330   if (devMixer < 0) return;
2331   adj_volume = LINUX_MIN_VOL +
2332         ((volume * (LINUX_MAX_VOL - LINUX_MIN_VOL)) / XA_AUDIO_MAXVOL);
2333   if (adj_volume > LINUX_MAX_VOL) adj_volume = LINUX_MAX_VOL;
2334   adj_volume |= adj_volume << 8;	/* left channel | right channel */
2335 #ifdef XA_LINUX_OLDER_SND
2336   ioctl(devMixer, MIXER_WRITE(linux_vol_chan), adj_volume);
2337 #else
2338   ioctl(devMixer, MIXER_WRITE(linux_vol_chan), &adj_volume);
2339 #endif
2340 }
2341 
2342 /********** Linux_Adjust_Volume ***********************************************
2343  * Routine for Adjusting Volume on Linux
2344  *
2345  *****************************************************************************/
Linux_Read_Volume()2346 xaULONG Linux_Read_Volume()
2347 { xaLONG ret,the_volume = 0;
2348   if (devMixer < 0) return(0);
2349 
2350 #ifdef XA_LINUX_OLDER_SND
2351   the_volume = ioctl(devMixer, MIXER_READ(linux_vol_chan), 0);
2352   if (the_volume < 0) the_volume = 0;
2353 #else
2354   ret = ioctl(devMixer, MIXER_READ(linux_vol_chan), &the_volume);
2355   if (ret < 0) the_volume = 0;
2356 #endif
2357 
2358   the_volume =  (XA_AUDIO_MAXVOL * (the_volume - LINUX_MIN_VOL))
2359 						/ (LINUX_MAX_VOL);
2360 
2361   fprintf(stderr,"volume = %d %d %d",the_volume,LINUX_MIN_VOL,LINUX_MAX_VOL);
2362   return(the_volume);
2363 }
2364 #endif
2365 /****************************************************************************/
2366 /******************* END OF LINUX SPECIFIC ROUTINES *********************/
2367 /****************************************************************************/
2368 
2369 
2370 /****************************************************************************/
2371 /**************** SGI SPECIFIC ROUTINES *******************************/
2372 /****************************************************************************/
2373 #ifdef XA_SGI_AUDIO
2374 
2375 void SGI_Audio_Init();
2376 void SGI_Audio_Kill();
2377 void SGI_Audio_Off();
2378 void SGI_Audio_Prep();
2379 void SGI_Audio_On();
2380 xaULONG SGI_Closest_Freq();
2381 void SGI_Speaker_Toggle();
2382 void SGI_Headphone_Toggle();
2383 void SGI_Adjust_Volume();
2384 
2385 #define SGI_MAX_VOL (255)
2386 #define SGI_MIN_VOL (0)
2387 
2388 static ALport port;
2389 static ALconfig conf;
2390 
2391 /********** XA_Audio_Setup **********************
2392  * Sets up SGI specific Routines
2393  *****/
XA_Audio_Setup()2394 void XA_Audio_Setup()
2395 {
2396   XA_Audio_Init		= SGI_Audio_Init;
2397   XA_Audio_Kill		= SGI_Audio_Kill;
2398   XA_Audio_Off		= SGI_Audio_Off;
2399   XA_Audio_Prep		= SGI_Audio_Prep;
2400   XA_Audio_On		= SGI_Audio_On;
2401   XA_Closest_Freq	= SGI_Closest_Freq;
2402   XA_Set_Output_Port	= (void *)(0);
2403   XA_Speaker_Tog	= SGI_Speaker_Toggle;
2404   XA_Headphone_Tog	= SGI_Headphone_Toggle;
2405   XA_LineOut_Tog	= SGI_Headphone_Toggle;
2406   XA_Adjust_Volume	= SGI_Adjust_Volume;
2407 
2408   xa_snd_cur = 0;
2409   xa_audio_present = XA_AUDIO_UNK;
2410   xa_audio_status  = XA_AUDIO_STOPPED;
2411   xa_audio_ring_size  = 8;
2412 }
2413 
2414 /********** SGI_Audio_Init **********************
2415  * Init SGI Audio, init variables, open Audio Devices.
2416  *****/
SGI_Audio_Init()2417 void SGI_Audio_Init()
2418 { long sgi_params[4];
2419   DEBUG_LEVEL2 fprintf(stderr,"SGI_Audio_Init\n");
2420 
2421   if (xa_audio_present != XA_AUDIO_UNK) return;
2422 
2423   conf = ALnewconfig();
2424   ALsetwidth(conf, AL_SAMPLE_16);
2425   ALsetchannels(conf, AL_MONO);
2426   ALsetqueuesize(conf, 16384);
2427   port = ALopenport("XAnim Mono", "w", conf);
2428   if (port == 0)
2429   { fprintf(stderr,"Can't Open SGI Audio device\n");
2430     xa_audio_present = XA_AUDIO_ERR;
2431     return;
2432   }
2433 
2434   /* get default frequency - no really necessary */
2435   sgi_params[0] = AL_OUTPUT_RATE;
2436   sgi_params[1] = 11025;
2437   ALsetparams(AL_DEFAULT_DEVICE, sgi_params, 2);
2438   ALgetparams(AL_DEFAULT_DEVICE, sgi_params, 2);
2439   xa_audio_hard_freq = sgi_params[1];
2440 
2441   xa_audio_hard_bps = 2;
2442   xa_audio_hard_chans = 1;
2443   xa_audio_hard_buff  = XA_HARD_BUFF_2K;   /* was XA_HARD_BUFF_1K */
2444   xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
2445 
2446   xa_interval_id = 0;
2447   xa_audio_present = XA_AUDIO_OK;
2448   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
2449   Init_Audio_Ring(xa_audio_ring_size,
2450 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
2451 }
2452 /********** SGI_Audio_Kill **********************
2453  * Stop SGI Audio and Close SGI Audio Devices. Free up memory.
2454  *****/
SGI_Audio_Kill()2455 void SGI_Audio_Kill()
2456 {
2457   /* TURN AUDIO OFF */
2458   SGI_Audio_Off(0);
2459   xa_audio_present = XA_AUDIO_UNK;
2460   /* SHUT THINGS DOWN  */
2461   ALcloseport(port);
2462   ALfreeconfig(conf);
2463   Kill_Audio_Ring();
2464   return;
2465 }
2466 
2467 /********** SGI_Audio_Off **********************
2468  * Stop SGI Audio
2469  *****/
SGI_Audio_Off(flag)2470 void SGI_Audio_Off(flag)
2471 xaULONG flag;
2472 {
2473   DEBUG_LEVEL2 fprintf(stderr,"SGI_Audio_Off\n");
2474   if (xa_audio_status != XA_AUDIO_STARTED) return;
2475 
2476   /* SET FLAG TO STOP OUTPUT ROUTINE */
2477   xa_audio_status = XA_AUDIO_STOPPED;
2478 
2479   /* TURN OFF SOUND ??? */
2480   SGI_Adjust_Volume(XA_AUDIO_MINVOL);
2481 
2482   /* FLUSH DEVICE SHOULD GO HERE */
2483   /* POD NOTE: DOES SGI HAVE A FLUSH???? */
2484 
2485   /* Wait until all samples drained */
2486   while(ALgetfilled(port) != 0) sginap(1);
2487 
2488   xa_time_audio = -1;
2489   xa_audio_flushed = 0;
2490 
2491   /* RESTORE ORIGINAL VOLUME */
2492   if (XAAUD->mute != xaTRUE) SGI_Adjust_Volume(XAAUD->volume);
2493 }
2494 
2495 /********** SGI_Audio_Prep **********************
2496  * Startup SGI Audio
2497  *****/
SGI_Audio_Prep()2498 void SGI_Audio_Prep()
2499 {
2500   DEBUG_LEVEL2 fprintf(stderr,"SGI_Audio_Prep \n");
2501   if (xa_audio_status == XA_AUDIO_STARTED) return;
2502   else if (xa_audio_present != XA_AUDIO_OK) return;
2503   else if (xa_snd_cur)
2504   {
2505     /* Change Frequency If necessary */
2506     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
2507     { long sgi_params[2];
2508       sgi_params[0] = AL_OUTPUT_RATE;
2509       sgi_params[1] = xa_snd_cur->hfreq;
2510       ALsetparams(AL_DEFAULT_DEVICE, sgi_params, 2);
2511       xa_audio_hard_freq = xa_snd_cur->hfreq;
2512     }
2513 
2514     /* xa_snd_cur gets changes in Update_Ring() */
2515     xa_out_time = 500;  /* keep audio fed 500ms ahead of video */
2516     xa_out_init = xa_audio_ring_size - 1;
2517     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
2518     if (xa_interval_time == 0) xa_interval_time = 1;
2519 
2520     XA_Flush_Ring();
2521     XA_Update_Ring(1000);
2522     xa_audio_status = XA_AUDIO_PREPPED;
2523   }
2524 }
2525 
2526 /****-------------------------------------------------------------------****
2527  *
2528  ****-------------------------------------------------------------------****/
SGI_Audio_On()2529 void SGI_Audio_On()
2530 {
2531   if (   (xa_snd_cur)
2532       && (xa_audio_present == XA_AUDIO_OK)
2533       && (xa_audio_status == XA_AUDIO_PREPPED) )
2534   {
2535     xa_audio_status = XA_AUDIO_STARTED;
2536     xa_time_now = XA_Read_AV_Time();  /* get new time */
2537     New_Merged_Audio_Output();
2538   }
2539 }
2540 
2541 /********** SGI_Closest_Freq **********************
2542  * Return closest support frequeny and set hard_buff.
2543  * The IRIX 4.0.5 audio.h file lists the following frequencies:
2544  * {8000,11025,16000,22050,32000,44100,48000}
2545  *****/
SGI_Closest_Freq(ifreq)2546 xaULONG SGI_Closest_Freq(ifreq)
2547 xaLONG ifreq;
2548 { static int valid[] = { 8000,11025,16000,22050,32000,44100,0};
2549   xaLONG i = 0;
2550   xaLONG ofreq = 8000;
2551   long sgi_params[2];
2552 
2553   while(valid[i])
2554   {
2555     if (xaABS(valid[i] - ifreq) < xaABS(ofreq - ifreq)) ofreq = valid[i];
2556     i++;
2557   }
2558   sgi_params[0] = AL_OUTPUT_RATE;
2559   sgi_params[1] = ofreq;
2560   ALsetparams(AL_DEFAULT_DEVICE, sgi_params, 2);
2561   ALgetparams(AL_DEFAULT_DEVICE, sgi_params, 2);
2562   if (ofreq != sgi_params[1])
2563 	fprintf(stderr,"SGI AUDIO: freq gotten %d wasn't wanted %d\n",
2564 		sgi_params[1],ofreq);
2565   ofreq = sgi_params[1];
2566   xa_audio_hard_buff = XA_HARD_BUFF_2K; /* fixed for SGI */
2567   return(ofreq);
2568 }
2569 
2570 
2571 /********** SGI_Speaker_Toggle **********************
2572  * Turn off/on/toggle SGI's Speaker(if possible)
2573  * flag= 0   1   2
2574  *****/
SGI_Speaker_Toggle(flag)2575 void SGI_Speaker_Toggle(flag)
2576 xaULONG flag;
2577 {
2578   return;
2579 }
2580 
2581 /********** SGI_Headphone_Toggle **********************
2582  * Turn off/on/toggle SGI's Headphone(if possible)
2583  * flag= 0   1   2
2584  *****/
SGI_Headphone_Toggle(flag)2585 void SGI_Headphone_Toggle(flag)
2586 xaULONG flag;
2587 {
2588   return;
2589 }
2590 
2591 /********** SGI_Adjust_Volume **********************
2592  * Routine for Adjusting Volume on SGI
2593  *
2594  *****/
SGI_Adjust_Volume(volume)2595 void SGI_Adjust_Volume(volume)
2596 xaULONG volume;
2597 { xaULONG adj_volume;
2598   long sgi_params[4];
2599   adj_volume =
2600       (int)(pow(10.0, (float)volume / XA_AUDIO_MAXVOL * 2.406540183) + 0.5);
2601   if (adj_volume > SGI_MAX_VOL) adj_volume = SGI_MAX_VOL;
2602   sgi_params[0] = AL_LEFT_SPEAKER_GAIN;
2603   sgi_params[1] = adj_volume;
2604   sgi_params[2] = AL_RIGHT_SPEAKER_GAIN;
2605   sgi_params[3] = adj_volume;
2606   ALsetparams(AL_DEFAULT_DEVICE, sgi_params, 4);
2607 }
2608 
2609 #endif
2610 /****************************************************************************/
2611 /******************* END OF SGI SPECIFIC ROUTINES *********************/
2612 /****************************************************************************/
2613 
2614 /****************************************************************************/
2615 /**************** HP SPECIFIC ROUTINES *******************************/
2616 /****************************************************************************/
2617 #ifdef XA_HP_AUDIO
2618 
2619 void HP_Audio_Init();
2620 void HP_Audio_Kill();
2621 void HP_Audio_Off();
2622 void HP_Audio_Prep();
2623 void HP_Audio_On();
2624 xaULONG HP_Closest_Freq();
2625 void HP_Speaker_Toggle();
2626 void HP_Headphone_Toggle();
2627 void HP_Adjust_Volume();
2628 void HP_Print_Error();
2629 void HP_Print_ErrEvent();
2630 long HP_Audio_Err_Handler();
2631 void TheEnd();
2632 int  streamSocket; /*POD NOTE: rename */
2633 
2634 
2635 #define HP_MAX_VOL (audio_connection->max_output_gain)
2636 #define HP_MIN_VOL (audio_connection->min_output_gain)
2637 
2638 Audio        *audio_connection = 0;
2639 
2640 /* structures */
2641 AudioAttributes	play_attribs;
2642 SSPlayParams	streamParams;
2643 SStream 	audio_stream;
2644 /* longs */
2645 ATransID	hp_trans_id;
2646 AudioAttrMask	hp_attr_mask;
2647 AErrorHandler	hp_prev_handler;
2648 AGainEntry	gainEntry[4];
2649 long		hp_status;
2650 
2651 long *hp_sample_rates = 0;
2652 int hp_audio_paused = xaFALSE;
2653 
HP_Audio_Err_Handler(audio,err_event)2654 long HP_Audio_Err_Handler(audio,err_event)
2655 Audio *audio;
2656 AErrorEvent *err_event;
2657 {
2658   fprintf(stderr,"HP_Audio_Err_Handler:\n");
2659   xa_audio_present = XA_AUDIO_ERR;
2660   xa_audio_status  = XA_AUDIO_STOPPED;
2661   HP_Print_ErrEvent("HP_Audio_Err_Handler: ","\n",err_event->error_code);
2662   /* PODNOTE: temporary: eventually we'll try a gracefull recovery
2663    * and shift back to visual only
2664    */
2665   TheEnd();
2666 }
2667 
2668 /********** XA_Audio_Setup **********************
2669  * Sets up HP specific Routines
2670  *****/
XA_Audio_Setup()2671 void XA_Audio_Setup()
2672 {
2673   XA_Audio_Init		= HP_Audio_Init;
2674   XA_Audio_Kill		= HP_Audio_Kill;
2675   XA_Audio_Off		= HP_Audio_Off;
2676   XA_Audio_Prep		= HP_Audio_Prep;
2677   XA_Audio_On		= HP_Audio_On;
2678   XA_Closest_Freq	= HP_Closest_Freq;
2679   XA_Set_Output_Port	= (void *)(0);
2680   XA_Speaker_Tog	= HP_Speaker_Toggle;
2681   XA_Headphone_Tog	= HP_Headphone_Toggle;
2682   XA_LineOut_Tog	= HP_Headphone_Toggle;
2683 
2684   xa_snd_cur = 0;
2685   xa_audio_present = XA_AUDIO_UNK;
2686   xa_audio_status  = XA_AUDIO_STOPPED;
2687   xa_audio_ring_size  = 8;
2688   hp_audio_paused = xaFALSE;
2689 }
2690 
2691 /********** HP_Print_Error **********************
2692  * print error message
2693  *****/
HP_Print_Error(pre_str,post_str,status)2694 void HP_Print_Error(pre_str,post_str,status)
2695 char *pre_str,*post_str;
2696 AError status;
2697 { char err_buff[132];
2698   if (pre_str) fprintf(stderr,"%s (%d)",pre_str,(int)(status));
2699   AGetErrorText(audio_connection,status,err_buff,131);
2700   fprintf(stderr,"%s",err_buff);
2701   if (post_str) fprintf(stderr,"%s",post_str);
2702 }
2703 
2704 /********** HP_Print_ErrEvent **********************
2705  * print error message
2706  *****/
HP_Print_ErrEvent(pre_str,post_str,errorCode)2707 void HP_Print_ErrEvent(pre_str,post_str,errorCode)
2708 char *pre_str,*post_str;
2709 int  errorCode;
2710 { char err_buff[132];
2711   if (pre_str) fprintf(stderr,"%s (%d)",pre_str,(int)(errorCode));
2712   AGetErrorText(audio_connection,errorCode,err_buff,131);
2713   fprintf(stderr,"%s",err_buff);
2714   if (post_str) fprintf(stderr,"%s",post_str);
2715 }
2716 
2717 
2718 /********** HP_Audio_Init ***************************************************
2719  * Init HP Audio, init variables, open Audio Devices.
2720  *****/
HP_Audio_Init()2721 void HP_Audio_Init()
2722 { int ret,tmp,type;
2723   AudioAttributes req_attribs;
2724   AByteOrder  req_byteorder;
2725   AudioAttrMask req_mask;
2726   char server[256];
2727   server[0] = '\0';
2728 
2729   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_Init\n");
2730   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_Init: theAudContext = %x\n",
2731 						(xaULONG)theAudContext);
2732 
2733   if (xa_audio_present != XA_AUDIO_UNK) return;
2734 
2735   /* Setup Error Handler */
2736   hp_prev_handler = ASetErrorHandler(HP_Audio_Err_Handler);
2737 
2738   /* Open Up Audio */
2739   audio_connection = AOpenAudio( server, &hp_status);
2740   if (audio_connection == NULL)
2741   { char buf[256];
2742     HP_Print_Error("HP_Audio: couldn't connect to Audio -","\n",hp_status);
2743     xa_audio_present = XA_AUDIO_ERR;
2744     return;
2745   }
2746 
2747 
2748   /* Request the following attributes and see what get's returned */
2749   req_attribs.type = ATSampled;
2750   req_attribs.attr.sampled_attr.data_format = ADFLin16;
2751   req_attribs.attr.sampled_attr.bits_per_sample = 16;
2752   req_attribs.attr.sampled_attr.sampling_rate = 8000;
2753   req_attribs.attr.sampled_attr.channels = 1;  /* MONO */
2754   req_attribs.attr.sampled_attr.interleave = 1; /*???*/
2755   req_byteorder = AMSBFirst;
2756 
2757   play_attribs.type = ATSampled;
2758   play_attribs.attr.sampled_attr.data_format = ADFLin16;
2759   play_attribs.attr.sampled_attr.bits_per_sample = 16;
2760   play_attribs.attr.sampled_attr.sampling_rate = 8000;
2761   play_attribs.attr.sampled_attr.channels = 1;  /* MONO */
2762   play_attribs.attr.sampled_attr.interleave = 1; /*???*/
2763 
2764   fprintf(stderr,"REQ- format %d  bits %d  rate %d  chans %d bo %d\n",
2765 	req_attribs.attr.sampled_attr.data_format,
2766 	req_attribs.attr.sampled_attr.bits_per_sample,
2767 	req_attribs.attr.sampled_attr.sampling_rate,
2768 	req_attribs.attr.sampled_attr.channels,
2769 	req_byteorder );
2770 
2771 /*
2772   req_mask =   ASDataFormatMask | ASBitsPerSampleMask | ASSamplingRateMask
2773 	    | ASChannelsMask;
2774 */
2775   req_mask = ASDurationMask;
2776 
2777   AChoosePlayAttributes(audio_connection, &req_attribs,req_mask,
2778 				&play_attribs, &req_byteorder, NULL);
2779 
2780   fprintf(stderr,"REQ+ format %d  bits %d  rate %d  chans %d bo %d\n",
2781 	req_attribs.attr.sampled_attr.data_format,
2782 	req_attribs.attr.sampled_attr.bits_per_sample,
2783 	req_attribs.attr.sampled_attr.sampling_rate,
2784 	req_attribs.attr.sampled_attr.channels,
2785 	req_byteorder );
2786 
2787   fprintf(stderr,"PLAY format %d  bits %d  rate %d  chans %d\n",
2788 	play_attribs.attr.sampled_attr.data_format,
2789 	play_attribs.attr.sampled_attr.bits_per_sample,
2790 	play_attribs.attr.sampled_attr.sampling_rate,
2791 	play_attribs.attr.sampled_attr.channels	);
2792 
2793   switch(play_attribs.attr.sampled_attr.data_format)
2794   {
2795     case ADFLin16:	xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB; break;
2796     case ADFLin8:	xa_audio_hard_type  = XA_AUDIO_LINEAR_1M; break;
2797     case ADFLin8Offset:	xa_audio_hard_type  = XA_AUDIO_SIGNED_1M; break;
2798     default:
2799 	fprintf(stderr,"HP_Audio: unknown hardware format\n");
2800 	xa_audio_present = XA_AUDIO_ERR;
2801 	return;
2802 	break;
2803   }
2804 
2805   if (play_attribs.attr.sampled_attr.bits_per_sample == 16)
2806   		xa_audio_hard_bps = 2;
2807   else		xa_audio_hard_bps = 1;
2808 
2809   if ( (req_byteorder == AMSBFirst) && (xa_audio_hard_bps > 1) )
2810 			xa_audio_hard_type |= XA_AUDIO_BIGEND_MSK;
2811 
2812   xa_audio_hard_chans = play_attribs.attr.sampled_attr.channels;
2813   if (xa_audio_hard_chans == 2)
2814 			xa_audio_hard_type |= XA_AUDIO_STEREO_MSK;
2815 
2816 DEBUG_LEVEL1 fprintf(stderr,"HP hard_type %x\n",xa_audio_hard_type);
2817 
2818   xa_audio_hard_freq = play_attribs.attr.sampled_attr.sampling_rate;
2819 
2820   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
2821 
2822 /* NOT USED FOR NOW, BUT HOPEFULLY EVENTUALLY */
2823   { unsigned long *tmp;
2824     long num;
2825     hp_sample_rates = 0;
2826     num = ANumSamplingRates(audio_connection);
2827     if (num >= 0)
2828     {
2829       hp_sample_rates = (long *)malloc( (num + 2) * sizeof(long) );
2830       tmp = ASamplingRates(audio_connection);
2831       if (tmp)
2832       { xaULONG i;
2833         for(i=0; i < num; i++) hp_sample_rates[i] = tmp[i];
2834         hp_sample_rates[num] = 0;
2835 /*
2836 DEBUG_LEVEL1
2837 */
2838 {
2839   fprintf(stderr,"HP sampling rates: ");
2840   for(i=0;i<num;i++) fprintf(stderr,"<%d>",hp_sample_rates[i]);
2841   fprintf(stderr,"\n");
2842 }
2843       }
2844       else {FREE(hp_sample_rates,0x500); hp_sample_rates=0;}
2845       if (hp_sample_rates==0)
2846       {
2847 	fprintf(stderr,"Audio_Init: couldn't get sampling rates\n");
2848 	xa_audio_present = XA_AUDIO_ERR;
2849 	return;
2850       }
2851     }
2852   }
2853 
2854   xa_interval_id = 0;
2855   xa_audio_present = XA_AUDIO_OK;
2856 
2857   Init_Audio_Ring(xa_audio_ring_size,
2858 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
2859 
2860   switch(play_attribs.attr.sampled_attr.channels)
2861   {
2862     case 1:
2863 	gainEntry[0].u.o.out_ch = AOCTMono;
2864 	gainEntry[0].gain = AUnityGain;
2865 	if (XAAUD->port & XA_AUDIO_PORT_INT)
2866 		gainEntry[0].u.o.out_dst = AODTMonoIntSpeaker; /* internal */
2867 	else	gainEntry[0].u.o.out_dst = AODTMonoJack; /* ext or hdphones */
2868 	break;
2869     case 2:
2870     default:
2871 	fprintf(stderr,"HP_AUDIO: Warning hardware wants stereo\n");
2872 	gainEntry[0].u.o.out_ch = AOCTLeft;
2873 	gainEntry[0].gain = AUnityGain;
2874 	gainEntry[1].u.o.out_ch = AOCTRight;
2875 	gainEntry[1].gain = AUnityGain;
2876 	if (XAAUD->port & XA_AUDIO_PORT_INT)
2877 	{
2878 	  gainEntry[0].u.o.out_dst = AODTLeftIntSpeaker;
2879 	  gainEntry[1].u.o.out_dst = AODTRightIntSpeaker;
2880 	}
2881 	else
2882 	{
2883 	  gainEntry[0].u.o.out_dst = AODTLeftJack;
2884 	  gainEntry[1].u.o.out_dst = AODTRightJack;
2885 	}
2886         break;
2887   }
2888   streamParams.gain_matrix.type = AGMTOutput;
2889   streamParams.gain_matrix.num_entries =
2890 			play_attribs.attr.sampled_attr.channels;
2891   streamParams.gain_matrix.gain_entries = gainEntry;
2892   streamParams.play_volume = AUnityGain;
2893   streamParams.priority = APriorityNormal;
2894   streamParams.event_mask = 0;
2895 
2896 
2897   /* START UP SOCKET CONNECTION TO HP's AUDIO DEVICE */
2898 /*
2899   hp_attr_mask = ASDataFormatMask | ASBitsPerSampleMask |
2900 			ASSamplingRateMask | ASChannelsMask | ASInterleaveMask;
2901 */
2902   hp_attr_mask = ~0;
2903 
2904   /* create the stream */
2905   hp_trans_id = APlaySStream(audio_connection,hp_attr_mask,&play_attribs,
2906 				&streamParams,&audio_stream,NULL);
2907 
2908   /* create socket */
2909   streamSocket = socket(AF_INET, SOCK_STREAM, 0);
2910   if (streamSocket < 0) fprintf(stderr,"HP_Audio: socket err %d\n",errno);
2911 
2912   ret = connect(streamSocket,(struct sockaddr *)&audio_stream.tcp_sockaddr,
2913 					sizeof(struct sockaddr_in) );
2914   if (ret < 0) fprintf(stderr,"HP_Audio: connect error %d\n",errno);
2915 
2916   /* Pause Audio Stream */
2917   APauseAudio( audio_connection, hp_trans_id, NULL, NULL );
2918   hp_audio_paused = xaTRUE;
2919 }
2920 
2921 /********** HP_Audio_Kill ***************************************************
2922  * Stop HP Audio and Close HP Audio Devices. Free up memory.
2923  *****/
HP_Audio_Kill()2924 void HP_Audio_Kill()
2925 {
2926   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_Kill\n");
2927   HP_Audio_Off(0);
2928   close(streamSocket);
2929   /* IS THIS NEEDED? need to get man page for ASetCloseDownMode */
2930   ASetCloseDownMode(audio_connection, AKeepTransactions, NULL );
2931   ACloseAudio(audio_connection,NULL);
2932   Kill_Audio_Ring();
2933 }
2934 
2935 /********** HP_Audio_Off ***************************************************
2936  * Stop HP Audio
2937  *****/
HP_Audio_Off(flag)2938 void HP_Audio_Off(flag)
2939 xaULONG flag;
2940 {
2941   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_Off\n");
2942   if (xa_audio_status != XA_AUDIO_STARTED) return;
2943   /* SET FLAG TO STOP OUTPUT ROUTINE */
2944   xa_audio_status = XA_AUDIO_STOPPED;
2945 
2946   /* POD NOTE: USE PAUSE FOR NOW */
2947 /*
2948   APauseAudio(audio_connection,hp_trans_id, NULL, NULL);
2949   hp_audio_paused = xaTRUE;
2950 */
2951   xa_audio_status = XA_AUDIO_STOPPED;
2952   xa_time_audio = -1;
2953   xa_audio_flushed = 0;
2954 }
2955 
2956 /********** HP_Audio_Prep ***************************************************
2957  * Startup HP Audio
2958  *****/
HP_Audio_Prep()2959 void HP_Audio_Prep()
2960 { AudioAttrMask attr_mask;
2961   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_Prep \n");
2962   if (xa_audio_status == XA_AUDIO_STARTED) return;
2963   else if (xa_audio_present != XA_AUDIO_OK) return;
2964   else if (xa_snd_cur)
2965   { int ret,tmp,utime;
2966 
2967     /* Change Frequency If necessary */
2968     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
2969     {
2970       play_attribs.attr.sampled_attr.sampling_rate = xa_snd_cur->hfreq;
2971       xa_audio_hard_freq = xa_snd_cur->hfreq;
2972     }
2973 
2974     /* xa_snd_cur gets changes in Update_Ring() */
2975     xa_out_time = 250;  /* keep audio fed 500ms ahead of video */
2976     xa_out_init = xa_audio_ring_size - 1;
2977     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
2978     if (xa_interval_time == 0) xa_interval_time = 1;
2979 
2980     XA_Flush_Ring();
2981     XA_Update_Ring(1000);
2982     xa_audio_status = XA_AUDIO_PREPPED;
2983   }
2984 }
2985 
2986 /****-------------------------------------------------------------------****
2987  *
2988  ****-------------------------------------------------------------------****/
HP_Audio_On()2989 void HP_Audio_On()
2990 {
2991   if (   (xa_snd_cur)
2992       && (xa_audio_present == XA_AUDIO_OK)
2993       && (xa_audio_status == XA_AUDIO_PREPPED) )
2994   {
2995     xa_audio_status = XA_AUDIO_STARTED;
2996     xa_time_now = XA_Read_AV_Time();  /* get new time */
2997     New_Merged_Audio_Output();
2998   }
2999 }
3000 
3001 /********** HP_Closest_Freq **********************
3002  * Return closest support frequeny and set hard_buff.
3003  *****/
HP_Closest_Freq(ifreq)3004 xaULONG HP_Closest_Freq(ifreq)
3005 xaLONG ifreq;
3006 {
3007  /* POD TEMPORARY */
3008   xa_audio_hard_buff = XA_HARD_BUFF_1K;
3009   return(8000);
3010 }
3011 
3012 /********** HP_Speaker_Toggle **********************
3013  * Turn off/on/toggle HP's Speaker(if possible)
3014  * flag= 0   1   2
3015  *****/
HP_Speaker_Toggle(flag)3016 void HP_Speaker_Toggle(flag)
3017 xaULONG flag;
3018 {
3019   return;
3020 }
3021 
3022 /********** HP_Headphone_Toggle **********************
3023  * Turn off/on/toggle HP's Headphone(if possible)
3024  * flag= 0   don't use Headphones(defaults to internal speaker)
3025  * flag= 1   Use Headphones.
3026  * flag= 2   Toggle. If headphone then internal and vice_versa.
3027  *****/
HP_Headphone_Toggle(flag)3028 void HP_Headphone_Toggle(flag)
3029 xaULONG flag;
3030 {
3031   return;
3032 }
3033 
3034 /********** HP_Adjust_Volume **********************
3035  * Routine for Adjusting Volume on HP
3036  *
3037  *****/
3038 
3039 /* AUnityGain is 0. AZeroGain is 0x80000000 */
HP_Adjust_Volume(volume)3040 void HP_Adjust_Volume(volume)
3041 xaLONG volume;
3042 { xaLONG adj_volume;
3043   AGainDB play_gain,tmp_gain;
3044   int ret;
3045   adj_volume = HP_MIN_VOL +
3046 	((volume * (HP_MAX_VOL - HP_MIN_VOL)) / XA_AUDIO_MAXVOL);
3047   if (adj_volume > HP_MAX_VOL) adj_volume = HP_MAX_VOL;
3048   play_gain = (AGainDB)adj_volume;
3049 /*
3050   AGetSystemChannelGain(audio_connection,ASGTPlay,ACTMono,&tmp_gain,NULL);
3051   fprintf(stderr,"Get Gain %x adj_vol %x  hpmin %x hpmax %x\n",
3052 				tmp_gain,adj_volume,HP_MIN_VOL, HP_MAX_VOL);
3053   ASetSystemChannelGain(audio_connection,ASGTPlay,ACTMono,play_gain,NULL);
3054   ASetChannelGain(audio_connection,hp_trans_id,ACTMono,play_gain,NULL);
3055   ASetGain(audio_connection,hp_trans_id,play_gain,NULL);
3056 */
3057   ASetSystemPlayGain(audio_connection,play_gain,NULL);
3058 }
3059 
3060 #endif
3061 /****************************************************************************/
3062 /******************* END OF HP SPECIFIC ROUTINES ****************************/
3063 /****************************************************************************/
3064 
3065 
3066 /****************************************************************************/
3067 /**************** HPDEV SPECIFIC ROUTINES ***************************/
3068 /****************************************************************************/
3069 #ifdef XA_HPDEV_AUDIO
3070 
3071 void HPDEV_Audio_Init();
3072 void HPDEV_Audio_Kill();
3073 void HPDEV_Audio_Off();
3074 void HPDEV_Audio_Prep();
3075 void HPDEV_Audio_On();
3076 xaULONG HPDEV_Closest_Freq();
3077 void HPDEV_Speaker_Toggle();
3078 void HPDEV_Headphone_Toggle();
3079 void HPDEV_LineOut_Toggle();
3080 void HPDEV_Adjust_Volume();
3081 static void HPDEV_Audio_Output();
3082 
3083 static int devAudio;
3084 static struct audio_describe audioDesc;
3085 
3086 
3087 /********** XA_Audio_Setup **********************
3088  * Sets up HP specific routines
3089  *****/
XA_Audio_Setup()3090 void XA_Audio_Setup()
3091 {
3092   XA_Audio_Init		= HPDEV_Audio_Init;
3093   XA_Audio_Kill		= HPDEV_Audio_Kill;
3094   XA_Audio_Off		= HPDEV_Audio_Off;
3095   XA_Audio_Prep		= HPDEV_Audio_Prep;
3096   XA_Audio_On		= HPDEV_Audio_On;
3097   XA_Closest_Freq	= HPDEV_Closest_Freq;
3098   XA_Set_Output_Port	= (void *)(0);
3099   XA_Speaker_Tog	= HPDEV_Speaker_Toggle;
3100   XA_Headphone_Tog	= HPDEV_Headphone_Toggle;
3101   XA_LineOut_Tog	= HPDEV_LineOut_Toggle;
3102   XA_Adjust_Volume	= HPDEV_Adjust_Volume;
3103 
3104   xa_snd_cur = 0;
3105   xa_audio_present = XA_AUDIO_UNK;
3106   xa_audio_status = XA_AUDIO_STOPPED;
3107   xa_audio_ring_size = 8;
3108 }
3109 
3110 /********** HPDEV_Audio_Init ***************************************************
3111  * open /dev/audio and init
3112  *****/
HPDEV_Audio_Init()3113 void HPDEV_Audio_Init()
3114 {
3115   DEBUG_LEVEL2 fprintf(stderr,"HPDEV_Audio_Init\n");
3116   if (xa_audio_present != XA_AUDIO_UNK) return;
3117 
3118   if ((devAudio = open ("/dev/audio", O_WRONLY | O_NDELAY, 0)) < 0)
3119   {
3120     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
3121     else fprintf(stderr,"Audio_Init: Error opening audio device. - ");
3122     fprintf(stderr,"Will continue without audio\n");
3123     xa_audio_present = XA_AUDIO_ERR;
3124     return;
3125   }
3126 
3127   fcntl(devAudio,F_SETFL,O_NDELAY);
3128 
3129 
3130   /* Get description of /dev/audio: */
3131   if (ioctl (devAudio, AUDIO_DESCRIBE, &audioDesc))
3132   {
3133     perror ("ioctl AUDIO_DESCRIBE on /dev/audio");
3134     xa_audio_present = XA_AUDIO_ERR;
3135     return;
3136   }
3137 
3138   xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
3139   xa_audio_hard_freq  = 0; /* none yet (HPDEV_Audio_Prep does this job) */
3140   xa_audio_hard_bps   = 2;
3141   xa_audio_hard_chans = 1;
3142   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
3143 
3144   if (ioctl (devAudio, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT))
3145   {
3146     perror ("ioctl AUDIO_SET_DATA_FORMAT on /dev/audio");
3147     xa_audio_present = XA_AUDIO_ERR;
3148     return;
3149   }
3150   if (ioctl (devAudio, AUDIO_SET_CHANNELS, 1))
3151   {
3152     perror ("ioctl AUDIO_SET_CHANNELS on /dev/audio");
3153     xa_audio_present = XA_AUDIO_ERR;
3154     return;
3155   }
3156 
3157   /* set device internal buffer size: */
3158   if (ioctl (devAudio, AUDIO_SET_TXBUFSIZE, 16 * 1024))
3159     perror ("ioctl AUDIO_SET_TXBUFSIZE on /dev/audio");
3160 
3161   xa_interval_id = 0;
3162   xa_audio_present = XA_AUDIO_OK;
3163   Init_Audio_Ring(xa_audio_ring_size, (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
3164 }
3165 
3166 /********** HPDEV_Audio_Kill ***************************************************
3167  * Stop HP Audio and Close HP Audio Devices. Free up memory.
3168  *****/
HPDEV_Audio_Kill()3169 void HPDEV_Audio_Kill()
3170 {
3171   DEBUG_LEVEL2 fprintf(stderr,"HPDEV_Audio_Kill\n");
3172   HPDEV_Audio_Off(0);
3173   xa_audio_present = XA_AUDIO_UNK;
3174   close(devAudio);
3175   Kill_Audio_Ring();
3176 }
3177 
3178 /********** HPDEV_Audio_Off ***************************************************
3179  * Stop HP Audio
3180  *****/
HPDEV_Audio_Off(flag)3181 void HPDEV_Audio_Off(flag)
3182 xaULONG flag;
3183 {
3184   DEBUG_LEVEL2 fprintf(stderr,"HPDEV_Audio_Off\n");
3185   if (xa_audio_status != XA_AUDIO_STARTED) return;
3186 
3187   /* SET FLAG TO STOP OUTPUT ROUTINE */
3188   xa_audio_status = XA_AUDIO_STOPPED;
3189 
3190   if (ioctl (devAudio, AUDIO_DRAIN, 0))
3191     perror ("ioctl AUDIO_DRAIN on /dev/audio");
3192 
3193   xa_time_audio = -1;
3194   xa_audio_flushed = 0;
3195 }
3196 
3197 /********** HPDEV_Audio_Prep **************************************************
3198  * Startup HP Audio
3199  *****/
HPDEV_Audio_Prep()3200 void HPDEV_Audio_Prep()
3201 {
3202   DEBUG_LEVEL2 fprintf(stderr,"HPDEV_Audio_Prep\n");
3203   if (xa_audio_status == XA_AUDIO_STARTED) return;
3204   else if (xa_audio_present != XA_AUDIO_OK) return;
3205   else if (xa_snd_cur)
3206   { int ret,tmp,utime;
3207 
3208     /* Change frequency if necessary */
3209     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
3210     {
3211       do { ret = ioctl(devAudio, AUDIO_SET_SAMPLE_RATE, xa_snd_cur->hfreq);
3212          } while( (ret < 0) && (errno == EBUSY) );
3213       if (ret < 0) perror ("ioctl AUDIO_SET_SAMPLE_RATE on /dev/audio");
3214       xa_audio_hard_freq = xa_snd_cur->hfreq;
3215     }
3216 
3217     /* xa_snd_cur gets changes in Update_Ring() */
3218     xa_out_time = 250; /* keep audio fed 250ms ahead of video */
3219     xa_out_init = xa_audio_ring_size - 1;
3220     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
3221     if (xa_interval_time == 0) xa_interval_time = 1;
3222 
3223     XA_Flush_Ring();
3224     XA_Update_Ring(1000);
3225     xa_audio_status = XA_AUDIO_PREPPED;
3226   }
3227 }
3228 
3229 /****-------------------------------------------------------------------****
3230  *
3231  ****-------------------------------------------------------------------****/
HPDEV_Audio_On()3232 void HPDEV_Audio_On()
3233 {
3234   if (   (xa_snd_cur)
3235       && (xa_audio_present == XA_AUDIO_OK)
3236       && (xa_audio_status == XA_AUDIO_PREPPED) )
3237   {
3238     xa_audio_status = XA_AUDIO_STARTED;
3239     xa_time_now = XA_Read_AV_Time();  /* get new time */
3240     New_Merged_Audio_Output();
3241   }
3242 }
3243 
3244 /********** HPDEV_Closest_Freq **********************
3245  * Return closest support frequeny and set hard_buff.
3246  *****/
HPDEV_Closest_Freq(ifreq)3247 xaULONG HPDEV_Closest_Freq(ifreq)
3248 xaLONG ifreq;
3249 {
3250   unsigned int rate_index;
3251   long nearest_frequency = 8000;
3252   long frequency_diff = 999999;
3253 
3254   xa_audio_hard_buff = XA_HARD_BUFF_1K;
3255 
3256   for (rate_index = 0; rate_index < audioDesc.nrates; ++rate_index)
3257   { if (abs (audioDesc.sample_rate[rate_index] - ifreq) <= frequency_diff)
3258     { nearest_frequency = audioDesc.sample_rate[rate_index];
3259       frequency_diff = abs (audioDesc.sample_rate[rate_index] - ifreq);
3260     }
3261   }
3262   return nearest_frequency;
3263 }
3264 
3265 /********** HPDEV_Speaker_Toggle **********************
3266  * Turn off/on/toggle HP's Speaker(if possible)
3267  * flag= 0   1   2
3268  *****/
HPDEV_Speaker_Toggle(flag)3269 void HPDEV_Speaker_Toggle(flag)
3270 xaULONG flag;
3271 {
3272   int output_channel;
3273 
3274   if (ioctl (devAudio, AUDIO_GET_OUTPUT, &output_channel))
3275   {
3276     perror ("ioctl AUDIO_GET_OUTPUT on /dev/audio");
3277     output_channel = 0;
3278   }
3279   switch (flag)
3280   {
3281     case 0:
3282       output_channel &= ~AUDIO_OUT_SPEAKER; break;
3283     case 1:
3284       output_channel |= AUDIO_OUT_SPEAKER; break;
3285     case 2:
3286       output_channel ^= AUDIO_OUT_SPEAKER;
3287   }
3288   if (ioctl (devAudio, AUDIO_SET_OUTPUT, output_channel))
3289     perror ("ioctl AUDIO_SET_OUTPUT on /dev/audio");
3290 }
3291 
3292 /********** HPDEV_Headphone_Toggle **********************
3293  * Turn off/on/toggle HP's Headphone(if possible)
3294  * flag= 0   don't use Headphones(defaults to internal speaker)
3295  * flag= 1   Use Headphones.
3296  * flag= 2   Toggle. If headphone then internal and vice_versa.
3297  *****/
HPDEV_Headphone_Toggle(flag)3298 void HPDEV_Headphone_Toggle(flag)
3299 xaULONG flag;
3300 {
3301   int output_channel;
3302 
3303   if (ioctl (devAudio, AUDIO_GET_OUTPUT, &output_channel))
3304   {
3305     perror ("ioctl AUDIO_GET_OUTPUT on /dev/audio");
3306     output_channel = 0;
3307   }
3308   switch (flag)
3309   {
3310     case 0:
3311       output_channel &= ~AUDIO_OUT_HEADPHONE; break;
3312     case 1:
3313       output_channel |= AUDIO_OUT_HEADPHONE; break;
3314     case 2:
3315       output_channel ^= AUDIO_OUT_HEADPHONE;
3316   }
3317   if (ioctl (devAudio, AUDIO_SET_OUTPUT, output_channel))
3318     perror ("ioctl AUDIO_SET_OUTPUT on /dev/audio");
3319 }
3320 
3321 /********** HPDEV_LineOut_Toggle **********************
3322  * Turn off/on/toggle HP's LineOut(if possible)
3323  * flag= 0   don't use LineOut(defaults to internal speaker)
3324  * flag= 1   Use LineOut.
3325  * flag= 2   Toggle. If LineOut then internal and vice_versa.
3326  *****/
HPDEV_LineOut_Toggle(flag)3327 void HPDEV_LineOut_Toggle(flag)
3328 xaULONG flag;
3329 {
3330   int output_channel;
3331 
3332   if (ioctl (devAudio, AUDIO_GET_OUTPUT, &output_channel))
3333   {
3334     perror ("ioctl AUDIO_GET_OUTPUT on /dev/audio");
3335     output_channel = 0;
3336   }
3337   switch (flag)
3338   {
3339     case 0:
3340       output_channel &= ~AUDIO_OUT_LINE; break;
3341     case 1:
3342       output_channel |= AUDIO_OUT_LINE; break;
3343     case 2:
3344       output_channel ^= AUDIO_OUT_LINE;
3345   }
3346   if (ioctl (devAudio, AUDIO_SET_OUTPUT, output_channel))
3347     perror ("ioctl AUDIO_SET_OUTPUT on /dev/audio");
3348 }
3349 
3350 /********** HPDEV_Adjust_Volume **********************
3351  * Routine for Adjusting Volume on HP
3352  *
3353  *****/
HPDEV_Adjust_Volume(volume)3354 void HPDEV_Adjust_Volume(volume)
3355 xaLONG volume;
3356 {
3357   struct audio_describe description;
3358   struct audio_gains gains;
3359   float floatvolume = ((float)volume - (float)XA_AUDIO_MINVOL) /
3360 		      ((float)XA_AUDIO_MAXVOL - (float)XA_AUDIO_MINVOL);
3361 
3362   if (ioctl (devAudio, AUDIO_DESCRIBE, &description))
3363   {
3364     perror ("ioctl AUDIO_DESCRIBE on /dev/audio");
3365     return;
3366   }
3367   if (ioctl (devAudio, AUDIO_GET_GAINS, &gains))
3368   {
3369     perror ("ioctl AUDIO_GET_GAINS on /dev/audio");
3370     return;
3371   }
3372   gains.transmit_gain = (int)((float)description.min_transmit_gain +
3373 			      (float)(description.max_transmit_gain
3374 				      - description.min_transmit_gain) * floatvolume);
3375   if (ioctl (devAudio, AUDIO_SET_GAINS, &gains))
3376     perror ("ioctl AUDIO_SET_GAINS on /dev/audio");
3377 }
3378 
3379 #endif
3380 /****************************************************************************/
3381 /******************* END OF HPDEV SPECIFIC ROUTINES ******************/
3382 /****************************************************************************/
3383 
3384 /****************************************************************************/
3385 /**************** AF SPECIFIC ROUTINES **************************************/
3386 /****************************************************************************/
3387 #ifdef XA_AF_AUDIO
3388 
3389 /*
3390  * AF port provided by Tom Levergood,
3391  *	tml@crl.dec.com
3392  * Thu Aug 25 14:05:47 1994
3393  * This is a quick hack, I need to stare at the xa buffering
3394  * further to clean up the port.
3395  */
3396 
3397 void  AF_Audio_Init();
3398 void  AF_Audio_Kill();
3399 void  AF_Audio_Off();
3400 void  AF_Audio_Prep();
3401 void  AF_Audio_On();
3402 void  AF_Adjust_Volume();
3403 xaULONG AF_Closest_Freq();
3404 void AF_Speaker_Toggle();
3405 void AF_Headphone_Toggle();
3406 
3407 
3408 static AFAudioConn *AFaud;
3409 static AC ac;
3410 static AFSetACAttributes AFattributes;
3411 static int	AFdevice;
3412 static ATime AFtime0=0;
3413 static ATime AFbaseT=0;
3414 
3415 /********** XA_Audio_Setup **********************
3416  *
3417  * Also defines Sparc Specific variables.
3418  *
3419  *****/
XA_Audio_Setup()3420 void XA_Audio_Setup()
3421 {
3422   XA_Audio_Init		= AF_Audio_Init;
3423   XA_Audio_Kill		= AF_Audio_Kill;
3424   XA_Audio_Off		= AF_Audio_Off;
3425   XA_Audio_Prep		= AF_Audio_Prep;
3426   XA_Audio_On		= AF_Audio_On;
3427   XA_Closest_Freq	= AF_Closest_Freq;
3428   XA_Set_Output_Port	= (void *)(0);
3429   XA_Speaker_Tog	= AF_Speaker_Toggle;
3430   XA_Headphone_Tog	= AF_Headphone_Toggle;
3431   XA_LineOut_Tog	= AF_Headphone_Toggle;
3432   XA_Adjust_Volume	= AF_Adjust_Volume;
3433 
3434   xa_snd_cur = 0;
3435   xa_audio_present = XA_AUDIO_UNK;
3436   xa_audio_status  = XA_AUDIO_STOPPED;
3437   xa_audio_ring_size  = 8;
3438 }
3439 
3440 
3441 #define	AF_C_MIN	-30
3442 #define	AF_C_MAX	30
3443 #define AF_MAP_TO_C_GAIN(vol) (( ((vol)*AF_C_MAX)/XA_AUDIO_MAXVOL) + (AF_C_MIN))
3444 
3445 #define SPU(type)       AF_sample_sizes[type].samps_per_unit
3446 #define BPU(type)       AF_sample_sizes[type].bytes_per_unit
3447 
3448 #define DPHONE(od) (int)(((AAudioDeviceDescriptor(AFaud, (od)))->outputsToPhone))
3449 #define DFREQ(od) (int)(((AAudioDeviceDescriptor(AFaud, (od)))->playSampleFreq))
3450 #define DCHAN(od) (int)((AAudioDeviceDescriptor(AFaud, (od)))->playNchannels)
3451 #define DTYPE(od) ((AAudioDeviceDescriptor(AFaud, (od)))->playBufType)
3452 
3453 #define	TOFFSET	250
3454 
3455 
3456 /*
3457  * Find a suitable default device (the first device not connected to the phone),
3458  *  returns device number.
3459  *
3460  * Returns -1 if no suitable device can be found.
3461  */
FindDefaultDevice(aud)3462 static int FindDefaultDevice(aud)
3463 AFAudioConn *aud;
3464 {
3465   int i;
3466   char *ep;
3467 
3468   if ((ep = getenv("AF_DEVICE")) != NULL)
3469   { int udevice;
3470     udevice = atoi(ep);
3471     if ((udevice >= 0) && (udevice < ANumberOfAudioDevices(aud)))
3472 	return udevice;
3473   }
3474   for(i=0; i<ANumberOfAudioDevices(aud); i++)
3475   {
3476     if ( DPHONE(i) == 0 && DCHAN(i) == 1 ) return i;
3477   }
3478   return -1;
3479 }
3480 
XA_No_Audio_Support()3481 void XA_No_Audio_Support()
3482 {
3483   fprintf(stderr,"AUDIO SUPPORT NOT COMPILED IN THIS EXECUTABLE.\n");
3484   return;
3485 }
3486 
3487 /********** AF_Audio_Init **********************
3488  *****/
AF_Audio_Init()3489 void AF_Audio_Init()
3490 {
3491   DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_Init\n");
3492   if (xa_audio_present != XA_AUDIO_UNK) return;
3493 
3494   /* Open connection. */
3495   if ( (AFaud = AFOpenAudioConn("")) == NULL)
3496   {
3497       fprintf(stderr, "Could not open connection to AF audio server.\n");
3498       fprintf(stderr, "Disabling audio service.\n");
3499       /* As long as xa_audio_present isn't OK, audio is effectively disabled*/
3500       /* but might as well really disable it */
3501       XA_Null_Audio_Setup();
3502       xa_audio_present = XA_AUDIO_UNK;
3503       return;
3504   }
3505   AFdevice = FindDefaultDevice(AFaud);
3506   AFattributes.type = LIN16;
3507   AFattributes.endian = ALittleEndian;
3508   AFattributes.play_gain = AF_MAP_TO_C_GAIN(XAAUD->volume);
3509   ac = AFCreateAC(AFaud, AFdevice, (ACPlayGain | ACEncodingType | ACEndian), &AFattributes);
3510   AFSync(AFaud, 0);     /* Make sure we confirm encoding type support. */
3511   if (ac == NULL)
3512   {
3513     fprintf(stderr,"AF: Could not create audio context for device %d\n",AFdevice);
3514     xa_audio_present = XA_AUDIO_ERR;
3515     return;
3516   }
3517 
3518 DEBUG_LEVEL2 fprintf(stderr,"Created audio context, SR %d device %d\n",
3519 			 DFREQ(AFdevice),AFdevice);
3520 
3521   /* get default frequency - not really necessary */
3522   xa_audio_hard_freq = DFREQ(AFdevice);
3523 
3524   xa_audio_hard_bps = 2;
3525   xa_audio_hard_chans = 1;
3526   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
3527   xa_audio_hard_type  = XA_AUDIO_SIGNED_2ML;
3528 
3529   xa_interval_id = 0;
3530   xa_audio_present = XA_AUDIO_OK;
3531   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
3532   Init_Audio_Ring(xa_audio_ring_size,
3533 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
3534 }
3535 
3536 /********** AF_Audio_Kill **********************
3537  *****/
AF_Audio_Kill()3538 void AF_Audio_Kill()
3539 {
3540 DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_Kill\n");
3541 
3542   AF_Audio_Off(0);
3543   xa_audio_present = XA_AUDIO_UNK;
3544 
3545   /* XXX */
3546   AFCloseAudioConn(AFaud);
3547 
3548   Kill_Audio_Ring();
3549 }
3550 
3551 /********** AF_Audio_Off **********************
3552  * Stop Audio Stream
3553  *
3554  *****/
AF_Audio_Off(flag)3555 void AF_Audio_Off(flag)
3556 xaULONG flag;
3557 {
3558   DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_Off\n");
3559   if (xa_audio_status == XA_AUDIO_STOPPED) return;
3560 
3561   /* XXX */
3562 
3563   xa_audio_status = XA_AUDIO_STOPPED;
3564 }
3565 
3566 /********** AF_Audio_Prep **********************
3567  * Turn On Audio Stream.
3568  *
3569  *****/
AF_Audio_Prep()3570 void AF_Audio_Prep()
3571 {
3572   DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_Prep \n");
3573   if (xa_audio_status == XA_AUDIO_STARTED) return;
3574   else if (xa_audio_present != XA_AUDIO_OK) return;
3575   else if (xa_snd_cur)
3576   {
3577     /* Change Frequency If necessary */
3578     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
3579     {
3580 	/* XXX */
3581       xa_audio_hard_freq = xa_snd_cur->hfreq;
3582     }
3583 
3584     /* xa_snd_cur gets changes in Update_Ring() */
3585     xa_out_time = 250; /* keep audio fed 250ms ahead of video - could be 500*/
3586     xa_out_init = xa_audio_ring_size - 1;
3587     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
3588     if (xa_interval_time == 0) xa_interval_time = 1;
3589 
3590     XA_Flush_Ring();
3591     XA_Update_Ring(1000);
3592     xa_audio_status = XA_AUDIO_PREPPED;
3593   }
3594 }
3595 
3596 /****-------------------------------------------------------------------****
3597  *
3598  ****-------------------------------------------------------------------****/
AF_Audio_On()3599 void AF_Audio_On()
3600 {
3601   if (   (xa_snd_cur)
3602       && (xa_audio_present == XA_AUDIO_OK)
3603       && (xa_audio_status == XA_AUDIO_PREPPED) )
3604   {
3605     xa_audio_status = XA_AUDIO_STARTED;
3606     AFtime0 = AFbaseT = AFGetTime(ac) + TOFFSET;
3607     xa_time_now = XA_Read_AV_Time();  /* get new time */
3608     New_Merged_Audio_Output();
3609   }
3610 }
3611 
3612 /*************
3613  * flag = 0  turn speaker off
3614  * flag = 1  turn speaker on
3615  * flag = 2  toggle speaker
3616  */
AF_Speaker_Toggle(flag)3617 void AF_Speaker_Toggle(flag)
3618 xaULONG flag;
3619 {
3620   DEBUG_LEVEL2 fprintf(stderr,"AF_Speaker_Toggle\n");
3621 }
3622 
AF_Headphone_Toggle(flag)3623 void AF_Headphone_Toggle(flag)
3624 xaULONG flag;
3625 {
3626   DEBUG_LEVEL2 fprintf(stderr,"AF_Headphone_Toggle\n");
3627 }
3628 
3629 /********** AF_Adjust_Volume **********************
3630  * Routine for Adjusting Volume on a AF
3631  *
3632  *****/
AF_Adjust_Volume(volume)3633 void AF_Adjust_Volume(volume)
3634 xaULONG volume;
3635 {
3636  DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_Volume %d\n",volume);
3637 
3638  /* Client gain settings range from -30 to +30 dB. */
3639  AFattributes.play_gain = AF_MAP_TO_C_GAIN(volume);
3640  AFChangeACAttributes(ac, ACPlayGain, &AFattributes);
3641  AFSync(AFaud,0);
3642 }
3643 
3644 /********** AF_Closest_Freq **********************
3645  *
3646  * Global Variable Affect:
3647  *   xaULONG xa_audio_hard_buff		must set but not larger than
3648  *					XA_AUDIO_MAX_RING_BUF size
3649  */
AF_Closest_Freq(ifreq)3650 xaULONG AF_Closest_Freq(ifreq)
3651 xaLONG ifreq;
3652 {
3653  return (DFREQ(AFdevice));
3654 }
3655 
3656 #endif
3657 /****************************************************************************/
3658 /******************* END OF AF SPECIFIC ROUTINES ****************************/
3659 /****************************************************************************/
3660 
3661 
3662 /****************************************************************************/
3663 /**************** DEC Multimedia Services SPECIFIC ROUTINES *****************/
3664 /****************************************************************************/
3665 #ifdef XA_MMS_AUDIO
3666 
3667 /*
3668  * MMS port provided by Tom Morris (morris@zko.dec.com)
3669  */
3670 
3671 void  MMS_Audio_Init();
3672 void  MMS_Audio_Kill();
3673 void  MMS_Audio_Off();
3674 void  MMS_Audio_Prep();
3675 void  MMS_Audio_On();
3676 void  MMS_Adjust_Volume();
3677 xaULONG MMS_Closest_Freq();
3678 void MMS_Speaker_Toggle();
3679 void MMS_Headphone_Toggle();
3680 
3681 /* Global variables */
3682 
3683 static HWAVEOUT		mms_device_handle = 0;
3684 static UINT		mms_device_id = 0;
3685 static xaULONG		mms_device_volume = xaFALSE;
3686 static LPWAVEHDR	mms_lpWaveHeader;
3687 static LPSTR		mms_audio_buffer;
3688 static int		mms_buffers_outstanding = 0;
3689 static int		mms_next_buffer = 0;
3690 
3691 /********** XA_Audio_Setup **********************
3692  *
3693  *****/
XA_Audio_Setup()3694 void XA_Audio_Setup()
3695 {
3696   XA_Audio_Init		= MMS_Audio_Init;
3697   XA_Audio_Kill		= MMS_Audio_Kill;
3698   XA_Audio_Off		= MMS_Audio_Off;
3699   XA_Audio_Prep		= MMS_Audio_Prep;
3700   XA_Audio_On		= MMS_Audio_On;
3701   XA_Closest_Freq	= MMS_Closest_Freq;
3702   XA_Set_Output_Port	= (void *)(0);
3703   XA_Speaker_Tog	= MMS_Speaker_Toggle;
3704   XA_Headphone_Tog	= MMS_Headphone_Toggle;
3705   XA_LineOut_Tog	= MMS_Headphone_Toggle;
3706   XA_Adjust_Volume	= MMS_Adjust_Volume;
3707 
3708   xa_snd_cur = 0;
3709   xa_audio_present = XA_AUDIO_UNK;
3710   xa_audio_status  = XA_AUDIO_STOPPED;
3711   xa_audio_ring_size  = 8;
3712 }
3713 
XA_No_Audio_Support()3714 void XA_No_Audio_Support()
3715 {
3716   fprintf(stderr,"AUDIO SUPPORT NOT COMPILED IN THIS EXECUTABLE.\n");
3717   return;
3718 }
3719 
3720 /********** MMS_Audio_Init **********************
3721 
3722   This just does some generic initialization.  The actual audio
3723   output device open is done in the Audio_Prep routine so that we
3724   can get a device which matches the requested sample rate & format
3725 
3726  *****/
MMS_Audio_Init()3727 void MMS_Audio_Init()
3728 {
3729   MMRESULT	status;
3730   LPWAVEOUTCAPS	lpCaps;
3731 
3732   DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_Init\n");
3733   if (xa_audio_present != XA_AUDIO_UNK) return;
3734 
3735   if( waveOutGetNumDevs() < 1 )
3736   {
3737     xa_audio_present = XA_AUDIO_ERR;
3738     fprintf(stderr,"Audio disabled - No Multimedia Services compatible audio devices available\n");
3739     return;
3740   }
3741 
3742   /* Figure out device capabilities  - Just use device 0 for now */
3743 
3744   if((lpCaps = (LPWAVEOUTCAPS)mmeAllocMem(sizeof(WAVEOUTCAPS))) == NULL ) {
3745       fprintf(stderr,"Failed to allocate WAVEOUTCAPS struct\n");
3746       return;
3747   }
3748   status = waveOutGetDevCaps( 0, lpCaps, sizeof(WAVEOUTCAPS));
3749   if( status != MMSYSERR_NOERROR ) {
3750       fprintf(stderr,"waveOutGetDevCaps failed - status = %d\n", status);
3751   }
3752 
3753   /* Multimedia Services will do sample rate & format conversion for
3754   ** simpler devices, so just go for the max
3755   */
3756 /* No stereo support currently?
3757   xa_audio_hard_type  = XA_AUDIO_SIGNED_2SL;
3758   xa_audio_hard_chans = 2;
3759   xa_audio_hard_bps = 4;
3760 */
3761 
3762   xa_audio_hard_type  = XA_AUDIO_SIGNED_2ML;
3763   xa_audio_hard_chans = 1;
3764   xa_audio_hard_bps = 2;
3765 
3766   /* Make sure device gets openend first time through */
3767   xa_audio_hard_freq = 0;
3768 
3769 
3770   /* Remember whether the volume control will work */
3771   if( lpCaps->dwSupport & WAVECAPS_VOLUME )
3772     mms_device_volume = xaTRUE;
3773   else
3774     mms_device_volume = xaFALSE;
3775 
3776   mmeFreeMem(lpCaps);
3777 
3778   /*
3779   ** We don't really care what this value is - use something easy
3780   */
3781   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
3782 
3783   xa_interval_id = 0;
3784   xa_audio_present = XA_AUDIO_OK;
3785 
3786   /* Register our callback routine to be called whenever there is work */
3787   XtAppAddInput(theAudContext,
3788 		mmeServerFileDescriptor(),
3789 		(XtPointer)XtInputReadMask,
3790 		(XtInputCallbackProc)mmeProcessCallbacks,
3791 		0);
3792 
3793   Init_Audio_Ring(xa_audio_ring_size,
3794 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
3795 }
3796 
3797 /********** MMS_Audio_Kill **********************
3798  *****/
MMS_Audio_Kill()3799 void MMS_Audio_Kill()
3800 {
3801   MMRESULT status;
3802   DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_Kill\n");
3803 
3804   MMS_Audio_Off(0);
3805   xa_audio_present = XA_AUDIO_UNK;
3806 
3807   status = waveOutReset(mms_device_handle);
3808   if( status != MMSYSERR_NOERROR ) {
3809       fprintf(stderr,"waveOutReset failed - status = %d\n", status);
3810   }
3811   status = waveOutClose(mms_device_handle);
3812   if( status != MMSYSERR_NOERROR ) {
3813       fprintf(stderr,"waveOutClose failed - status = %d\n", status);
3814   }
3815 
3816   mmeFreeBuffer(mms_audio_buffer);
3817   mmeFreeMem(mms_lpWaveHeader);
3818 
3819   Kill_Audio_Ring();
3820 }
3821 
3822 /********** MMS_Audio_Off **********************
3823  * Stop Audio Stream
3824  *
3825  *****/
MMS_Audio_Off(flag)3826 void MMS_Audio_Off(flag)
3827 xaULONG flag;
3828 {
3829   DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_Off\n");
3830   if (xa_audio_status == XA_AUDIO_STOPPED) return;
3831 
3832   /* Just set our flag and let things drain */
3833   /* we could use waveOutReset if we were in a hurry */
3834   xa_audio_status = XA_AUDIO_STOPPED;
3835 }
3836 
3837 /********** MMS_Audio_Prep **********************
3838  * Turn On Audio Stream.
3839  *
3840  *****/
3841 /*POD TEMP
3842 static void MMS_wave_callback(HANDLE hWaveOut,
3843 			      UINT wMsg,
3844 			      DWORD dwInstance,
3845 			      LPARAM lParam1,
3846 			      LPARAM lParam2)
3847 */
MMS_wave_callback(hWaveOut,wMsg,dwInstance,lParam1,lParam2)3848 static void MMS_wave_callback(hWaveOut,wMsg,dwInstance,lParam1,lParam2)
3849 HANDLE hWaveOut;
3850 UINT wMsg;
3851 DWORD dwInstance;
3852 LPARAM lParam1;
3853 LPARAM lParam2;
3854 {
3855     switch(wMsg)
3856       {
3857 	  case WOM_OPEN:
3858 	  case WOM_CLOSE: {
3859 	      /* Ignore these */
3860 	      break;
3861 	  }
3862 	  case WOM_DONE: {
3863 	      LPWAVEHDR lpwh = (LPWAVEHDR)lParam1;
3864 	      mms_buffers_outstanding--;
3865 	      break;
3866 	  }
3867 	  default: {
3868 	      fprintf(stderr,
3869 		      "Unknown MMS waveOut callback messages receieved.\n");
3870 	      break;
3871 	  }
3872       }
3873 }
3874 
MMS_Audio_Prep()3875 void MMS_Audio_Prep()
3876 {
3877   MMRESULT status;
3878   LPPCMWAVEFORMAT lpWaveFormat;
3879 
3880   DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_Prep \n");
3881   if (xa_audio_status == XA_AUDIO_STARTED) return;
3882   else if (xa_audio_present != XA_AUDIO_OK) return;
3883   else if (xa_snd_cur)
3884   {
3885     /* Close & Reopen device if necessary */
3886     if (xa_audio_hard_freq != xa_snd_cur->hfreq )
3887     {
3888 	if( mms_device_handle != 0 ) {
3889 	    status = waveOutReset(mms_device_handle);
3890 	    if( status != MMSYSERR_NOERROR ) {
3891 		fprintf(stderr,"waveOutReset failed - status = %d\n", status);
3892 	    }
3893 	    status = waveOutClose(mms_device_handle);
3894 	    if( status != MMSYSERR_NOERROR ) {
3895 		fprintf(stderr,"waveOutClose failed - status = %d\n", status);
3896 	    }
3897 	}
3898 	if((lpWaveFormat = (LPPCMWAVEFORMAT)
3899 			mmeAllocMem(sizeof(PCMWAVEFORMAT))) == NULL )
3900 	{
3901 	    fprintf(stderr,"Failed to allocate PCMWAVEFORMAT struct\n");
3902 	    return;
3903 	}
3904 	lpWaveFormat->wf.nSamplesPerSec = xa_snd_cur->hfreq;
3905 
3906 	lpWaveFormat->wf.nChannels = xa_audio_hard_chans;
3907 	lpWaveFormat->wBitsPerSample = xa_audio_hard_bps*8/xa_audio_hard_chans;
3908 	if( xa_audio_hard_type == XA_AUDIO_SUN_AU )
3909 	  lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_MULAW;
3910 	else if((xa_audio_hard_type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_SIGNED ||
3911 		(xa_audio_hard_type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_LINEAR )
3912 	  lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
3913 	else {
3914 	    fprintf(stderr,"Unsupported audio format\n");
3915 	    return;
3916 	}
3917 
3918 	/* The audio format to convert to has already been picked based on what
3919 	   we said the hardware capabilities were, so don't change now or we'll
3920 	   confuse everyone.  If we were going to take maximum advantage of the
3921 	   MMS & hardware capabilities, we'd do it something like this:
3922 	*/
3923 #if 0
3924 	if (xa_audio_hard_freq != xa_snd_cur->hfreq ||
3925 	    xa_audio_hard_type != xa_snd_cur->type );
3926 
3927 	if( xa_snd_cur->type & XA_AUDIO_STEREO_MSK )
3928 	  lpWaveFormat->wf.nChannels = 2;
3929 	else
3930 	  lpWaveFormat->wf.nChannels = 1;
3931 	if( xa_snd_cur->type & XA_AUDIO_BPS_2_MSK )
3932 	  lpWaveFormat->wBitsPerSample = 16;
3933 	else
3934 	  lpWaveFormat->wBitsPerSample = 8;
3935 	if( (xa_snd_cur->type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_SUN_AU )
3936 	  lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_MULAW;
3937 	else if(   (xa_snd_cur->type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_SIGNED
3938 		|| (xa_snd_cur->type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_LINEAR )
3939 	  lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
3940 	else if( (xa_snd_cur->type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_ADPCM)
3941 	  lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_IMA_ADPCM;
3942 	else {
3943 	    fprintf(stderr,"Unsupported audio format\n");
3944 	    return;
3945 	}
3946 #endif
3947 
3948 	lpWaveFormat->wf.nBlockAlign = lpWaveFormat->wf.nChannels *
3949 	                               ((lpWaveFormat->wBitsPerSample+7)/8);
3950 	lpWaveFormat->wf.nAvgBytesPerSec = lpWaveFormat->wf.nBlockAlign *
3951 	  				  lpWaveFormat->wf.nSamplesPerSec;
3952 
3953 	/* Open the audio device in the appropriate rate/format */
3954 	mms_device_handle = 0;
3955 	status = waveOutOpen( &mms_device_handle,
3956 			     WAVE_MAPPER,
3957 			     (LPWAVEFORMAT)lpWaveFormat,
3958 			     MMS_wave_callback,
3959 			     NULL,
3960 			     CALLBACK_FUNCTION | WAVE_OPEN_SHAREABLE );
3961 	if( status != MMSYSERR_NOERROR ) {
3962 	    fprintf(stderr,"waveOutOpen failed - status = %d\n", status);
3963 	}
3964 
3965 	/* Get & save the device ID for volume control */
3966 	status = waveOutGetID( mms_device_handle, &mms_device_id );
3967 	if( status != MMSYSERR_NOERROR ) {
3968 	    fprintf(stderr,"waveOutGetID failed - status = %d\n", status);
3969 	}
3970 
3971 	DEBUG_LEVEL2 fprintf(stderr,"Opened waveOut device #%d \n",
3972 		mms_device_id);
3973 	DEBUG_LEVEL2 fprintf(stderr,
3974 			     "Format=%d, Rate=%d, channels=%d, bps=%d \n",
3975 			     lpWaveFormat->wf.wFormatTag,
3976 			     lpWaveFormat->wf.nSamplesPerSec,
3977 			     lpWaveFormat->wf.nChannels,
3978 			     lpWaveFormat->wBitsPerSample );
3979 
3980 	mmeFreeMem(lpWaveFormat);
3981 
3982 	/* Allocate wave header for use in write */
3983 	if((mms_lpWaveHeader = (LPWAVEHDR)
3984 				mmeAllocMem(sizeof(WAVEHDR))) == NULL )
3985 	{
3986 	    fprintf(stderr,"Failed to allocate WAVEHDR struct\n");
3987 	    return;
3988 	}
3989 
3990 	/* Allocate shared audio buffer for communicating with audio device */
3991 	/* NOTE: It's just a matter of convenience that it's the same size  */
3992 	/*	as  XAnim's audio ring buffer - don't confuse the two	    */
3993 	if ( (mms_audio_buffer = (LPSTR)
3994 	      mmeAllocBuffer(xa_audio_hard_buff*xa_audio_ring_size )) == NULL)
3995         {
3996 	  fprintf(stderr,"Failed to allocate shared audio buffer\n");
3997 	  return;
3998 	}
3999 
4000 	/* Save current hardware settings */
4001 	xa_audio_hard_freq = xa_snd_cur->hfreq;
4002 	xa_audio_hard_type = xa_snd_cur->type;
4003     }
4004 
4005     /* These values are all cut & paste from other devices - hope they got
4006        them right there! - tfm */
4007     xa_out_time = 100;
4008     xa_out_init = xa_audio_ring_size - 1;
4009     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
4010     if (xa_interval_time == 0) xa_interval_time = 1;
4011 
4012     XA_Flush_Ring();
4013     XA_Update_Ring(1000);
4014     xa_audio_status = XA_AUDIO_PREPPED;
4015   }
4016 }
4017 
4018 /****-------------------------------------------------------------------****
4019  *
4020  ****-------------------------------------------------------------------****/
MMS_Audio_On()4021 void MMS_Audio_On()
4022 {
4023   if (   (xa_snd_cur)
4024       && (xa_audio_present == XA_AUDIO_OK)
4025       && (xa_audio_status == XA_AUDIO_PREPPED) )
4026   {
4027     xa_audio_status = XA_AUDIO_STARTED;
4028     xa_time_now = XA_Read_AV_Time();  /* get new time */
4029     New_Merged_Audio_Output();
4030   }
4031 }
4032 
4033 /********** MMS_Closest_Freq **********************************************
4034  *
4035  * Global Variable Affect:
4036  *   xaULONG xa_audio_hard_buff		must set but not larger than
4037  *					XA_AUDIO_MAX_RING_BUF size
4038  ****************************************************************************/
MMS_Closest_Freq(ifreq)4039 xaULONG MMS_Closest_Freq(ifreq)
4040 xaLONG ifreq;
4041 {
4042   xa_audio_hard_buff = XA_HARD_BUFF_1K;
4043 
4044   /* Query our audio devices to see what sample rates are supported */
4045 
4046   if (xa_audio_hard_type == XA_AUDIO_SIGNED_2ML)
4047   { static int valid[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000, 0};
4048     xaLONG i = 0;
4049     xaLONG best = valid[0];
4050 
4051     while(valid[i])
4052     {
4053       if (xaABS(valid[i] - ifreq) < xaABS(best - ifreq)) best = valid[i];
4054       i++;
4055     }
4056 
4057     return(best);
4058   }
4059   else return(8000);
4060 }
4061 
4062 /* Select the appropriate output port */
4063 
MMS_Set_Output_Port(aud_ports)4064 void MMS_Set_Output_Port(aud_ports)
4065 xaULONG aud_ports;
4066 {
4067   MMRESULT status;
4068   DWORD ports = 0;
4069 /* dummy definitions to support pseudo code below - needs to be fixed - tfm */
4070   int device_type = 0;
4071 #define J300 0
4072 #define BBA 1
4073 
4074   if (aud_ports & XA_AUDIO_PORT_INT &&
4075       device_type == BBA )
4076     ports |= MME_PORTMASK_02;
4077   if (aud_ports & XA_AUDIO_PORT_HEAD) {
4078       if(device_type = BBA)
4079 	ports |= MME_PORTMASK_02;
4080       if(device_type = J300)
4081 	ports |= MME_PORTMASK_01;
4082   }
4083   if (aud_ports & XA_AUDIO_PORT_EXT &&
4084       device_type == J300)
4085     ports |= MME_PORTMASK_02;
4086 
4087   status = waveOutSelectPorts(mms_device_id,ports);
4088   if( status != MMSYSERR_NOERROR ) {
4089       fprintf(stderr,"waveOutSelectPorts failed - status = %d\n", status); }
4090 }
4091 
4092 
4093 
4094 /*************
4095  * flag = 0  turn speaker off
4096  * flag = 1  turn speaker on
4097  * flag = 2  toggle speaker
4098  */
MMS_Speaker_Toggle(flag)4099 void MMS_Speaker_Toggle(flag)
4100 xaULONG flag;
4101 {
4102   DEBUG_LEVEL2 fprintf(stderr,"MMS_Speaker_Toggle\n");
4103 }
4104 
MMS_Headphone_Toggle(flag)4105 void MMS_Headphone_Toggle(flag)
4106 xaULONG flag;
4107 {
4108   DEBUG_LEVEL2 fprintf(stderr,"MMS_Headphone_Toggle\n");
4109 }
4110 
4111 /********** MMS_Adjust_Volume **********************
4112  * Routine for adjusting output volume
4113  *
4114  * NOTE: It isn't really a good idea to do this on a per application
4115  *       basis, particularly at startup where we are going to override
4116  *       the value the user has set up
4117  *	 I've left this disabled for now
4118  *
4119  * POD NOTE: once xanim leaves default volume alone at startup, remember
4120  *           to renable this.
4121  *****/
MMS_Adjust_Volume(volume)4122 void MMS_Adjust_Volume(volume)
4123 xaULONG volume;
4124 {
4125  DWORD vol;
4126  DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_Volume %d\n",volume);
4127 
4128  vol = (0xFFFF * volume) / 100;	/* convert to 16 bit scale */
4129  vol = (vol << 16) | vol;	/* duplicate for left & right channels */
4130 
4131 #ifdef MMS_VOL
4132  waveOutSetVolume(mms_device_id, vol);
4133 #endif
4134 
4135 }
4136 
4137 #endif
4138 /****************************************************************************/
4139 /************************* END OF MMS SPECIFIC ROUTINES *********************/
4140 /****************************************************************************/
4141 
4142 /****************************************************************************/
4143 /**************** NAS SPECIFIC ROUTINES *************************************/
4144 /****************************************************************************/
4145 #ifdef XA_NAS_AUDIO
4146 
4147 /*
4148  * NAS port provided by Bob Phillips,
4149  *	bobp@syl.nj.nec.com
4150  * Adapted from AF port by Tom Levergood
4151  * Wednesday October 26, 1994
4152  *
4153  * Re-written by Greg Renda (greg@ncd.com) 5/10/95
4154  */
4155 
4156 static void		NAS_Audio_Init();
4157 static void		NAS_Audio_Kill();
4158 static void		NAS_Audio_Off();
4159 static void		NAS_Audio_Prep();
4160 static void		NAS_Audio_On();
4161 static void		NAS_Adjust_Volume();
4162 static xaULONG		NAS_Closest_Freq();
4163 static void		NAS_Speaker_Toggle();
4164 static void		NAS_Headphone_Toggle();
4165 
4166 static xaULONG		NAS_pod_flag = 0;
4167 
4168 typedef struct _NASChunk
4169 {
4170     xaUBYTE          *buf;
4171     xaULONG           len,
4172                     offset;
4173     struct _NASChunk *next;
4174 }               NASChunk, *NASChunkPtr;
4175 
4176 typedef struct
4177 {
4178     AuServer       *aud;
4179     AuFlowID        flow;
4180     AuDeviceID      device;
4181     NASChunkPtr     head,
4182                     tail;
4183     xaULONG           bytes;
4184     AuDeviceAttributes *da;
4185     AuEventHandlerRec *handler;
4186     AuBool flowRunning;
4187 }               NASInfo, *NASInfoPtr;
4188 
4189 static NASInfo  nas;
4190 
4191 static AuBool
NAS_Event_Handler(aud,ev,handler)4192 NAS_Event_Handler(aud, ev, handler)
4193 AuServer       *aud;
4194 AuEvent        *ev;
4195 AuEventHandlerRec *handler;
4196 {
4197     NASInfoPtr      np = (NASInfoPtr) handler->data;
4198 
4199     switch (ev->type)
4200     {
4201 	case AuEventTypeElementNotify:
4202 	    {
4203 		AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
4204 
4205 		switch (event->kind)
4206 		{
4207 		    case AuElementNotifyKindLowWater:
4208 			np->bytes += event->num_bytes;
4209 			break;
4210 		    case AuElementNotifyKindState:
4211 			switch (event->cur_state)
4212 			{
4213 			    case AuStatePause:
4214 				if (event->reason != AuReasonUser)
4215 				    np->bytes += event->num_bytes;
4216 				break;
4217 			    case AuStateStop:
4218 				np->flowRunning = AuFalse;
4219 				break;
4220 			}
4221 		}
4222 	    }
4223     }
4224 
4225     return AuTrue;
4226 }
4227 
4228 static void
NAS_Audio_Init()4229 NAS_Audio_Init()
4230 {
4231     char           *errmsg;
4232     int             i;
4233 
4234     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_Init\n");
4235 
4236     if (xa_audio_present != XA_AUDIO_UNK)
4237 	return;
4238 
4239     /* Open connection. */
4240     if (!(nas.aud = AuOpenServer(NULL, 0, NULL, 0, NULL, &errmsg)))
4241     {
4242 	fprintf(stderr, "Could not open connection to NAS audio server.\n");
4243 	fprintf(stderr, "Error is \"%s\".\n", errmsg);
4244 	fprintf(stderr, "Disabling audio service.\n");
4245 	/*
4246 	 * As long as xa_audio_present isn't OK, audio is effectively
4247 	 * disabled
4248 	 */
4249 	/* but might as well really disable it */
4250 	AuFree(errmsg);
4251 	XA_Null_Audio_Setup();
4252 	xa_audio_present = XA_AUDIO_UNK;
4253 	return;
4254     }
4255 
4256     /* look for an output device */
4257     for (i = 0; i < AuServerNumDevices(nas.aud); i++)
4258 	if ((AuDeviceKind(AuServerDevice(nas.aud, i)) ==
4259 	     AuComponentKindPhysicalOutput) &&
4260 	    AuDeviceNumTracks(AuServerDevice(nas.aud, i)) == 1)
4261 	{
4262 	    nas.device = AuDeviceIdentifier(AuServerDevice(nas.aud, i));
4263 	    nas.da = AuServerDevice(nas.aud, i);
4264 	    break;
4265 	}
4266 
4267     if (i == AuServerNumDevices(nas.aud))
4268     {
4269 	fprintf(stderr, "NAS: Couldn't find an appropriate output device\n");
4270 	XA_Null_Audio_Setup();
4271 	xa_audio_present = XA_AUDIO_UNK;
4272 	return;
4273     }
4274 
4275     if (!(nas.flow = AuCreateFlow(nas.aud, NULL)))
4276     {
4277 	fprintf(stderr, "NAS: Couldn't create flow\n");
4278 	XA_Null_Audio_Setup();
4279 	xa_audio_present = XA_AUDIO_UNK;
4280 	return;
4281     }
4282 
4283     nas.handler = AuRegisterEventHandler(nas.aud, AuEventHandlerIDMask, 0,
4284 					 nas.flow, NAS_Event_Handler,
4285 					 (AuPointer) &nas);
4286 
4287     xa_audio_present = XA_AUDIO_OK;
4288     xa_audio_hard_type = XA_AUDIO_SIGNED_2MB;
4289     xa_audio_hard_bps = 2;
4290     xa_audio_hard_chans = 1;
4291     NAS_pod_flag = 0;
4292     Init_Audio_Ring(xa_audio_ring_size,
4293 		    (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps));
4294 }
4295 
4296 static void
NAS_Audio_Kill()4297 NAS_Audio_Kill()
4298 {
4299     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_Kill\n");
4300 
4301     NAS_Audio_Off(0);
4302     xa_audio_present = XA_AUDIO_UNK;
4303 
4304     AuUnregisterEventHandler(nas.aud, nas.handler);
4305     AuCloseServer(nas.aud);
4306 
4307     Kill_Audio_Ring();
4308 }
4309 
4310 
4311 static void
NAS_Audio_Off(flag)4312 NAS_Audio_Off(flag)
4313 xaULONG           flag;
4314 {
4315     NASChunkPtr     p = nas.head,
4316                     next;
4317 
4318     if (NAS_pod_flag) return; NAS_pod_flag = 1; /* POD TEST */
4319 
4320     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_Off\n");
4321 
4322     if (!nas.flowRunning && xa_audio_status != XA_AUDIO_STARTED)
4323 	return;
4324 /* POD new */
4325     xa_audio_status = XA_AUDIO_STOPPED;
4326 
4327     AuStopFlow(nas.aud, nas.flow, NULL);
4328 
4329     while (nas.flowRunning == AuTrue) AuHandleEvents(nas.aud);
4330 
4331     while (p)
4332     {
4333 	next = p->next;
4334 	free(p->buf);
4335 	free(p);
4336 	p = next;
4337     }
4338 
4339     nas.head = nas.tail = NULL;
4340 
4341     /* SET FLAG TO STOP OUTPUT ROUTINE */
4342 /* POD Was
4343     xa_audio_status = XA_AUDIO_STOPPED;
4344 */
4345 
4346     xa_time_audio = -1;
4347     xa_audio_flushed = 0;
4348 
4349     NAS_pod_flag = 0; /* POD TEST */
4350 }
4351 
4352 static void
NAS_Audio_Prep()4353 NAS_Audio_Prep()
4354 {
4355     if (NAS_pod_flag) return; NAS_pod_flag = 1; /* POD TEST */
4356 
4357     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_Prep \n");
4358 
4359     if ( (xa_audio_status == XA_AUDIO_STARTED) ||
4360 	 (xa_audio_present != XA_AUDIO_OK) || (!xa_snd_cur) )
4361 	return;
4362 
4363     if (nas.flowRunning == AuTrue) NAS_Audio_Off(0);
4364 
4365 #define NASBufSize 30000
4366     /* Change Frequency If necessary */
4367     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
4368     {
4369 	AuElement       elements[3];
4370 
4371 	AuMakeElementImportClient(&elements[0], xa_snd_cur->hfreq,
4372 				  AuFormatLinearSigned16MSB,
4373 				  1, AuTrue, NASBufSize,
4374 				  NASBufSize / 4 * 3, 0, NULL);
4375 	AuMakeElementMultiplyConstant(&elements[1], 0,
4376 				      AuFixedPointFromFraction(100, 100));
4377 	AuMakeElementExportDevice(&elements[2], 1, nas.device,
4378 				  xa_snd_cur->hfreq, AuUnlimitedSamples,
4379 				  0, NULL);
4380 
4381 	AuSetElements(nas.aud, nas.flow, AuTrue, 3, elements, NULL);
4382 
4383 	xa_audio_hard_freq = xa_snd_cur->hfreq;
4384     }
4385 
4386     nas.bytes = 0;
4387     AuStartFlow(nas.aud, nas.flow, NULL);
4388     nas.flowRunning = AuTrue;
4389 
4390     /* xa_snd_cur gets changes in Update_Ring() */
4391     /* FINE TUNED from 4 to 20 */
4392     xa_out_time = 250;			       /* keep audio fed XXms ahead
4393 					        * of video - could be 500 */
4394     xa_out_init = xa_audio_ring_size - 1;
4395     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
4396     if (xa_interval_time == 0) xa_interval_time = 1;
4397 
4398     XA_Flush_Ring();
4399     XA_Update_Ring(1000);
4400     xa_audio_status = XA_AUDIO_PREPPED;
4401     NAS_pod_flag = 0;
4402 }
4403 
4404 /****-------------------------------------------------------------------****
4405  *
4406  ****-------------------------------------------------------------------****/
NAS_Audio_On()4407 void NAS_Audio_On()
4408 {
4409   if (   (xa_snd_cur)
4410       && (xa_audio_present == XA_AUDIO_OK)
4411       && (xa_audio_status == XA_AUDIO_PREPPED) )
4412   {
4413     xa_audio_status = XA_AUDIO_STARTED;
4414     xa_time_now = XA_Read_AV_Time();  /* get new time */
4415     New_Merged_Audio_Output();
4416   }
4417 }
4418 
4419 static void
NAS_Toggle_OutputMode(flag,mode)4420 NAS_Toggle_OutputMode(flag, mode)
4421 xaULONG flag, mode;
4422 {
4423     if (!(AuDeviceChangableMask(nas.da) & AuCompDeviceOutputModeMask))
4424 	return;
4425 
4426     switch(flag)
4427     {
4428 	case 0:
4429 	    AuDeviceOutputMode(nas.da) &= ~mode;
4430 	    break;
4431 	case 1:
4432 	    AuDeviceOutputMode(nas.da) |= mode;
4433 	    break;
4434   	case 2:
4435 	    AuDeviceOutputMode(nas.da) ^= mode;
4436 	    break;
4437     }
4438 
4439     AuSetDeviceAttributes(nas.aud, AuDeviceIdentifier(nas.da),
4440 			  AuCompDeviceOutputModeMask, nas.da, NULL);
4441     AuFlush(nas.aud);
4442 }
4443 
4444 /*************
4445  * flag = 0  turn speaker off
4446  * flag = 1  turn speaker on
4447  * flag = 2  toggle speaker
4448  */
4449 static void
NAS_Speaker_Toggle(flag)4450 NAS_Speaker_Toggle(flag)
4451 xaULONG           flag;
4452 {
4453     DEBUG_LEVEL2    fprintf(stdout, "NAS_Speaker_Toggle\n");
4454     NAS_Toggle_OutputMode(flag, AuDeviceOutputModeSpeaker);
4455 }
4456 
4457 static void
NAS_Headphone_Toggle(flag)4458 NAS_Headphone_Toggle(flag)
4459 xaULONG           flag;
4460 {
4461     DEBUG_LEVEL2    fprintf(stdout, "NAS_Headphone_Toggle\n");
4462     NAS_Toggle_OutputMode(flag, AuDeviceOutputModeHeadphone);
4463 }
4464 
4465 
4466 /********** NAS_Adjust_Volume **********************
4467  * Routine for Adjusting Volume on NAS
4468  *
4469  *****/
4470 static void
NAS_Adjust_Volume(volume)4471 NAS_Adjust_Volume(volume)
4472 xaULONG           volume;
4473 {
4474     AuElementParameters parms;
4475 
4476     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_Volume %d\n", volume);
4477     parms.flow = nas.flow;
4478     parms.element_num = 1;
4479     parms.num_parameters = AuParmsMultiplyConstant;
4480     parms.parameters[AuParmsMultiplyConstantConstant] =
4481 	AuFixedPointFromFraction(volume, 100);
4482     AuSetElementParameters(nas.aud, 1, &parms, NULL);
4483     AuFlush(nas.aud);
4484 }
4485 
4486 /********** NAS_Closest_Freq **********************
4487  *
4488  * Global Variable Affect:
4489  *   xaULONG xa_audio_hard_buff		must set but not larger than
4490  *					XA_AUDIO_MAX_RING_BUF size
4491  */
4492 static xaULONG
NAS_Closest_Freq(ifreq)4493 NAS_Closest_Freq(ifreq)
4494 xaLONG            ifreq;
4495 {
4496     xa_audio_hard_buff = XA_AUDIO_MAX_RING_BUFF;
4497     return ifreq;
4498 }
4499 
4500 static void
NAS_Write_Data(buf,len)4501 NAS_Write_Data(buf, len)
4502 xaUBYTE          *buf;
4503 xaULONG           len;
4504 {
4505     NASChunkPtr     p;
4506 
4507     if (!(p = (NASChunkPtr) malloc(sizeof(NASChunk))))
4508 	return;
4509 
4510     if (!(p->buf = (xaUBYTE *) malloc(len)))
4511     {
4512 	free(p);
4513 	return;
4514     }
4515 
4516     memcpy((char *) p->buf, (char *) buf, (int) len);
4517     p->len = len;
4518     p->offset = 0;
4519     p->next = NULL;
4520 
4521     if (nas.tail)
4522     {
4523 	nas.tail->next = p;
4524 	nas.tail = p;
4525     }
4526     else
4527 	nas.head = nas.tail = p;
4528 
4529     AuHandleEvents(nas.aud);
4530 
4531     while (nas.head && nas.bytes && (xa_audio_status == XA_AUDIO_STARTED) )
4532     {
4533 	int             n = xaMIN(nas.bytes, nas.head->len);
4534 	AuWriteElement(nas.aud, nas.flow, 0, n,
4535 		       nas.head->buf + nas.head->offset, AuFalse, NULL);
4536 
4537 	nas.bytes -= n;
4538 	nas.head->len -= n;
4539 	nas.head->offset += n;
4540 
4541 	if (!nas.head->len)
4542 	{
4543 	    NASChunkPtr     next = nas.head->next;
4544 
4545 	    free(nas.head->buf);
4546 	    free(nas.head);
4547 
4548 	    if (!(nas.head = next))
4549 		nas.tail = nas.head;
4550 	}
4551 
4552 	AuHandleEvents(nas.aud);
4553     }
4554 }
4555 
4556 void
XA_Audio_Setup()4557 XA_Audio_Setup()
4558 {
4559     DEBUG_LEVEL2    fprintf(stdout, "XA_Audio_Setup()\n");
4560     XA_Audio_Init = NAS_Audio_Init;
4561     XA_Audio_Kill = NAS_Audio_Kill;
4562     XA_Audio_Off = NAS_Audio_Off;
4563     XA_Audio_Prep = NAS_Audio_Prep;
4564     XA_Audio_On = NAS_Audio_On;
4565     XA_Closest_Freq = NAS_Closest_Freq;
4566     XA_Set_Output_Port = (void *) (0);
4567     XA_Speaker_Tog = NAS_Speaker_Toggle;
4568     XA_Headphone_Tog = NAS_Headphone_Toggle;
4569     XA_LineOut_Tog = NAS_Headphone_Toggle;
4570     XA_Adjust_Volume = NAS_Adjust_Volume;
4571 
4572     xa_snd_cur = 0;
4573     xa_audio_present = XA_AUDIO_UNK;
4574     xa_audio_status = XA_AUDIO_STOPPED;
4575     xa_audio_ring_size = 8;
4576 }
4577 
4578 #endif
4579 /****************************************************************************/
4580 /******************* END OF NAS SPECIFIC ROUTINES ***************************/
4581 /****************************************************************************/
4582 
4583 
4584 /****************************************************************************/
4585 /**************** NetBSD SPECIFIC ROUTINES **********************************/
4586 /****************************************************************************/
4587 
4588 /*
4589  * NetBSD port provided by Roland C Dowdeswell
4590  * roland@imrryr.org
4591  * Heavily stolen from the Sparc port (like the others)
4592  * Tuesday 9/May 1995 -- very early -- still dark.
4593  */
4594 
4595 #ifdef XA_NetBSD_AUDIO
4596 
4597 void  NetBSD_Audio_Init();
4598 void  NetBSD_Audio_Kill();
4599 void  NetBSD_Audio_Off();
4600 void  NetBSD_Audio_Prep();
4601 void  NetBSD_Audio_On();
4602 void  NetBSD_Adjust_Volume();
4603 xaULONG NetBSD_Closest_Freq();
4604 void NetBSD_Set_Output_Port();
4605 void NetBSD_Speaker_Toggle();
4606 void NetBSD_Headphone_Toggle();
4607 
4608 #define NetBSD_MAX_VOL AUDIO_MAX_GAIN
4609 #define NetBSD_MIN_VOL AUDIO_MIN_GAIN
4610 
4611 static int devAudio;
4612 
4613 /********** XA_Audio_Setup **********************
4614  *
4615  * Also defines NetBSD Specific variables.
4616  *
4617  *****/
XA_Audio_Setup()4618 void XA_Audio_Setup()
4619 {
4620   XA_Audio_Init		= NetBSD_Audio_Init;
4621   XA_Audio_Kill		= NetBSD_Audio_Kill;
4622   XA_Audio_Off		= NetBSD_Audio_Off;
4623   XA_Audio_Prep		= NetBSD_Audio_Prep;
4624   XA_Audio_On		= NetBSD_Audio_On;
4625   XA_Closest_Freq	= NetBSD_Closest_Freq;
4626   XA_Set_Output_Port	= NetBSD_Set_Output_Port;
4627   XA_Speaker_Tog	= NetBSD_Speaker_Toggle;
4628   XA_Headphone_Tog	= NetBSD_Headphone_Toggle;
4629   XA_LineOut_Tog	= NetBSD_Headphone_Toggle;
4630   XA_Adjust_Volume	= NetBSD_Adjust_Volume;
4631 
4632   xa_snd_cur = 0;
4633   xa_audio_present = XA_AUDIO_UNK;
4634   xa_audio_status  = XA_AUDIO_STOPPED;
4635   xa_audio_ring_size  = 8;
4636 }
4637 
4638 
4639 /********** NetBSD_Audio_Init **********************
4640  * Open /dev/audio and NetBSD.
4641  *
4642  *****/
NetBSD_Audio_Init()4643 void NetBSD_Audio_Init()
4644 { int ret;
4645   int type;
4646   audio_info_t a_info;
4647   DEBUG_LEVEL2 fprintf(stderr,"NetBSD_Audio_Init\n");
4648   if (xa_audio_present != XA_AUDIO_UNK) return;
4649   devAudio = open("/dev/audio", O_WRONLY | O_NDELAY);
4650   if (devAudio == -1)
4651   {
4652     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
4653     else fprintf(stderr,"Audio_Init: Error opening audio device. - ");
4654     fprintf(stderr,"Will continue without audio\n");
4655     xa_audio_present = XA_AUDIO_ERR;
4656     return;
4657   }
4658 
4659   DEBUG_LEVEL1 fprintf(stderr,"NetBSD AUDIO\n");
4660 
4661   AUDIO_INITINFO(&a_info);
4662   a_info.blocksize = 1024;
4663   ioctl(devAudio, AUDIO_SETINFO, &a_info);
4664   AUDIO_INITINFO(&a_info);
4665 
4666   a_info.mode = AUMODE_PLAY | AUMODE_PLAY_ALL;
4667   ioctl(devAudio, AUDIO_SETINFO, &a_info);
4668 #ifdef AUDIO_ENCODING_SLINEAR
4669   /* Use new encoding names */
4670   AUDIO_INITINFO(&a_info);
4671   a_info.play.encoding = AUDIO_ENCODING_SLINEAR;
4672   a_info.play.precision = 16;
4673   if ( ioctl(devAudio, AUDIO_SETINFO, &a_info) < 0)
4674   {
4675     AUDIO_INITINFO(&a_info);
4676     a_info.play.encoding = AUDIO_ENCODING_ULINEAR;
4677     a_info.play.precision = 8;
4678     ioctl(devAudio, AUDIO_SETINFO, &a_info);
4679   }
4680 #else
4681   AUDIO_INITINFO(&a_info);
4682   a_info.play.encoding = AUDIO_ENCODING_PCM16;
4683   a_info.play.precision = 16;
4684   if (ioctl(devAudio, AUDIO_SETINFO, &a_info) < 0)
4685   {
4686     AUDIO_INITINFO(&a_info);
4687     a_info.play.encoding = AUDIO_ENCODING_PCM;
4688     a_info.play.precision = 8;
4689     ioctl(devAudio, AUDIO_SETINFO, &a_info);
4690   }
4691 #endif
4692   AUDIO_INITINFO(&a_info);
4693   a_info.play.channels = /*2*/1;  /* Eventually test for and support stereo */
4694   ioctl(devAudio, AUDIO_SETINFO, &a_info);
4695 
4696   AUDIO_INITINFO(&a_info);
4697   a_info.play.sample_rate = 11025;   /* this is changed later */
4698   ioctl(devAudio, AUDIO_SETINFO, &a_info);
4699   ioctl(devAudio, AUDIO_GETINFO, &a_info);
4700 
4701 /* Eventually support stereo
4702   if (a_info.play.channels == 2)
4703     if (a_info.play.precision == 8)
4704       xa_audio_hard_type = XA_AUDIO_LINEAR_1S;
4705     else
4706       xa_audio_hard_type = XA_AUDIO_SIGNED_2SL;
4707   else
4708 */
4709     if (a_info.play.precision == 8)
4710       xa_audio_hard_type = XA_AUDIO_LINEAR_1M;
4711     else
4712       xa_audio_hard_type = XA_AUDIO_SIGNED_2ML;
4713 
4714   xa_audio_hard_freq  = a_info.play.sample_rate;
4715   xa_audio_hard_buff  = a_info.blocksize;
4716 
4717 	/* only precision 8 and 16 are supported. Fail if otherwise?? */
4718   xa_audio_hard_bps   = (a_info.play.precision==8)?1:2;
4719   xa_audio_hard_chans = a_info.play.channels;
4720   Gen_uLaw_2_Signed();
4721   Gen_Signed_2_uLaw();
4722 
4723   xa_interval_id = 0;
4724   xa_audio_present = XA_AUDIO_OK;
4725   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
4726   Init_Audio_Ring(xa_audio_ring_size,
4727 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
4728 }
4729 
4730 /********** NetBSD_Audio_Kill **********************
4731  * Close /dev/audio.
4732  *
4733  *****/
NetBSD_Audio_Kill()4734 void NetBSD_Audio_Kill()
4735 {
4736   /* TURN AUDIO OFF */
4737   NetBSD_Audio_Off(0);
4738   xa_audio_present = XA_AUDIO_UNK;
4739   /* SHUT THINGS DOWN  */
4740   close(devAudio);
4741   Kill_Audio_Ring();
4742 }
4743 
4744 /********** NetBSD_Audio_Off **********************
4745  * Stop Audio Stream
4746  *
4747  *****/
NetBSD_Audio_Off(flag)4748 void NetBSD_Audio_Off(flag)
4749 xaULONG flag;
4750 { /* long ret; */
4751 
4752   DEBUG_LEVEL1 fprintf(stderr,"NetBSD_Audio_Off\n");
4753   if (xa_audio_status != XA_AUDIO_STARTED) return;
4754 
4755   /* SET FLAG TO STOP OUTPUT ROUTINE */
4756   xa_audio_status = XA_AUDIO_STOPPED;
4757 
4758   /* TURN OFF SOUND ??? */
4759   NetBSD_Adjust_Volume(XA_AUDIO_MINVOL);
4760 
4761   /* FLUSH AUDIO DEVICE */ /* NOT! */
4762 /*
4763   ret = ioctl(devAudio, AUDIO_FLUSH, NULL);
4764   if (ret == -1) fprintf(stderr,"NetBSD Audio: off flush err %d\n",errno);
4765 */
4766 
4767   xa_time_audio = -1;
4768   xa_audio_flushed = 0;
4769 
4770   /* FLUSH AUDIO DEVICE AGAIN */ /* NOT! */
4771 /*
4772   ret = ioctl(devAudio, AUDIO_FLUSH, NULL);
4773   if (ret == -1) fprintf(stderr,"NetBSD Audio: off flush err %d\n",errno);
4774 */
4775 
4776   /* RESTORE ORIGINAL VOLUME */
4777   if (XAAUD->mute != xaTRUE) NetBSD_Adjust_Volume(XAAUD->volume);
4778 }
4779 
4780 /********** NetBSD_Audio_Prep **********************
4781  * Turn On Audio Stream.
4782  *
4783  *****/
NetBSD_Audio_Prep()4784 void NetBSD_Audio_Prep()
4785 {
4786   DEBUG_LEVEL2
4787   {
4788     fprintf(stderr,"NetBSD_Audio_Prep \n");
4789   }
4790   if (xa_audio_status == XA_AUDIO_STARTED) return;
4791   else if (xa_audio_present != XA_AUDIO_OK) return;
4792 
4793   else if (xa_snd_cur)
4794   { int ret;
4795 
4796     /* CHANGE FREQUENCY IF NEEDED */
4797     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
4798     { audio_info_t a_info;
4799       AUDIO_INITINFO(&a_info);
4800       a_info.play.sample_rate = xa_snd_cur->hfreq;
4801       ret = ioctl(devAudio, AUDIO_SETINFO, &a_info);
4802       if (ret == -1) fprintf(stderr,"audio setfreq: freq %x errno %d\n",
4803 						xa_snd_cur->hfreq, errno);
4804       xa_audio_hard_freq = xa_snd_cur->hfreq;
4805     }
4806 
4807     /* xa_snd_cur gets changes in Update_Ring() */
4808     xa_out_time = 100;  /* keep audio fed 500ms ahead of video */  /* was 500, changed it to 100 - rcd */
4809     xa_out_init = xa_audio_ring_size - 1;
4810     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
4811     if (xa_interval_time == 0) xa_interval_time = 1;
4812 
4813     XA_Flush_Ring();
4814     XA_Update_Ring(1000);
4815     xa_audio_status = XA_AUDIO_PREPPED;
4816   }
4817 }
4818 
4819 /****-------------------------------------------------------------------****
4820  *
4821  ****-------------------------------------------------------------------****/
NetBSD_Audio_On()4822 void NetBSD_Audio_On()
4823 {
4824   if (   (xa_snd_cur)
4825       && (xa_audio_present == XA_AUDIO_OK)
4826       && (xa_audio_status == XA_AUDIO_PREPPED) )
4827   {
4828     xa_audio_status = XA_AUDIO_STARTED;
4829     xa_time_now = XA_Read_AV_Time();  /* get new time */
4830     New_Merged_Audio_Output();
4831   }
4832 }
4833 
4834 
4835 /********** NetBSD_Closest_Freq **********************************************
4836  *
4837  * Global Variable Affect:
4838  *   xaULONG xa_audio_hard_buff		must set but not larger than
4839  *					XA_AUDIO_MAX_RING_BUF size
4840  ****************************************************************************/
NetBSD_Closest_Freq(ifreq)4841 xaULONG NetBSD_Closest_Freq(ifreq)
4842 xaLONG ifreq;
4843 { audio_info_t a_info;
4844 
4845   AUDIO_INITINFO(&a_info);
4846   a_info.play.sample_rate = ifreq;
4847   ioctl(devAudio, AUDIO_SETINFO, &a_info);
4848 
4849   ioctl(devAudio, AUDIO_GETINFO, &a_info);
4850 
4851   xa_audio_hard_buff  = a_info.blocksize;
4852   return (a_info.play.sample_rate);
4853 }
4854 
4855 
4856 /* Eventually merge everything to one */
NetBSD_Set_Output_Port(aud_ports)4857 void NetBSD_Set_Output_Port(aud_ports)
4858 xaULONG aud_ports;
4859 {
4860 /* Commented out for now ;-) */
4861 /*
4862 audio_info_t a_info;
4863   xaLONG ret;
4864   xaULONG NetBSD_ports = 0;
4865   if (aud_ports & XA_AUDIO_PORT_INT)  NetBSD_ports |= AUDIO_SPEAKER;
4866   if (aud_ports & XA_AUDIO_PORT_HEAD) NetBSD_ports |= AUDIO_HEADPHONE;
4867   if (aud_ports & XA_AUDIO_PORT_EXT)  NetBSD_ports |= AUDIO_LINE_OUT;
4868   AUDIO_INITINFO(&a_info);
4869   a_info.play.port = NetBSD_ports;
4870   ret = ioctl(devAudio, AUDIO_SETINFO, &a_info);
4871   if (ret < 0) fprintf(stderr,"Audio: couldn't set speaker port %d\n",errno);
4872 */
4873 }
4874 
4875 /************* NetBSD_Speaker_Toggle *****************************************
4876  *
4877  * flag = 0  turn speaker off
4878  * flag = 1  turn speaker on
4879  * flag = 2  toggle speaker
4880  ****************************************************************************/
NetBSD_Speaker_Toggle(flag)4881 void NetBSD_Speaker_Toggle(flag)
4882 xaULONG flag;
4883 {
4884   switch(flag)
4885   {
4886     case  0: XAAUD->port &= ~XA_AUDIO_PORT_INT; break;
4887     case  1: XAAUD->port |=  XA_AUDIO_PORT_INT; break;
4888     default:  /* mutually exclusive set for now - never turn off */
4889     { if ( !(XAAUD->port & XA_AUDIO_PORT_INT))
4890 		XAAUD->port = XA_AUDIO_PORT_INT;
4891     }
4892   }
4893   NetBSD_Set_Output_Port(XAAUD->port);
4894 }
4895 
4896 /************* NetBSD_Headphone_Toggle *****************************************
4897  *
4898  * flag = 0  turn headphones off
4899  * flag = 1  turn headphones on
4900  * flag = 2  toggle headphones
4901  ****************************************************************************/
NetBSD_Headphone_Toggle(flag)4902 void NetBSD_Headphone_Toggle(flag)
4903 xaULONG flag;
4904 {
4905   switch(flag)
4906   {
4907     case  0: XAAUD->port &= ~XA_AUDIO_PORT_HEAD; break;
4908     case  1: XAAUD->port |=  XA_AUDIO_PORT_HEAD; break;
4909     default:  /* mutually exclusive set for now - never turn off */
4910     { if ( !(XAAUD->port & XA_AUDIO_PORT_HEAD))
4911 		XAAUD->port = XA_AUDIO_PORT_HEAD;
4912     }
4913   }
4914   NetBSD_Set_Output_Port(XAAUD->port);
4915 }
4916 
4917 
4918 /********** NetBSD_Adjust_Volume **********************
4919  * Routine for Adjusting Volume on NetBSD
4920  *
4921  * Volume is in the range [0,XA_AUDIO_MAXVOL]
4922  ****************************************************************************/
NetBSD_Adjust_Volume(volume)4923 void NetBSD_Adjust_Volume(volume)
4924 xaULONG volume;
4925 { audio_info_t a_info;
4926 
4927   AUDIO_INITINFO(&a_info);
4928   a_info.play.gain = NetBSD_MIN_VOL +
4929 	((volume * (NetBSD_MAX_VOL - NetBSD_MIN_VOL)) / XA_AUDIO_MAXVOL);
4930   if (a_info.play.gain > NetBSD_MAX_VOL) a_info.play.gain = NetBSD_MAX_VOL;
4931   ioctl(devAudio, AUDIO_SETINFO, &a_info);
4932 
4933 }
4934 #endif
4935 /****************************************************************************/
4936 /******************* END OF NetBSD SPECIFIC ROUTINES ************************/
4937 /****************************************************************************/
4938 
4939  /****************************************************************************/
4940 /**************** TOWNS SPECIFIC ROUTINES ***********************************/
4941 /****************************************************************************/
4942 #ifdef XA_TOWNS_AUDIO
4943 
4944 /*
4945  * FUJITSU FM-TOWNS  port provided by Osamu KURATI,
4946  *	kurati@bigfoot.com
4947  * Heavily stolen from the Sparc port
4948  * Sun Sep. 2, 1997
4949  *
4950  */
4951 
4952 static int auTownsSamplingRate[12]={
4953 	48000,44100,32000,22050,
4954 	19200,16000,11025, 9600,
4955 	 8000, 5512,24000,12000
4956 	};
4957 
4958 void  Towns_Audio_Init();
4959 void  Towns_Audio_Kill();
4960 void  Towns_Audio_Off();
4961 void  Towns_Audio_Prep();
4962 void  Towns_Audio_On();
4963 void  Towns_Adjust_Volume();
4964 xaULONG Towns_Closest_Freq();
4965 void Towns_Set_Output_Port();
4966 void Towns_Speaker_Toggle();
4967 void Towns_Headphone_Toggle();
4968 
4969 
4970 static int devAudio;
4971 
4972 
4973 /********** XA_Audio_Setup **********************
4974  *
4975  * Also defines Towns Specific variables.
4976  *
4977  *****/
XA_Audio_Setup()4978 void XA_Audio_Setup()
4979 {
4980 
4981   XA_Audio_Init		= Towns_Audio_Init;
4982   XA_Audio_Kill		= Towns_Audio_Kill;
4983   XA_Audio_Off		= Towns_Audio_Off;
4984   XA_Audio_Prep		= Towns_Audio_Prep;
4985   XA_Audio_On		= Towns_Audio_On;
4986   XA_Closest_Freq	= Towns_Closest_Freq;
4987   XA_Set_Output_Port	= (void *)(0);
4988   XA_Speaker_Tog	= Towns_Speaker_Toggle;
4989   XA_Headphone_Tog	= Towns_Headphone_Toggle;
4990   XA_LineOut_Tog	= Towns_Headphone_Toggle;
4991   XA_Adjust_Volume	= Towns_Adjust_Volume;
4992 
4993   xa_snd_cur = 0;
4994   xa_audio_present = XA_AUDIO_UNK;
4995   xa_audio_status  = XA_AUDIO_STOPPED;
4996   xa_audio_ring_size  = 8;
4997 }
4998 
4999 
5000 /********** Towns_Audio_Init **********************
5001  * Open /dev/pcm16 for Towns's.
5002  *
5003  *****/
Towns_Audio_Init()5004 void Towns_Audio_Init()
5005 { int ret;
5006   int type;
5007 
5008   DEBUG_LEVEL2 fprintf(stderr,"Towns_Audio_Init\n");
5009   if (xa_audio_present != XA_AUDIO_UNK) return;
5010   devAudio = open("/dev/pcm16",O_WRONLY | O_NDELAY);
5011   if (devAudio == -1)
5012   {
5013     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
5014     else fprintf(stderr,"Audio_Init: Error %x opening audio device. - ",errno);
5015     fprintf(stderr,"Will continue without audio\n");
5016     xa_audio_present = XA_AUDIO_ERR;
5017     return;
5018   }
5019 
5020     ioctl(devAudio,PCM16_CTL_SNDWAV,0);  /* select  wav */
5021 
5022     /***** 8000 Hz : cnt == 8 *****/
5023     /***** 22050 Hz : cnt == 3 *****/
5024     ioctl(devAudio,PCM16_CTL_RATE,3); /* sampling rate  set */
5025 
5026     /***** monoral *****/
5027     ioctl(devAudio,PCM16_CTL_STMONO,0); /* monoral=0 */
5028 
5029     ioctl(devAudio,PCM16_CTL_BITS,1);   /* 16bit data */
5030 
5031     xa_audio_hard_freq  = 22050;
5032     xa_audio_hard_type  = XA_AUDIO_SIGNED_2ML;
5033     xa_audio_hard_buff  = XA_HARD_BUFF_1K;             /* default buffer size */
5034     xa_audio_hard_bps   = 2;
5035     xa_audio_hard_chans = 1;
5036 
5037   xa_interval_id = 0;
5038   xa_audio_present = XA_AUDIO_OK;
5039   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
5040   Init_Audio_Ring(xa_audio_ring_size,
5041 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
5042 }
5043 
5044 /********** Towns_Audio_Kill **********************
5045  * Close /dev/pcm16
5046  *
5047  *****/
Towns_Audio_Kill()5048 void Towns_Audio_Kill()
5049 {
5050   /* TURN AUDIO OFF */
5051   Towns_Audio_Off(0);
5052   xa_audio_present = XA_AUDIO_UNK;
5053   /* SHUT THINGS DOWN  */
5054   close(devAudio);
5055   Kill_Audio_Ring();
5056 }
5057 
5058 /********** Towns_Audio_Off **********************
5059  * Stop Audio Stream
5060  *
5061  *****/
Towns_Audio_Off(flag)5062 void Towns_Audio_Off(flag)
5063 xaULONG flag;
5064 { long ret;
5065 
5066   if (xa_audio_status != XA_AUDIO_STARTED) return;
5067 
5068   /* SET FLAG TO STOP OUTPUT ROUTINE */
5069   xa_audio_status = XA_AUDIO_STOPPED;
5070 
5071   /* TURN OFF SOUND ??? */
5072   /*
5073   Towns_Adjust_Volume(XA_AUDIO_MINVOL);
5074   */
5075 
5076   /* FLUSH AUDIO DEVICE */
5077   /***** none *****/
5078 
5079 
5080   xa_time_audio = -1;
5081   xa_audio_flushed = 0;
5082 
5083   /* FLUSH AUDIO DEVICE AGAIN */
5084   /***** none *****/
5085 
5086   /* RESTORE ORIGINAL VOLUME */
5087   /*
5088   if (XAAUD->mute != xaTRUE) Towns_Adjust_Volume(XAAUD->volume);
5089   */
5090 }
5091 
5092 /********** Towns_Audio_Prep **********************
5093  * Turn On Audio Stream.
5094  *
5095  *****/
Towns_Audio_Prep()5096 void Towns_Audio_Prep()
5097 {
5098   DEBUG_LEVEL2
5099   {
5100     fprintf(stderr,"Towns_Audio_Prep \n");
5101   }
5102   if (xa_audio_status == XA_AUDIO_STARTED) return;
5103   else if (xa_audio_present != XA_AUDIO_OK) return;
5104   else if (xa_snd_cur)
5105   { int ret;
5106 
5107     /* CHANGE FREQUENCY IF NEEDED */
5108     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
5109     {
5110        int i_;
5111 
5112        ret = -1;
5113        for(i_=0; i_<12; i_++){
5114 	  if (xa_snd_cur->hfreq == auTownsSamplingRate[i_]) {
5115 	     ret = i_;
5116 	  }
5117        }
5118        if (ret == -1) fprintf(stderr,"audio setfreq: freq %x can't set\n",
5119 			      xa_snd_cur->hfreq);
5120        xa_audio_hard_freq = xa_snd_cur->hfreq;
5121     }
5122 
5123     /* xa_snd_cur gets changes in Update_Ring() */
5124     xa_out_time = 500;  /* keep audio fed 500ms ahead of video */
5125     xa_out_init = xa_audio_ring_size - 1;
5126     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
5127     if (xa_interval_time == 0) xa_interval_time = 1;
5128 
5129     XA_Flush_Ring();
5130     XA_Update_Ring(1000);
5131     xa_audio_status = XA_AUDIO_PREPPED;
5132   }
5133 }
5134 
5135 /****-------------------------------------------------------------------****
5136  *
5137  ****-------------------------------------------------------------------****/
Towns_Audio_On()5138 void Towns_Audio_On()
5139 {
5140   if (   (xa_snd_cur)
5141       && (xa_audio_present == XA_AUDIO_OK)
5142       && (xa_audio_status == XA_AUDIO_PREPPED) )
5143   {
5144     xa_audio_status = XA_AUDIO_STARTED;
5145     xa_time_now = XA_Read_AV_Time();  /* get new time */
5146     New_Merged_Audio_Output();
5147   }
5148 }
5149 
5150 
5151 /********** Towns_Closest_Freq **********************************************
5152  *
5153  * Global Variable Affect:
5154  *   xaULONG xa_audio_hard_buff		must set but not larger than
5155  *					XA_AUDIO_MAX_RING_BUF size
5156  ****************************************************************************/
Towns_Closest_Freq(ifreq)5157 xaULONG Towns_Closest_Freq(ifreq)
5158 xaLONG ifreq;
5159 {
5160 
5161    static int valid[] = {5512, 8000, 9600,
5162 			  11025, 12000, 16000, 19200,
5163 			  22050, 24000, 32000, 44100, 48000,
5164 			  0};
5165 
5166     xaLONG i = 0;
5167     xaLONG best = 22050;
5168 
5169     xa_audio_hard_buff = XA_HARD_BUFF_1K;
5170     while(valid[i])
5171     {
5172       if (xaABS(valid[i] - ifreq) < xaABS(best - ifreq)) best = valid[i];
5173       i++;
5174     }
5175     return(best);
5176 }
5177 
5178 /************* Towns_Speaker_Toggle *****************************************
5179  *
5180  * flag = 0  turn speaker off
5181  * flag = 1  turn speaker on
5182  * flag = 2  toggle speaker
5183  ****************************************************************************/
Towns_Speaker_Toggle(flag)5184 void Towns_Speaker_Toggle(flag)
5185 xaULONG flag;
5186 {
5187    return;
5188 }
5189 
5190 /************* Towns_Headphone_Toggle *****************************************
5191  *
5192  * flag = 0  turn headphones off
5193  * flag = 1  turn headphones on
5194  * flag = 2  toggle headphones
5195  ****************************************************************************/
Towns_Headphone_Toggle(flag)5196 void Towns_Headphone_Toggle(flag)
5197 xaULONG flag;
5198 {
5199    return;
5200 }
5201 
5202 
5203 /********** Towns_Adjust_Volume **********************
5204  * Routine for Adjusting Volume on a Towns
5205  *
5206  * Volume is in the range [0,XA_AUDIO_MAXVOL]
5207  ****************************************************************************/
Towns_Adjust_Volume(volume)5208 void Towns_Adjust_Volume(volume)
5209 xaULONG volume;
5210 {
5211    return;
5212 }
5213 #endif
5214 /****************************************************************************/
5215 /******************* END OF TOWNS SPECIFIC ROUTINES *************************/
5216 /****************************************************************************/
5217 
5218 /****************************************************************************/
5219 /**************** TOWNS 8 bit SPECIFIC ROUTINES *****************************/
5220 /****************************************************************************/
5221 #ifdef XA_TOWNS8_AUDIO
5222 
5223 /*
5224  * FUJITSU FM-TOWNS  port provided by Osamu KURATI,
5225  *	kurati@bigfoot.com
5226  * Heavily stolen from the Sparc port
5227  * Sun Sep. 2, 1997
5228  *
5229  */
5230 
5231 void  Towns8_Audio_Init();
5232 void  Towns8_Audio_Kill();
5233 void  Towns8_Audio_Off();
5234 void  Towns8_Audio_Prep();
5235 void  Towns8_Audio_On();
5236 void  Towns8_Adjust_Volume();
5237 xaULONG Towns8_Closest_Freq();
5238 void Towns8_Set_Output_Port();
5239 void Towns8_Speaker_Toggle();
5240 void Towns8_Headphone_Toggle();
5241 
5242 
5243 static int devAudio;
5244 
5245 
5246 /********** XA_Audio_Setup **********************
5247  *
5248  * Also defines Towns8 Specific variables.
5249  *
5250  *****/
XA_Audio_Setup()5251 void XA_Audio_Setup()
5252 {
5253 
5254   XA_Audio_Init		= Towns8_Audio_Init;
5255   XA_Audio_Kill		= Towns8_Audio_Kill;
5256   XA_Audio_Off		= Towns8_Audio_Off;
5257   XA_Audio_Prep		= Towns8_Audio_Prep;
5258   XA_Audio_On		= Towns8_Audio_On;
5259   XA_Closest_Freq	= Towns8_Closest_Freq;
5260   XA_Set_Output_Port	= (void *)(0);
5261   XA_Speaker_Tog	= Towns8_Speaker_Toggle;
5262   XA_Headphone_Tog	= Towns8_Headphone_Toggle;
5263   XA_LineOut_Tog	= Towns8_Headphone_Toggle;
5264   XA_Adjust_Volume	= Towns8_Adjust_Volume;
5265 
5266   xa_snd_cur = 0;
5267   xa_audio_present = XA_AUDIO_UNK;
5268   xa_audio_status  = XA_AUDIO_STOPPED;
5269   xa_audio_ring_size  = 8;
5270 }
5271 
5272 
5273 /********** Towns8_Audio_Init **********************
5274  * Open /dev/pcm for Towns 8 bit PCM
5275  *
5276  *****/
Towns8_Audio_Init()5277 void Towns8_Audio_Init()
5278 { int ret;
5279   int type;
5280 
5281   DEBUG_LEVEL2 fprintf(stderr,"Towns8_Audio_Init\n");
5282   if (xa_audio_present != XA_AUDIO_UNK) return;
5283   devAudio = open("/dev/pcm",O_WRONLY | O_NDELAY);
5284   if (devAudio == -1)
5285   {
5286     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
5287     else fprintf(stderr,"Audio_Init: Error %x opening audio device. - ",errno);
5288     fprintf(stderr,"Will continue without audio\n");
5289     xa_audio_present = XA_AUDIO_ERR;
5290     return;
5291   }
5292 
5293   /***** 19200 Hz *****/
5294   {
5295      short s_;
5296      s_ = 1920;
5297      write(devAudio,&s_,sizeof(s_));
5298   }
5299 
5300     xa_audio_hard_freq  = 19200;
5301     xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
5302     xa_audio_hard_buff  = XA_HARD_BUFF_1K;             /* default buffer size */
5303     xa_audio_hard_bps   = 2;
5304     xa_audio_hard_chans = 1;
5305 
5306   xa_interval_id = 0;
5307   xa_audio_present = XA_AUDIO_OK;
5308   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
5309   Init_Audio_Ring(xa_audio_ring_size,
5310 			(XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
5311 }
5312 
5313 /********** Towns8_Audio_Kill **********************
5314  * Close /dev/pcm
5315  *
5316  *****/
Towns8_Audio_Kill()5317 void Towns8_Audio_Kill()
5318 {
5319   /* TURN AUDIO OFF */
5320   Towns8_Audio_Off(0);
5321   xa_audio_present = XA_AUDIO_UNK;
5322   /* SHUT THINGS DOWN  */
5323   close(devAudio);
5324   Kill_Audio_Ring();
5325 }
5326 
5327 /********** Towns8_Audio_Off **********************
5328  * Stop Audio Stream
5329  *
5330  *****/
Towns8_Audio_Off(flag)5331 void Towns8_Audio_Off(flag)
5332 xaULONG flag;
5333 { long ret;
5334 
5335   if (xa_audio_status != XA_AUDIO_STARTED) return;
5336 
5337   /* SET FLAG TO STOP OUTPUT ROUTINE */
5338   xa_audio_status = XA_AUDIO_STOPPED;
5339 
5340   /* TURN OFF SOUND ??? */
5341   /*
5342   Towns8_Adjust_Volume(XA_AUDIO_MINVOL);
5343   */
5344 
5345   /* FLUSH AUDIO DEVICE */
5346   /***** none *****/
5347 
5348 
5349   xa_time_audio = -1;
5350   xa_audio_flushed = 0;
5351 
5352   /* FLUSH AUDIO DEVICE AGAIN */
5353   /***** none *****/
5354 
5355   /* RESTORE ORIGINAL VOLUME */
5356   /*
5357   if (XAAUD->mute != xaTRUE) Towns8_Adjust_Volume(XAAUD->volume);
5358   */
5359 }
5360 
5361 /********** Towns8_Audio_Prep **********************
5362  * Turn On Audio Stream.
5363  *
5364  *****/
Towns8_Audio_Prep()5365 void Towns8_Audio_Prep()
5366 {
5367   DEBUG_LEVEL2
5368   {
5369     fprintf(stderr,"Towns8_Audio_Prep \n");
5370   }
5371   if (xa_audio_status == XA_AUDIO_STARTED) return;
5372   else if (xa_audio_present != XA_AUDIO_OK) return;
5373   else if (xa_snd_cur)
5374   { int ret;
5375 
5376     /* CHANGE FREQUENCY IF NEEDED */
5377   /***** cant change *****/
5378 
5379     /* xa_snd_cur gets changes in Update_Ring() */
5380     xa_out_time = 500;  /* keep audio fed 500ms ahead of video */
5381     xa_out_init = xa_audio_ring_size - 1;
5382     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
5383     if (xa_interval_time == 0) xa_interval_time = 1;
5384 
5385     XA_Flush_Ring();
5386     XA_Update_Ring(1000);
5387     xa_audio_status = XA_AUDIO_PREPPED;
5388   }
5389 }
5390 
5391 /****-------------------------------------------------------------------****
5392  *
5393  ****-------------------------------------------------------------------****/
Towns8_Audio_On()5394 void Towns8_Audio_On()
5395 {
5396   if (   (xa_snd_cur)
5397       && (xa_audio_present == XA_AUDIO_OK)
5398       && (xa_audio_status == XA_AUDIO_PREPPED) )
5399   {
5400     xa_audio_status = XA_AUDIO_STARTED;
5401     xa_time_now = XA_Read_AV_Time();  /* get new time */
5402     New_Merged_Audio_Output();
5403   }
5404 }
5405 
5406 /********** Towns8_Closest_Freq **********************************************
5407  *
5408  * Global Variable Affect:
5409  *   xaULONG xa_audio_hard_buff		must set but not larger than
5410  *					XA_AUDIO_MAX_RING_BUF size
5411  ****************************************************************************/
Towns8_Closest_Freq(ifreq)5412 xaULONG Towns8_Closest_Freq(ifreq)
5413 xaLONG ifreq;
5414 {
5415     xa_audio_hard_buff = XA_HARD_BUFF_1K;
5416     return(19200);
5417 }
5418 
5419 /************* Towns8_Speaker_Toggle *****************************************
5420  *
5421  * flag = 0  turn speaker off
5422  * flag = 1  turn speaker on
5423  * flag = 2  toggle speaker
5424  ****************************************************************************/
Towns8_Speaker_Toggle(flag)5425 void Towns8_Speaker_Toggle(flag)
5426 xaULONG flag;
5427 {
5428    return;
5429 }
5430 
5431 /************* Towns8_Headphone_Toggle *****************************************
5432  *
5433  * flag = 0  turn headphones off
5434  * flag = 1  turn headphones on
5435  * flag = 2  toggle headphones
5436  ****************************************************************************/
Towns8_Headphone_Toggle(flag)5437 void Towns8_Headphone_Toggle(flag)
5438 xaULONG flag;
5439 {
5440    return;
5441 }
5442 
5443 
5444 /********** Towns8_Adjust_Volume **********************
5445  * Routine for Adjusting Volume on a Towns8
5446  *
5447  * Volume is in the range [0,XA_AUDIO_MAXVOL]
5448  ****************************************************************************/
Towns8_Adjust_Volume(volume)5449 void Towns8_Adjust_Volume(volume)
5450 xaULONG volume;
5451 {
5452    return;
5453 }
5454 #endif
5455 /****************************************************************************/
5456 /******************* END OF Towns8 SPECIFIC ROUTINES *********************/
5457 /****************************************************************************/
5458 
5459 
5460 /* NEW CODE */
XA_Audio_Next_Snd(snd_hdr)5461 XA_SND *XA_Audio_Next_Snd(snd_hdr)
5462 XA_SND *snd_hdr;
5463 { DEBUG_LEVEL2 fprintf(stderr,"XA_Audio_Next_Snd: snd_hdr %x \n",
5464 							(xaULONG)snd_hdr);
5465   xa_snd_cur = snd_hdr->next;
5466   /* brief clean up of old header */
5467   snd_hdr->inc_cnt = 0;
5468   snd_hdr->byte_cnt = 0;
5469   snd_hdr->samp_cnt = snd_hdr->tot_samps;
5470   if (snd_hdr->fpos >= 0) snd_hdr->snd = 0;
5471   if (xa_snd_cur==0) return(0);
5472   /* full init of new header */
5473   XA_Audio_Init_Snd(xa_snd_cur);
5474   /* read in info from file if necessary */
5475   if (xa_snd_cur->fpos >= 0)
5476   { xa_snd_cur->snd = xa_audcodec_buf;
5477     XA_Read_Audio_Delta(xa_aud_fd,xa_snd_cur->fpos,
5478 				xa_snd_cur->tot_bytes,xa_audcodec_buf);
5479   }
5480   return(xa_snd_cur);
5481 }
5482 
XA_Read_Audio_Delta(fd,fpos,fsize,buf)5483 void XA_Read_Audio_Delta(fd,fpos,fsize,buf)
5484 int fd;
5485 xaLONG fpos;
5486 xaULONG fsize;
5487 char *buf;
5488 { int ret;
5489   ret  = lseek(fd,fpos,SEEK_SET);
5490   if (ret != fpos) TheEnd1("XA_Read_Audio_Delta:seek err");
5491   ret = read(fd, buf, fsize);
5492   if (ret != fsize) TheEnd1("XA_Read_Audio_Delta:read err");
5493 }
5494 
5495 
5496 
5497 /*************
5498  *  May not be needed
5499  *
5500  *****/
XA_Signed_To_uLaw(ch)5501 xaUBYTE XA_Signed_To_uLaw(ch)
5502 xaLONG ch;
5503 {
5504   xaLONG mask;
5505   if (ch < 0) { ch = -ch; mask = 0x7f; }
5506   else { mask = 0xff; }
5507   if (ch < 32)		{ ch = 0xF0 | (15 - (ch / 2)); }
5508   else if (ch < 96)	{ ch = 0xE0 | (15 - (ch - 32) / 4); }
5509   else if (ch < 224)	{ ch = 0xD0 | (15 - (ch - 96) / 8); }
5510   else if (ch < 480)	{ ch = 0xC0 | (15 - (ch - 224) / 16); }
5511   else if (ch < 992)	{ ch = 0xB0 | (15 - (ch - 480) / 32); }
5512   else if (ch < 2016)	{ ch = 0xA0 | (15 - (ch - 992) / 64); }
5513   else if (ch < 4064)	{ ch = 0x90 | (15 - (ch - 2016) / 128); }
5514   else if (ch < 8160)	{ ch = 0x80 | (15 - (ch - 4064) /  256); }
5515   else			{ ch = 0x80; }
5516   return (mask & ch);
5517 }
5518 
Gen_Signed_2_uLaw()5519 void Gen_Signed_2_uLaw()
5520 {
5521   xaULONG i;
5522   for(i=0;i<256;i++)
5523   { xaUBYTE d;
5524     xaBYTE ch = i;
5525     xaLONG chr = ch;
5526     d = XA_Signed_To_uLaw(chr * 16);
5527     xa_sign_2_ulaw[i] = d;
5528   }
5529 }
5530 
5531 
5532 /*
5533 ** This routine converts from ulaw to 16 bit linear.
5534 **
5535 ** Craig Reese: IDA/Supercomputing Research Center
5536 ** 29 September 1989
5537 **
5538 ** References:
5539 ** 1) CCITT Recommendation G.711  (very difficult to follow)
5540 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
5541 **     for Analog-to_Digital Conversion Techniques,"
5542 **     17 February 1987
5543 **
5544 ** Input: 8 bit ulaw sample
5545 ** Output: signed 16 bit linear sample
5546 */
5547 
XA_uLaw_to_Signed(ulawbyte)5548 xaLONG XA_uLaw_to_Signed( ulawbyte )
5549 xaUBYTE ulawbyte;
5550 {
5551   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
5552   int sign, exponent, mantissa, sample;
5553 
5554   ulawbyte = ~ ulawbyte;
5555   sign = ( ulawbyte & 0x80 );
5556   exponent = ( ulawbyte >> 4 ) & 0x07;
5557   mantissa = ulawbyte & 0x0F;
5558   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
5559   if ( sign != 0 ) sample = -sample;
5560 
5561   return sample;
5562 }
5563 
5564 /****-----------------------------------------------------------------****
5565  *
5566  ****-----------------------------------------------------------------****/
Gen_uLaw_2_Signed()5567 void Gen_uLaw_2_Signed()
5568 { xaULONG i;
5569   for(i=0;i<256;i++)
5570   { xaUBYTE data = (xaUBYTE)(i);
5571     xaLONG d = XA_uLaw_to_Signed( data );
5572     xa_ulaw_2_sign[i] = (xaULONG)((xaULONG)(d) & 0xffff);
5573   }
5574 }
5575 
5576 /****-----------------------------------------------------------------****
5577  *
5578  ****-----------------------------------------------------------------****/
Gen_aLaw_2_Signed()5579 void Gen_aLaw_2_Signed()
5580 { xaULONG i;
5581   for(i=0;i<256;i++)
5582   { xaUBYTE data = (xaUBYTE)(i);
5583     xaLONG d, t, seg;
5584 
5585     data ^= 0x55;
5586 
5587     t = (data & 0xf) << 4;
5588     seg = (data & 0x70) >> 4;
5589     if (seg == 0)	t += 8;
5590     else if (seg == 1)	t += 0x108;
5591     else	{ t += 108; t <<= seg - 1; }
5592 
5593     d =  (data & 0x80)?(t):(-t);
5594     xa_alaw_2_sign[i] = (xaULONG)((xaULONG)(d) & 0xffff);
5595   }
5596 }
5597 
5598 
5599 
5600 /* Pod this was 4096, I changed to 32768 */
5601 #define XA_ARM_VAL_LIMIT       32768
5602 /* Mu-law format constants */
5603 #define XA_ARM_SIGN_BIT        1
5604 #define XA_ARM_NCHORDS         8
5605 #define XA_ARM_NPOINTS         16
5606     /* limit of "magnitude" (logarithmic) */
5607 #define XA_ARM_DAC_LIMIT       (XA_ARM_NCHORDS*XA_ARM_NPOINTS)
5608 
5609 xaULONG arm_dac_to_val[XA_ARM_DAC_LIMIT];     /* obsolete */
5610 
5611 /**************************************
5612  *
5613  * original code courtesy of Mark Taunton, Acorn Computers Ltd, June 1992.
5614  * hacked by Mark Podlipec
5615  *************************************/
Gen_Arm_2_Signed()5616 void Gen_Arm_2_Signed()
5617 { int c, p, ux, step, curval, max;
5618   double adjust;
5619 
5620   ux = 0; curval = 0;
5621   for (c = 0; c < XA_ARM_NCHORDS; ++c)
5622   {
5623     step = 1 << c;
5624     for (p = 0; p < XA_ARM_NPOINTS; ++p)
5625     {
5626       arm_dac_to_val[ux++] = curval;
5627       curval += step;
5628     }
5629   }
5630 
5631   /* Now adjust for 0..4095 notional linear range rather than 0..4016 */
5632   /* i.e. half-step over max nominal: 3952+128/2 = 4016 */
5633   max = curval - step/2;
5634   adjust = (double)(XA_ARM_VAL_LIMIT-1) / (double)max;
5635   /* Scale dac_to_val table to give 0..4095 linear range coverage */
5636   for (ux = 0; ux < XA_ARM_DAC_LIMIT; ++ux)
5637   {                       /* implement rounding */
5638     arm_dac_to_val[ux] = (int) (arm_dac_to_val[ux] * adjust + 0.5);
5639         /* Compute signed table values also */
5640     xa_arm_2_signed[ux << 1 |        0]        =  arm_dac_to_val[ux];
5641     xa_arm_2_signed[ux << 1 | XA_ARM_SIGN_BIT] = -arm_dac_to_val[ux];
5642   }
5643 }
5644 
5645 /********* Init_Audio_Ring ************
5646  *
5647  * Global Variables:
5648  *  xa_audio_ring		pointer to somewhere in the ring
5649  *************************************/
Init_Audio_Ring(ring_num,buf_size)5650 void Init_Audio_Ring(ring_num,buf_size)
5651 xaULONG ring_num;
5652 xaULONG buf_size;
5653 {
5654   xaULONG i;
5655   XA_AUDIO_RING_HDR *t_ring,*t_first;
5656   xaUBYTE *t_buf;
5657   if (xa_audio_ring) Kill_Audio_Ring();
5658   t_first = xa_audio_ring = 0;
5659   for(i=0;i<ring_num;i++)
5660   {
5661     t_ring = (XA_AUDIO_RING_HDR *)malloc( sizeof(XA_AUDIO_RING_HDR) );
5662     if (t_ring==0) TheEnd1("Init Audio Ring: malloc err0");
5663     t_buf = (xaUBYTE *)malloc( buf_size );
5664     if (t_buf==0) TheEnd1("Init Audio Ring: malloc err1");
5665     t_ring->time = t_ring->timelo = 0;
5666     t_ring->len = 0;
5667     t_ring->buf = t_buf;
5668     if (t_first == 0) t_first = xa_audio_ring = t_ring;
5669     t_ring->next = t_first;
5670     xa_audio_ring->next = t_ring;
5671     xa_audio_ring = t_ring;
5672   }
5673   xa_audio_ring_t = xa_audio_ring;
5674 }
5675 
5676 /********* Kill_Audio_Ring ************
5677  * Move around ring, free'ing up memory structures.
5678  *
5679  * Global Variables:
5680  *  xa_audio_ring		pointer to somewhere in the ring
5681  **************************************/
Kill_Audio_Ring()5682 void Kill_Audio_Ring()
5683 {
5684   XA_AUDIO_RING_HDR *t_first;
5685 
5686   if (xa_audio_ring==0) return;
5687   t_first = xa_audio_ring;
5688 
5689   do
5690   { XA_AUDIO_RING_HDR *t_tmp = xa_audio_ring;
5691     if (xa_audio_ring->buf) FREE(xa_audio_ring->buf,0x508);
5692     xa_audio_ring->time = xa_audio_ring->timelo = 0;
5693     xa_audio_ring->len = 0;
5694     xa_audio_ring->buf = 0;
5695     xa_audio_ring = xa_audio_ring->next;
5696     FREE(t_tmp,0x509);
5697   } while(xa_audio_ring != t_first);
5698   xa_audio_ring = 0;
5699   xa_audio_ring_t = 0;
5700 }
5701 
5702 /****************************************************************
5703  * Fill up any unused Audio Ring Entries with sound.
5704  *
5705  ****************************************************************/
5706 
XA_Update_Ring(cnt)5707 void XA_Update_Ring(cnt)
5708 xaULONG cnt;
5709 {
5710 DEBUG_LEVEL1 fprintf(stderr,"UPDATE RING %d\n",cnt);
5711   while( (xa_audio_ring_t->len == 0) && (xa_snd_cur) && cnt)
5712   { xaULONG tmp_time, tmp_timelo; xaLONG i,xx;
5713     cnt--;
5714     tmp_time = xa_snd_cur->ch_time;	/* save these */
5715     tmp_timelo = xa_snd_cur->ch_timelo;
5716 	/* uncompress sound chunk */
5717     i = xa_audio_ring_t->len = xa_snd_cur->ch_size * xa_audio_hard_bps;
5718     /* NOTE: the following delta call may modify xa_snd_cur */
5719     xx = xa_snd_cur->delta(xa_snd_cur,xa_audio_ring_t->buf,0,
5720 							xa_snd_cur->ch_size);
5721     i -= xx * xa_audio_hard_bps;
5722     if (i > 0) /* Some system need fixed size chunks */
5723     { xaUBYTE *dptr = xa_audio_ring_t->buf;
5724       while(i--) *dptr++ = 0;
5725     }
5726     xa_audio_ring_t->time = tmp_time;
5727     xa_audio_ring_t->timelo = tmp_timelo;
5728     xa_audio_ring_t = xa_audio_ring_t->next;
5729   }
5730 }
5731 
5732 /***************************************************************8
5733  * Flush Ring of All Conversions
5734  * SHOULD ONLY BE CALLED BY OUTPUT ROUTINE.
5735  */
5736 
XA_Flush_Ring()5737 void XA_Flush_Ring()
5738 { XA_AUDIO_RING_HDR *tring = xa_audio_ring;
5739 
5740 DEBUG_LEVEL1 fprintf(stderr,"FLUSH_RING\n");
5741   do
5742   { xa_audio_ring->len = 0;
5743     xa_audio_ring = xa_audio_ring->next;
5744   } while(xa_audio_ring != tring);
5745   xa_audio_ring_t = xa_audio_ring;	/* resync  fill and empty */
5746   xa_audio_flushed = 1;
5747 }
5748 
5749 
5750 /********** New_Merged_Audio_Output **********************
5751  * Set Volume if needed and then write audio data to audio device.
5752  *
5753  * IS
5754  *****/
New_Merged_Audio_Output()5755 void New_Merged_Audio_Output()
5756 { xaLONG time_diff, loop_cnt = xa_audio_ring_size;
5757 
5758   /* normal exit is when audio gets ahead */
5759   while(loop_cnt--)
5760   {
5761     if (xa_audio_status != XA_AUDIO_STARTED) { return; }
5762     time_diff = xa_time_audio - xa_time_now; /* how far ahead is audio */
5763     if (time_diff > xa_out_time) /* potentially ahead */
5764     {
5765       xa_time_now = XA_Read_AV_Time();  /* get new time */
5766       time_diff = xa_time_audio - xa_time_now;
5767       if (time_diff > xa_out_time)  /* definitely ahead */
5768       { /* If we're ahead, update the ring. */
5769         XA_Update_Ring(2);
5770 	xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
5771 		(XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
5772         return;
5773       }
5774     }
5775 
5776 
5777     if (xa_audio_ring->len)
5778     {
5779       /* If audio buffer is full, write() can't write all of the data. */
5780       /* So, next routine checks the rest length in buffer.            */
5781 #ifdef XA_SONY_AUDIO
5782       { int ret, buf_len;
5783 	ret = ioctl(devAudio, SBIOCBUFRESID,&buf_len) ;
5784 	if( ret == -1 ) fprintf(stderr,"SONY_AUDIO: SIOCBUFRESID error.\n");
5785 	if(buf_len > sony_audio_buf_len - xa_audio_ring->len)
5786 	{
5787 	  xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
5788 		(XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
5789 	  return;
5790 	}
5791       }
5792 #endif
5793 
5794 #ifdef XA_SGI_AUDIO
5795       { int buf_len;
5796 	buf_len = ALgetfillable(port) ;
5797 	if (buf_len < (xa_audio_ring->len >> 1))
5798 	{
5799 	  xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
5800 		(XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
5801 	  return;
5802 	}
5803       }
5804 #endif
5805 
5806 #ifdef XA_MMS_AUDIO
5807       {
5808         mmeProcessCallbacks();
5809 	/* NOTE: These buffers aren't part of the XAnim audio ring buffer */
5810 	/*       Our ring buffer just happens to be the same size */
5811 	if( mms_buffers_outstanding  >= xa_audio_ring_size )
5812 	{
5813 	  xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
5814 		(XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
5815  	  return ;
5816 	}
5817       }
5818 #endif
5819 
5820 #ifdef XA_HP_AUDIO
5821       if (hp_audio_paused == xaTRUE)
5822       { DEBUG_LEVEL1 fprintf(stderr,"HP-out-unpause\n");
5823         AResumeAudio( audio_connection, hp_trans_id, NULL, NULL );
5824         hp_audio_paused = xaFALSE;
5825       }
5826 #endif
5827 
5828 
5829 /*---------------- Now for the Write Segments -------------------------------*/
5830 
5831 #ifdef XA_SPARC_AUDIO
5832       write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
5833 #endif
5834 
5835 #ifdef XA_NetBSD_AUDIO
5836       write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
5837 #endif
5838 
5839 #ifdef XA_AIX_AUDIO
5840       { int rc;
5841         rc = write ( devAudio, xa_audio_ring->buf, xa_audio_ring->len );
5842       }
5843 #endif
5844 
5845 #ifdef XA_SGI_AUDIO
5846       /* # of Samples, not Bytes. Note: assume 16 bit samples. */
5847       ALwritesamps(port,xa_audio_ring->buf, (xa_audio_ring->len >> 1) );
5848 #endif
5849 
5850 #ifdef XA_LINUX_AUDIO
5851       write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
5852 #endif
5853 
5854 #ifdef XA_NAS_AUDIO
5855       NAS_Write_Data(xa_audio_ring->buf, xa_audio_ring->len);
5856 #endif
5857 
5858 #ifdef XA_SONY_AUDIO
5859       { int ret;
5860         write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
5861         /* Buffer of Sony audio device is too large */ /* HP needs this */
5862         ret = ioctl(devAudio, SBIOCFLUSH, 0);
5863         if( ret == -1 ) fprintf(stderr,"audio output:SBIOCFLUSH error.\n");
5864       }
5865 #endif
5866 
5867 #ifdef XA_EWS_AUDIO
5868       write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
5869 #endif
5870 
5871 #ifdef XA_AF_AUDIO
5872       { ATime act, atd = AFtime0;
5873 	if (XAAUD->mute != xaTRUE)
5874 	  act = AFPlaySamples(ac,AFtime0,xa_audio_ring->len,xa_audio_ring->buf);
5875 	else act = AFGetTime(ac);
5876 	if (AFtime0 < act)	AFtime0 = act+TOFFSET;
5877 	else	AFtime0 += xa_audio_ring->len >> 1; /* Number of samples */
5878       }
5879 #endif
5880 
5881 #ifdef XA_HP_AUDIO
5882       write(streamSocket,xa_audio_ring->buf,xa_audio_ring->len);
5883 /* Some way to flush streamsocket???? */
5884 #endif
5885 
5886 #ifdef XA_HPDEV_AUDIO
5887       write (devAudio, xa_audio_ring->buf, xa_audio_ring->len);
5888 #endif
5889 
5890 #ifdef XA_MMS_AUDIO
5891       /* As currently implemented, this copies the audio data into a separate
5892          shared memory buffer for communication with the multimedia server. We
5893          could actually work directly out of the audio ring buffer if it was
5894          allocated in shared memory, but this keeps things more independent of
5895          each other - tfm
5896       */
5897       {
5898 	MMRESULT	status;
5899 	int		bytes,len;
5900 	if (XAAUD->mute != xaTRUE)
5901 	{
5902 	  bytes = xa_audio_hard_buff * xa_audio_hard_bps;
5903 	  mms_lpWaveHeader->lpData = (LPSTR)(mms_audio_buffer
5904 						+ mms_next_buffer * bytes);
5905 	  mms_lpWaveHeader->dwBufferLength = xa_audio_ring->len;
5906 	  if(xa_audio_ring->len > bytes)
5907 	  {
5908 	    len = bytes;
5909 	    fprintf(stderr,"Audio chunk truncated to %d bytes\n",len);
5910 	  }
5911 	  else len = xa_audio_ring->len;
5912 	  memcpy( mms_lpWaveHeader->lpData, xa_audio_ring->buf, len);
5913 	  mms_next_buffer++;
5914 	  if(mms_next_buffer >= xa_audio_ring_size) mms_next_buffer = 0;
5915 	  status = waveOutWrite(mms_device_handle, mms_lpWaveHeader,
5916 							sizeof(WAVEHDR));
5917 	  if( status != MMSYSERR_NOERROR )
5918 	  {
5919 	    fprintf(stderr,"waveOutWrite failed - status = %d\n",status);
5920 	  }
5921 	  else { mms_buffers_outstanding++; }
5922 	}
5923       }
5924 #endif
5925 
5926 #ifdef XA_TOWNS_AUDIO
5927       write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
5928 #endif
5929 
5930 #ifdef XA_TOWNS8_AUDIO
5931       { int i_;
5932 	char *cp_,*cp2_;
5933 
5934 	i_=0;
5935 	cp_ = cp2_ = xa_audio_ring->buf;
5936 
5937 	while (i_<xa_audio_ring->len)
5938 	{ int i1_,i2_;
5939 	  i1_ = *cp_++;
5940 	  cp_++;
5941 	  if (i1_ < 0) { i1_ += 256; }
5942 	  if (i1_ >= 128) { i1_ = 128 - i1_; }
5943 	  *cp2_++ = (char) i1_;
5944 	  i_+=2;
5945         }
5946         write(devAudio,xa_audio_ring->buf,xa_audio_ring->len/2);
5947       }
5948 #endif
5949 
5950 
5951       /* Don't adjust volume until after write. If we're behind
5952        * the extra delay could cause a pop. */
5953       if (XAAUD->newvol==xaTRUE)
5954       { xaULONG vol = (XAAUD->mute==xaTRUE)?(XA_AUDIO_MINVOL):(XAAUD->volume);
5955   	XA_Adjust_Volume(vol);
5956   	XAAUD->newvol = xaFALSE;
5957       }
5958       xa_time_audio   += xa_audio_ring->time;
5959       xa_timelo_audio += xa_audio_ring->timelo;
5960       if (xa_timelo_audio & 0xff000000)
5961 		{ xa_time_audio++; xa_timelo_audio &= 0x00ffffff; }
5962       xa_audio_ring->len = 0;
5963       xa_audio_ring = xa_audio_ring->next;  /* move to next */
5964       if (xa_audio_status != XA_AUDIO_STARTED) { return;}
5965 
5966       if (xa_out_init) xa_out_init--;
5967       else XA_Update_Ring(2);  /* only allow two to be updated */
5968 /* NOT HERE - loop first
5969       xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
5970 	    (XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
5971       return;
5972 */
5973     }
5974     else  /* Audio Sample finished */
5975     { xa_time_now = XA_Read_AV_Time();
5976 
5977 	/* Is audio still playing buffered samples? */
5978       if (xa_time_now < xa_time_audio)
5979       { xaULONG diff = xa_time_audio - xa_time_now;
5980 	/* POD note 50ms is arbitrarily chosen to be long, but not noticeable*/
5981         if (xa_audio_status != XA_AUDIO_STARTED) {return;}
5982 	xa_interval_id = XtAppAddTimeOut(theAudContext,diff,
5983 		(XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
5984         return;
5985       }
5986       else
5987       { XA_Audio_Off(0);
5988 	return;
5989       }
5990     } /* end of ring_len */
5991   } /* end of while ring */
5992   xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
5993 	    (XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
5994   return;
5995 }  /* end of function */
5996 
5997