aboutsummaryrefslogtreecommitdiffstats
path: root/distrib/sdl-1.2.15/src/audio/ums/SDL_umsaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'distrib/sdl-1.2.15/src/audio/ums/SDL_umsaudio.c')
-rw-r--r--distrib/sdl-1.2.15/src/audio/ums/SDL_umsaudio.c547
1 files changed, 547 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/audio/ums/SDL_umsaudio.c b/distrib/sdl-1.2.15/src/audio/ums/SDL_umsaudio.c
new file mode 100644
index 0000000..9488911
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/audio/ums/SDL_umsaudio.c
@@ -0,0 +1,547 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Carsten Griwodz
+ griff@kom.tu-darmstadt.de
+
+ based on linux/SDL_dspaudio.c by Sam Lantinga
+*/
+#include "SDL_config.h"
+
+/* Allow access to a raw mixing buffer */
+
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "SDL_audio.h"
+#include "../SDL_audio_c.h"
+#include "../SDL_audiodev_c.h"
+#include "SDL_umsaudio.h"
+
+/* The tag name used by UMS audio */
+#define UMS_DRIVER_NAME "ums"
+
+#define DEBUG_AUDIO 1
+
+/* Audio driver functions */
+static int UMS_OpenAudio(_THIS, SDL_AudioSpec *spec);
+static void UMS_PlayAudio(_THIS);
+static Uint8 *UMS_GetAudioBuf(_THIS);
+static void UMS_CloseAudio(_THIS);
+
+static UMSAudioDevice_ReturnCode UADOpen(_THIS, string device, string mode, long flags);
+static UMSAudioDevice_ReturnCode UADClose(_THIS);
+static UMSAudioDevice_ReturnCode UADGetBitsPerSample(_THIS, long* bits);
+static UMSAudioDevice_ReturnCode UADSetBitsPerSample(_THIS, long bits);
+static UMSAudioDevice_ReturnCode UADSetSampleRate(_THIS, long rate, long* set_rate);
+static UMSAudioDevice_ReturnCode UADSetByteOrder(_THIS, string byte_order);
+static UMSAudioDevice_ReturnCode UADSetAudioFormatType(_THIS, string fmt);
+static UMSAudioDevice_ReturnCode UADSetNumberFormat(_THIS, string fmt);
+static UMSAudioDevice_ReturnCode UADInitialize(_THIS);
+static UMSAudioDevice_ReturnCode UADStart(_THIS);
+static UMSAudioDevice_ReturnCode UADStop(_THIS);
+static UMSAudioDevice_ReturnCode UADSetTimeFormat(_THIS, UMSAudioTypes_TimeFormat fmt );
+static UMSAudioDevice_ReturnCode UADWriteBuffSize(_THIS, long* buff_size );
+static UMSAudioDevice_ReturnCode UADWriteBuffRemain(_THIS, long* buff_size );
+static UMSAudioDevice_ReturnCode UADWriteBuffUsed(_THIS, long* buff_size );
+static UMSAudioDevice_ReturnCode UADSetDMABufferSize(_THIS, long bytes, long* bytes_ret );
+static UMSAudioDevice_ReturnCode UADSetVolume(_THIS, long volume );
+static UMSAudioDevice_ReturnCode UADSetBalance(_THIS, long balance );
+static UMSAudioDevice_ReturnCode UADSetChannels(_THIS, long channels );
+static UMSAudioDevice_ReturnCode UADPlayRemainingData(_THIS, boolean block );
+static UMSAudioDevice_ReturnCode UADEnableOutput(_THIS, string output, long* left_gain, long* right_gain);
+static UMSAudioDevice_ReturnCode UADWrite(_THIS, UMSAudioTypes_Buffer* buff, long samples, long* samples_written);
+
+/* Audio driver bootstrap functions */
+static int Audio_Available(void)
+{
+ return 1;
+}
+
+static void Audio_DeleteDevice(_THIS)
+{
+ if(this->hidden->playbuf._buffer) SDL_free(this->hidden->playbuf._buffer);
+ if(this->hidden->fillbuf._buffer) SDL_free(this->hidden->fillbuf._buffer);
+ _somFree( this->hidden->umsdev );
+ SDL_free(this->hidden);
+ SDL_free(this);
+}
+
+static SDL_AudioDevice *Audio_CreateDevice(int devindex)
+{
+ SDL_AudioDevice *this;
+
+ /*
+ * Allocate and initialize management storage and private management
+ * storage for this SDL-using library.
+ */
+ this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));
+ if ( this ) {
+ SDL_memset(this, 0, (sizeof *this));
+ this->hidden = (struct SDL_PrivateAudioData *)SDL_malloc((sizeof *this->hidden));
+ }
+ if ( (this == NULL) || (this->hidden == NULL) ) {
+ SDL_OutOfMemory();
+ if ( this ) {
+ SDL_free(this);
+ }
+ return(0);
+ }
+ SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "Creating UMS Audio device\n");
+#endif
+
+ /*
+ * Calls for UMS env initialization and audio object construction.
+ */
+ this->hidden->ev = somGetGlobalEnvironment();
+ this->hidden->umsdev = UMSAudioDeviceNew();
+
+ /*
+ * Set the function pointers.
+ */
+ this->OpenAudio = UMS_OpenAudio;
+ this->WaitAudio = NULL; /* we do blocking output */
+ this->PlayAudio = UMS_PlayAudio;
+ this->GetAudioBuf = UMS_GetAudioBuf;
+ this->CloseAudio = UMS_CloseAudio;
+ this->free = Audio_DeleteDevice;
+
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "done\n");
+#endif
+ return this;
+}
+
+AudioBootStrap UMS_bootstrap = {
+ UMS_DRIVER_NAME, "AIX UMS audio",
+ Audio_Available, Audio_CreateDevice
+};
+
+static Uint8 *UMS_GetAudioBuf(_THIS)
+{
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "enter UMS_GetAudioBuf\n");
+#endif
+ return this->hidden->fillbuf._buffer;
+/*
+ long bufSize;
+ UMSAudioDevice_ReturnCode rc;
+
+ rc = UADSetTimeFormat(this, UMSAudioTypes_Bytes );
+ rc = UADWriteBuffSize(this, bufSize );
+*/
+}
+
+static void UMS_CloseAudio(_THIS)
+{
+ UMSAudioDevice_ReturnCode rc;
+
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "enter UMS_CloseAudio\n");
+#endif
+ rc = UADPlayRemainingData(this, TRUE);
+ rc = UADStop(this);
+ rc = UADClose(this);
+}
+
+static void UMS_PlayAudio(_THIS)
+{
+ UMSAudioDevice_ReturnCode rc;
+ long samplesToWrite;
+ long samplesWritten;
+ UMSAudioTypes_Buffer swpbuf;
+
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "enter UMS_PlayAudio\n");
+#endif
+ samplesToWrite = this->hidden->playbuf._length/this->hidden->bytesPerSample;
+ do
+ {
+ rc = UADWrite(this, &this->hidden->playbuf,
+ samplesToWrite,
+ &samplesWritten );
+ samplesToWrite -= samplesWritten;
+
+ /* rc values: UMSAudioDevice_Success
+ * UMSAudioDevice_Failure
+ * UMSAudioDevice_Preempted
+ * UMSAudioDevice_Interrupted
+ * UMSAudioDevice_DeviceError
+ */
+ if ( rc == UMSAudioDevice_DeviceError ) {
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "Returning from PlayAudio with devices error\n");
+#endif
+ return;
+ }
+ }
+ while(samplesToWrite>0);
+
+ SDL_LockAudio();
+ SDL_memcpy( &swpbuf, &this->hidden->playbuf, sizeof(UMSAudioTypes_Buffer) );
+ SDL_memcpy( &this->hidden->playbuf, &this->hidden->fillbuf, sizeof(UMSAudioTypes_Buffer) );
+ SDL_memcpy( &this->hidden->fillbuf, &swpbuf, sizeof(UMSAudioTypes_Buffer) );
+ SDL_UnlockAudio();
+
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "Wrote audio data and swapped buffer\n");
+#endif
+}
+
+#if 0
+// /* Set the DSP frequency */
+// value = spec->freq;
+// if ( ioctl(this->hidden->audio_fd, SOUND_PCM_WRITE_RATE, &value) < 0 ) {
+// SDL_SetError("Couldn't set audio frequency");
+// return(-1);
+// }
+// spec->freq = value;
+#endif
+
+static int UMS_OpenAudio(_THIS, SDL_AudioSpec *spec)
+{
+ char* audiodev = "/dev/paud0";
+ long lgain;
+ long rgain;
+ long outRate;
+ long outBufSize;
+ long bitsPerSample;
+ long samplesPerSec;
+ long success;
+ Uint16 test_format;
+ int frag_spec;
+ UMSAudioDevice_ReturnCode rc;
+
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "enter UMS_OpenAudio\n");
+#endif
+ rc = UADOpen(this, audiodev,"PLAY", UMSAudioDevice_BlockingIO);
+ if ( rc != UMSAudioDevice_Success ) {
+ SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
+ return -1;
+ }
+
+ rc = UADSetAudioFormatType(this, "PCM");
+
+ success = 0;
+ test_format = SDL_FirstAudioFormat(spec->format);
+ do
+ {
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
+#endif
+ switch ( test_format )
+ {
+ case AUDIO_U8:
+/* from the mac code: better ? */
+/* sample_bits = spec->size / spec->samples / spec->channels * 8; */
+ success = 1;
+ bitsPerSample = 8;
+ rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
+ rc = UADSetByteOrder(this, "MSB"); /* irrelevant */
+ rc = UADSetNumberFormat(this, "UNSIGNED");
+ break;
+ case AUDIO_S8:
+ success = 1;
+ bitsPerSample = 8;
+ rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
+ rc = UADSetByteOrder(this, "MSB"); /* irrelevant */
+ rc = UADSetNumberFormat(this, "SIGNED");
+ break;
+ case AUDIO_S16LSB:
+ success = 1;
+ bitsPerSample = 16;
+ rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
+ rc = UADSetByteOrder(this, "LSB");
+ rc = UADSetNumberFormat(this, "SIGNED");
+ break;
+ case AUDIO_S16MSB:
+ success = 1;
+ bitsPerSample = 16;
+ rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
+ rc = UADSetByteOrder(this, "MSB");
+ rc = UADSetNumberFormat(this, "SIGNED");
+ break;
+ case AUDIO_U16LSB:
+ success = 1;
+ bitsPerSample = 16;
+ rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
+ rc = UADSetByteOrder(this, "LSB");
+ rc = UADSetNumberFormat(this, "UNSIGNED");
+ break;
+ case AUDIO_U16MSB:
+ success = 1;
+ bitsPerSample = 16;
+ rc = UADSetSampleRate(this, spec->freq << 16, &outRate );
+ rc = UADSetByteOrder(this, "MSB");
+ rc = UADSetNumberFormat(this, "UNSIGNED");
+ break;
+ default:
+ break;
+ }
+ if ( ! success ) {
+ test_format = SDL_NextAudioFormat();
+ }
+ }
+ while ( ! success && test_format );
+
+ if ( success == 0 ) {
+ SDL_SetError("Couldn't find any hardware audio formats");
+ return -1;
+ }
+
+ spec->format = test_format;
+
+ for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec );
+ if ( (0x01<<frag_spec) != spec->size ) {
+ SDL_SetError("Fragment size must be a power of two");
+ return -1;
+ }
+ if ( frag_spec > 2048 ) frag_spec = 2048;
+
+ this->hidden->bytesPerSample = (bitsPerSample / 8) * spec->channels;
+ samplesPerSec = this->hidden->bytesPerSample * outRate;
+
+ this->hidden->playbuf._length = 0;
+ this->hidden->playbuf._maximum = spec->size;
+ this->hidden->playbuf._buffer = (unsigned char*)SDL_malloc(spec->size);
+ this->hidden->fillbuf._length = 0;
+ this->hidden->fillbuf._maximum = spec->size;
+ this->hidden->fillbuf._buffer = (unsigned char*)SDL_malloc(spec->size);
+
+ rc = UADSetBitsPerSample(this, bitsPerSample );
+ rc = UADSetDMABufferSize(this, frag_spec, &outBufSize );
+ rc = UADSetChannels(this, spec->channels); /* functions reduces to mono or stereo */
+
+ lgain = 100; /*maximum left input gain*/
+ rgain = 100; /*maimum right input gain*/
+ rc = UADEnableOutput(this, "LINE_OUT",&lgain,&rgain);
+ rc = UADInitialize(this);
+ rc = UADStart(this);
+ rc = UADSetVolume(this, 100);
+ rc = UADSetBalance(this, 0);
+
+ /* We're ready to rock and roll. :-) */
+ return 0;
+}
+
+
+static UMSAudioDevice_ReturnCode UADGetBitsPerSample(_THIS, long* bits)
+{
+ return UMSAudioDevice_get_bits_per_sample( this->hidden->umsdev,
+ this->hidden->ev,
+ bits );
+}
+
+static UMSAudioDevice_ReturnCode UADSetBitsPerSample(_THIS, long bits)
+{
+ return UMSAudioDevice_set_bits_per_sample( this->hidden->umsdev,
+ this->hidden->ev,
+ bits );
+}
+
+static UMSAudioDevice_ReturnCode UADSetSampleRate(_THIS, long rate, long* set_rate)
+{
+ /* from the mac code: sample rate = spec->freq << 16; */
+ return UMSAudioDevice_set_sample_rate( this->hidden->umsdev,
+ this->hidden->ev,
+ rate,
+ set_rate );
+}
+
+static UMSAudioDevice_ReturnCode UADSetByteOrder(_THIS, string byte_order)
+{
+ return UMSAudioDevice_set_byte_order( this->hidden->umsdev,
+ this->hidden->ev,
+ byte_order );
+}
+
+static UMSAudioDevice_ReturnCode UADSetAudioFormatType(_THIS, string fmt)
+{
+ /* possible PCM, A_LAW or MU_LAW */
+ return UMSAudioDevice_set_audio_format_type( this->hidden->umsdev,
+ this->hidden->ev,
+ fmt );
+}
+
+static UMSAudioDevice_ReturnCode UADSetNumberFormat(_THIS, string fmt)
+{
+ /* possible SIGNED, UNSIGNED, or TWOS_COMPLEMENT */
+ return UMSAudioDevice_set_number_format( this->hidden->umsdev,
+ this->hidden->ev,
+ fmt );
+}
+
+static UMSAudioDevice_ReturnCode UADInitialize(_THIS)
+{
+ return UMSAudioDevice_initialize( this->hidden->umsdev,
+ this->hidden->ev );
+}
+
+static UMSAudioDevice_ReturnCode UADStart(_THIS)
+{
+ return UMSAudioDevice_start( this->hidden->umsdev,
+ this->hidden->ev );
+}
+
+static UMSAudioDevice_ReturnCode UADSetTimeFormat(_THIS, UMSAudioTypes_TimeFormat fmt )
+{
+ /*
+ * Switches the time format to the new format, immediately.
+ * possible UMSAudioTypes_Msecs, UMSAudioTypes_Bytes or UMSAudioTypes_Samples
+ */
+ return UMSAudioDevice_set_time_format( this->hidden->umsdev,
+ this->hidden->ev,
+ fmt );
+}
+
+static UMSAudioDevice_ReturnCode UADWriteBuffSize(_THIS, long* buff_size )
+{
+ /*
+ * returns write buffer size in the current time format
+ */
+ return UMSAudioDevice_write_buff_size( this->hidden->umsdev,
+ this->hidden->ev,
+ buff_size );
+}
+
+static UMSAudioDevice_ReturnCode UADWriteBuffRemain(_THIS, long* buff_size )
+{
+ /*
+ * returns amount of available space in the write buffer
+ * in the current time format
+ */
+ return UMSAudioDevice_write_buff_remain( this->hidden->umsdev,
+ this->hidden->ev,
+ buff_size );
+}
+
+static UMSAudioDevice_ReturnCode UADWriteBuffUsed(_THIS, long* buff_size )
+{
+ /*
+ * returns amount of filled space in the write buffer
+ * in the current time format
+ */
+ return UMSAudioDevice_write_buff_used( this->hidden->umsdev,
+ this->hidden->ev,
+ buff_size );
+}
+
+static UMSAudioDevice_ReturnCode UADSetDMABufferSize(_THIS, long bytes, long* bytes_ret )
+{
+ /*
+ * Request a new DMA buffer size, maximum requested size 2048.
+ * Takes effect with next initialize() call.
+ * Devices may or may not support DMA.
+ */
+ return UMSAudioDevice_set_DMA_buffer_size( this->hidden->umsdev,
+ this->hidden->ev,
+ bytes,
+ bytes_ret );
+}
+
+static UMSAudioDevice_ReturnCode UADSetVolume(_THIS, long volume )
+{
+ /*
+ * Set the volume.
+ * Takes effect immediately.
+ */
+ return UMSAudioDevice_set_volume( this->hidden->umsdev,
+ this->hidden->ev,
+ volume );
+}
+
+static UMSAudioDevice_ReturnCode UADSetBalance(_THIS, long balance )
+{
+ /*
+ * Set the balance.
+ * Takes effect immediately.
+ */
+ return UMSAudioDevice_set_balance( this->hidden->umsdev,
+ this->hidden->ev,
+ balance );
+}
+
+static UMSAudioDevice_ReturnCode UADSetChannels(_THIS, long channels )
+{
+ /*
+ * Set mono or stereo.
+ * Takes effect with next initialize() call.
+ */
+ if ( channels != 1 ) channels = 2;
+ return UMSAudioDevice_set_number_of_channels( this->hidden->umsdev,
+ this->hidden->ev,
+ channels );
+}
+
+static UMSAudioDevice_ReturnCode UADOpen(_THIS, string device, string mode, long flags)
+{
+ return UMSAudioDevice_open( this->hidden->umsdev,
+ this->hidden->ev,
+ device,
+ mode,
+ flags );
+}
+
+static UMSAudioDevice_ReturnCode UADWrite(_THIS, UMSAudioTypes_Buffer* buff,
+ long samples,
+ long* samples_written)
+{
+ return UMSAudioDevice_write( this->hidden->umsdev,
+ this->hidden->ev,
+ buff,
+ samples,
+ samples_written );
+}
+
+static UMSAudioDevice_ReturnCode UADPlayRemainingData(_THIS, boolean block )
+{
+ return UMSAudioDevice_play_remaining_data( this->hidden->umsdev,
+ this->hidden->ev,
+ block);
+}
+
+static UMSAudioDevice_ReturnCode UADStop(_THIS)
+{
+ return UMSAudioDevice_stop( this->hidden->umsdev,
+ this->hidden->ev );
+}
+
+static UMSAudioDevice_ReturnCode UADClose(_THIS)
+{
+ return UMSAudioDevice_close( this->hidden->umsdev,
+ this->hidden->ev );
+}
+
+static UMSAudioDevice_ReturnCode UADEnableOutput(_THIS, string output, long* left_gain, long* right_gain)
+{
+ return UMSAudioDevice_enable_output( this->hidden->umsdev,
+ this->hidden->ev,
+ output,
+ left_gain,
+ right_gain );
+}
+