--- xa_audio.c.orig Tue Mar 16 00:58:48 1999 +++ xa_audio.c Fri Mar 19 01:15:03 1999 @@ -114,6 +114,7 @@ * 21Feb99 - Added routine *_Audio_Prep to hide initialization delays * when starting audio. * 02Mar99 - Linux: Change XA_LINUX_NEWER_SND TO OLDER_SND to avoid confusion. + * 18Mar99 - OpenBSD: newer configuration, solves a few problems. * ****************************************************************************/ @@ -4936,6 +4937,402 @@ /******************* END OF NetBSD SPECIFIC ROUTINES ************************/ /****************************************************************************/ +/****************************************************************************/ +/**************** OpenBSD SPECIFIC ROUTINES *********************************/ +/****************************************************************************/ + +/* + * Based on the NetBSD port initially, + * contributed by Marc Espie + * This code may actually work on NetBSD, but this is not my place to + * change this. + * + * This code tries not to abuse AUDIO_SETINFO, as this can be an expensive + * ioctl on some arches. Also, it is able to deal with weirder audio + * devices, such as those found on amiga or sparcs. + */ + +#ifdef XA_OpenBSD_AUDIO + +void OpenBSD_Audio_Init(); +void OpenBSD_Audio_Kill(); +void OpenBSD_Audio_Off(); +void OpenBSD_Audio_Prep(); +void OpenBSD_Audio_On(); +void OpenBSD_Adjust_Volume(); +xaULONG OpenBSD_Closest_Freq(); +void OpenBSD_Set_Output_Port(); +void OpenBSD_Speaker_Toggle(); +void OpenBSD_Headphone_Toggle(); + +#define OpenBSD_MAX_VOL AUDIO_MAX_GAIN +#define OpenBSD_MIN_VOL AUDIO_MIN_GAIN + +static int devAudio; + +/********** XA_Audio_Setup ********************** + * + * Also defines OpenBSD Specific variables. + * + *****/ +void XA_Audio_Setup() +{ + XA_Audio_Init = OpenBSD_Audio_Init; + XA_Audio_Kill = OpenBSD_Audio_Kill; + XA_Audio_Off = OpenBSD_Audio_Off; + XA_Audio_Prep = OpenBSD_Audio_Prep; + XA_Audio_On = OpenBSD_Audio_On; + XA_Closest_Freq = OpenBSD_Closest_Freq; + XA_Set_Output_Port = OpenBSD_Set_Output_Port; + XA_Speaker_Tog = OpenBSD_Speaker_Toggle; + XA_Headphone_Tog = OpenBSD_Headphone_Toggle; + XA_LineOut_Tog = OpenBSD_Headphone_Toggle; + XA_Adjust_Volume = OpenBSD_Adjust_Volume; + + xa_snd_cur = 0; + xa_audio_present = XA_AUDIO_UNK; + xa_audio_status = XA_AUDIO_STOPPED; + xa_audio_ring_size = 8; +} + +/********** OpenBSD_Audio_Init ********************** + * Open /dev/audio and OpenBSD. + * + *****/ +void OpenBSD_Audio_Init() +{ int ret; + int type; + audio_info_t a_info; + struct audio_encoding query; + DEBUG_LEVEL2 fprintf(stderr,"OpenBSD_Audio_Init\n"); + if (xa_audio_present != XA_AUDIO_UNK) return; + devAudio = open("/dev/audio", O_WRONLY | O_NDELAY); + if (devAudio == -1) + { + if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - "); + else fprintf(stderr,"Audio_Init: Error opening audio device. - "); + fprintf(stderr,"Will continue without audio\n"); + xa_audio_present = XA_AUDIO_ERR; + return; + } + + DEBUG_LEVEL1 fprintf(stderr,"OpenBSD AUDIO\n"); + + AUDIO_INITINFO(&a_info); + a_info.blocksize = 1024; + a_info.mode = AUMODE_PLAY | AUMODE_PLAY_ALL; + a_info.play.sample_rate = 11025; /* this is changed later */ + + /* find true native formats */ + for (query.index = 0; + ioctl(devAudio, AUDIO_GETENC, &query) != -1; + query.index++) + { + if (query.flags & AUDIO_ENCODINGFLAG_EMULATED) + continue; + if (query.precision == 16) + { + a_info.play.encoding = query.encoding; + a_info.play.precision = query.precision; + break; + } + if ((query.precision == 8) && ( + (query.encoding == AUDIO_ENCODING_SLINEAR) || + (query.encoding == AUDIO_ENCODING_ULINEAR)) ) + { + a_info.play.encoding = query.encoding; + a_info.play.precision = query.precision; + } + /* no linear format -> resort to log formats */ + if (a_info.play.precision != 8) + { + if ( query.encoding == AUDIO_ENCODING_ULAW) + a_info.play.encoding = query.encoding; + } + } + /* set format, then retrieve what the device actually says */ + ioctl(devAudio, AUDIO_SETINFO, &a_info); + ioctl(devAudio, AUDIO_GETINFO, &a_info); + + switch(a_info.play.encoding) + { + case AUDIO_ENCODING_SLINEAR: + xa_audio_hard_type = a_info.play.precision == 8 ? XA_AUDIO_SIGNED_1M : +#if BYTE_ORDER == BIG_ENDIAN + XA_AUDIO_SIGNED_2MB; +#else + XA_AUDIO_SIGNED_2ML; +#endif + break; + case AUDIO_ENCODING_ULINEAR: + xa_audio_hard_type = a_info.play.precision == 8 ? XA_AUDIO_LINEAR_1M : +#if BYTE_ORDER == BIG_ENDIAN + XA_AUDIO_LINEAR_2MB; +#else + XA_AUDIO_LINEAR_2ML; +#endif + break; + case AUDIO_ENCODING_ULAW: + xa_audio_hard_type = XA_AUDIO_SUN_AU; + break; + case AUDIO_ENCODING_ULINEAR_LE: + xa_audio_hard_type = a_info.play.precision == 8 ? XA_AUDIO_LINEAR_1M : + XA_AUDIO_LINEAR_2ML; + break; + case AUDIO_ENCODING_ULINEAR_BE: + xa_audio_hard_type = a_info.play.precision == 8 ? XA_AUDIO_LINEAR_1M : + XA_AUDIO_LINEAR_2MB; + break; + case AUDIO_ENCODING_SLINEAR_LE: + xa_audio_hard_type = a_info.play.precision == 8 ? XA_AUDIO_SIGNED_1M : + XA_AUDIO_SIGNED_2ML; + break; + case AUDIO_ENCODING_SLINEAR_BE: + xa_audio_hard_type = a_info.play.precision == 8 ? XA_AUDIO_SIGNED_1M : + XA_AUDIO_SIGNED_2MB; + break; + default: + fprintf(stderr,"Audio_Init: Weird audio format %d\n", + a_info.play.encoding); + fprintf(stderr,"Will continue without audio\n"); + xa_audio_present = XA_AUDIO_ERR; + close(devAudio); + return; + } + + xa_audio_hard_freq = a_info.play.sample_rate; + xa_audio_hard_buff = a_info.blocksize; + + /* only precision 8 and 16 are supported. Fail if otherwise?? */ + xa_audio_hard_bps = (a_info.play.precision==8)?1:2; + xa_audio_hard_chans = a_info.play.channels; + Gen_uLaw_2_Signed(); + Gen_Signed_2_uLaw(); + + xa_interval_id = 0; + xa_audio_present = XA_AUDIO_OK; + DEBUG_LEVEL2 fprintf(stderr," success \n"); + Init_Audio_Ring(xa_audio_ring_size, + (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) ); +} + +/********** OpenBSD_Audio_Kill ********************** + * Close /dev/audio. + * + *****/ +void OpenBSD_Audio_Kill() +{ + /* TURN AUDIO OFF */ + OpenBSD_Audio_Off(0); + xa_audio_present = XA_AUDIO_UNK; + /* SHUT THINGS DOWN */ + close(devAudio); + Kill_Audio_Ring(); +} + +/********** OpenBSD_Audio_Off ********************** + * Stop Audio Stream + * + *****/ +void OpenBSD_Audio_Off(flag) +xaULONG flag; +{ /* long ret; */ + + DEBUG_LEVEL1 fprintf(stderr,"OpenBSD_Audio_Off\n"); + if (xa_audio_status != XA_AUDIO_STARTED) return; + + /* SET FLAG TO STOP OUTPUT ROUTINE */ + xa_audio_status = XA_AUDIO_STOPPED; + + /* TURN OFF SOUND ??? */ + OpenBSD_Adjust_Volume(XA_AUDIO_MINVOL); + + /* FLUSH AUDIO DEVICE */ /* NOT! */ +/* + ret = ioctl(devAudio, AUDIO_FLUSH, NULL); + if (ret == -1) fprintf(stderr,"OpenBSD Audio: off flush err %d\n",errno); +*/ + + xa_time_audio = -1; + xa_audio_flushed = 0; + + /* FLUSH AUDIO DEVICE AGAIN */ /* NOT! */ +/* + ret = ioctl(devAudio, AUDIO_FLUSH, NULL); + if (ret == -1) fprintf(stderr,"OpenBSD Audio: off flush err %d\n",errno); +*/ + + /* RESTORE ORIGINAL VOLUME */ + if (XAAUD->mute != xaTRUE) OpenBSD_Adjust_Volume(XAAUD->volume); +} + +/********** OpenBSD_Audio_Prep ********************** + * Turn On Audio Stream. + * + *****/ +void OpenBSD_Audio_Prep() +{ + DEBUG_LEVEL2 + { + fprintf(stderr,"OpenBSD_Audio_Prep \n"); + } + if (xa_audio_status == XA_AUDIO_STARTED) return; + else if (xa_audio_present != XA_AUDIO_OK) return; + + else if (xa_snd_cur) + { int ret; + + /* CHANGE FREQUENCY IF NEEDED */ + if (xa_audio_hard_freq != xa_snd_cur->hfreq) + { audio_info_t a_info; + AUDIO_INITINFO(&a_info); + a_info.play.sample_rate = xa_snd_cur->hfreq; + ret = ioctl(devAudio, AUDIO_SETINFO, &a_info); + if (ret == -1) fprintf(stderr,"audio setfreq: freq %x errno %d\n", + xa_snd_cur->hfreq, errno); + xa_audio_hard_freq = xa_snd_cur->hfreq; + } + + /* xa_snd_cur gets changes in Update_Ring() */ + xa_out_time = 100; /* keep audio fed 500ms ahead of video */ /* was 500, changed it to 100 - rcd */ + xa_out_init = xa_audio_ring_size - 1; + xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest; + if (xa_interval_time == 0) xa_interval_time = 1; + + XA_Flush_Ring(); + XA_Update_Ring(1000); + xa_audio_status = XA_AUDIO_PREPPED; + } +} + +/****-------------------------------------------------------------------**** + * + ****-------------------------------------------------------------------****/ +void OpenBSD_Audio_On() +{ + if ( (xa_snd_cur) + && (xa_audio_present == XA_AUDIO_OK) + && (xa_audio_status == XA_AUDIO_PREPPED) ) + { + xa_audio_status = XA_AUDIO_STARTED; + xa_time_now = XA_Read_AV_Time(); /* get new time */ + New_Merged_Audio_Output(); + } +} + + +/********** OpenBSD_Closest_Freq ********************************************** + * + * Global Variable Affect: + * xaULONG xa_audio_hard_buff must set but not larger than + * XA_AUDIO_MAX_RING_BUF size + ****************************************************************************/ +xaULONG OpenBSD_Closest_Freq(ifreq) +xaLONG ifreq; +{ +static int cache_ifreq =0, cache_ofreq = 0; + if (cache_ifreq == ifreq || cache_ofreq == ifreq) + return cache_ofreq; + else + { audio_info_t a_info; + + AUDIO_INITINFO(&a_info); + a_info.play.sample_rate = ifreq; + ioctl(devAudio, AUDIO_SETINFO, &a_info); + + ioctl(devAudio, AUDIO_GETINFO, &a_info); + + xa_audio_hard_buff = a_info.blocksize; + cache_ifreq = ifreq; + cache_ofreq = a_info.play.sample_rate; + return (a_info.play.sample_rate); + } +} + + +/* Eventually merge everything to one */ +void OpenBSD_Set_Output_Port(aud_ports) +xaULONG aud_ports; +{ +/* Commented out for now ;-) */ +/* +audio_info_t a_info; + xaLONG ret; + xaULONG OpenBSD_ports = 0; + if (aud_ports & XA_AUDIO_PORT_INT) OpenBSD_ports |= AUDIO_SPEAKER; + if (aud_ports & XA_AUDIO_PORT_HEAD) OpenBSD_ports |= AUDIO_HEADPHONE; + if (aud_ports & XA_AUDIO_PORT_EXT) OpenBSD_ports |= AUDIO_LINE_OUT; + AUDIO_INITINFO(&a_info); + a_info.play.port = OpenBSD_ports; + ret = ioctl(devAudio, AUDIO_SETINFO, &a_info); + if (ret < 0) fprintf(stderr,"Audio: couldn't set speaker port %d\n",errno); +*/ +} + +/************* OpenBSD_Speaker_Toggle ***************************************** + * + * flag = 0 turn speaker off + * flag = 1 turn speaker on + * flag = 2 toggle speaker + ****************************************************************************/ +void OpenBSD_Speaker_Toggle(flag) +xaULONG flag; +{ + switch(flag) + { + case 0: XAAUD->port &= ~XA_AUDIO_PORT_INT; break; + case 1: XAAUD->port |= XA_AUDIO_PORT_INT; break; + default: /* mutually exclusive set for now - never turn off */ + { if ( !(XAAUD->port & XA_AUDIO_PORT_INT)) + XAAUD->port = XA_AUDIO_PORT_INT; + } + } + OpenBSD_Set_Output_Port(XAAUD->port); +} + +/************* OpenBSD_Headphone_Toggle ***************************************** + * + * flag = 0 turn headphones off + * flag = 1 turn headphones on + * flag = 2 toggle headphones + ****************************************************************************/ +void OpenBSD_Headphone_Toggle(flag) +xaULONG flag; +{ + switch(flag) + { + case 0: XAAUD->port &= ~XA_AUDIO_PORT_HEAD; break; + case 1: XAAUD->port |= XA_AUDIO_PORT_HEAD; break; + default: /* mutually exclusive set for now - never turn off */ + { if ( !(XAAUD->port & XA_AUDIO_PORT_HEAD)) + XAAUD->port = XA_AUDIO_PORT_HEAD; + } + } + OpenBSD_Set_Output_Port(XAAUD->port); +} + + +/********** OpenBSD_Adjust_Volume ********************** + * Routine for Adjusting Volume on OpenBSD + * + * Volume is in the range [0,XA_AUDIO_MAXVOL] + ****************************************************************************/ +void OpenBSD_Adjust_Volume(volume) +xaULONG volume; +{ audio_info_t a_info; + + AUDIO_INITINFO(&a_info); + a_info.play.gain = OpenBSD_MIN_VOL + + ((volume * (OpenBSD_MAX_VOL - OpenBSD_MIN_VOL)) / XA_AUDIO_MAXVOL); + if (a_info.play.gain > OpenBSD_MAX_VOL) a_info.play.gain = OpenBSD_MAX_VOL; + ioctl(devAudio, AUDIO_SETINFO, &a_info); + +} +#endif +/****************************************************************************/ +/******************* END OF OpenBSD SPECIFIC ROUTINES ************************/ +/****************************************************************************/ + /****************************************************************************/ /**************** TOWNS SPECIFIC ROUTINES ***********************************/ /****************************************************************************/ @@ -5828,29 +6225,15 @@ /*---------------- Now for the Write Segments -------------------------------*/ -#ifdef XA_SPARC_AUDIO +#ifdef XA_NORMAL_AUDIO_WRITES write(devAudio,xa_audio_ring->buf,xa_audio_ring->len); #endif -#ifdef XA_NetBSD_AUDIO - write(devAudio,xa_audio_ring->buf,xa_audio_ring->len); -#endif - -#ifdef XA_AIX_AUDIO - { int rc; - rc = write ( devAudio, xa_audio_ring->buf, xa_audio_ring->len ); - } -#endif - #ifdef XA_SGI_AUDIO /* # of Samples, not Bytes. Note: assume 16 bit samples. */ ALwritesamps(port,xa_audio_ring->buf, (xa_audio_ring->len >> 1) ); #endif -#ifdef XA_LINUX_AUDIO - write(devAudio,xa_audio_ring->buf,xa_audio_ring->len); -#endif - #ifdef XA_NAS_AUDIO NAS_Write_Data(xa_audio_ring->buf, xa_audio_ring->len); #endif @@ -5864,10 +6247,6 @@ } #endif -#ifdef XA_EWS_AUDIO - write(devAudio,xa_audio_ring->buf,xa_audio_ring->len); -#endif - #ifdef XA_AF_AUDIO { ATime act, atd = AFtime0; if (XAAUD->mute != xaTRUE) @@ -5883,10 +6262,6 @@ /* Some way to flush streamsocket???? */ #endif -#ifdef XA_HPDEV_AUDIO - write (devAudio, xa_audio_ring->buf, xa_audio_ring->len); -#endif - #ifdef XA_MMS_AUDIO /* As currently implemented, this copies the audio data into a separate shared memory buffer for communication with the multimedia server. We @@ -5921,10 +6296,6 @@ else { mms_buffers_outstanding++; } } } -#endif - -#ifdef XA_TOWNS_AUDIO - write(devAudio,xa_audio_ring->buf,xa_audio_ring->len); #endif #ifdef XA_TOWNS8_AUDIO