* autoload.cc: Add winmm functions needed by fhandler_dsp.cc.
* fhandler_dsp.cc: New file. Implements OSS like /dev/dsp. * include/sys/soundcard.h: New file. User land includes for OSS /dev/dsp. * fhandler.h: Add new class fhandler_dev_dsp and a FH_OSS_DSP definition. * dtable.cc (dtable::build_fhandler): Allow creation of the /dev/dsp device. * path.cc (windows_device_names): Add /dev/dsp into list of device names. * Makefile.in (DLL_OFILES): Add fhandler_dsp.o.
This commit is contained in:
parent
9f42525632
commit
b0a50cf34c
|
@ -1,3 +1,20 @@
|
|||
Sun Apr 15 23:23:29 2001 Christopher Faylor <cgf@cygnus.com>
|
||||
|
||||
* autoload.cc: Add winmm functions needed by fhandler_dsp.cc.
|
||||
|
||||
Sun Apr 15 22:53:52 2001 Andy Younger <andylyounger@hotmail.com>
|
||||
|
||||
* fhandler_dsp.cc: New file. Implements OSS like /dev/dsp.
|
||||
* include/sys/soundcard.h: New file. User land includes for OSS
|
||||
/dev/dsp.
|
||||
* fhandler.h: Add new class fhandler_dev_dsp and a FH_OSS_DSP
|
||||
definition.
|
||||
* dtable.cc (dtable::build_fhandler): Allow creation of the /dev/dsp
|
||||
device.
|
||||
* path.cc (windows_device_names): Add /dev/dsp into list of device
|
||||
names.
|
||||
* Makefile.in (DLL_OFILES): Add fhandler_dsp.o.
|
||||
|
||||
Sun Apr 15 16:36:27 2001 Christopher Faylor <cgf@cygnus.com>
|
||||
|
||||
* uname.c (uname): Default n in in86 to 6 if Windows returns > 6.
|
||||
|
|
|
@ -114,11 +114,10 @@ EXTRA_OFILES=$(bupdir1)/libiberty/random.o $(bupdir1)/libiberty/strsignal.o
|
|||
DLL_IMPORTS:=$(w32api_lib)/libkernel32.a
|
||||
|
||||
DLL_OFILES:=assert.o autoload.o cygheap.o dcrt0.o debug.o delqueue.o dir.o \
|
||||
dlfcn.o \
|
||||
dll_init.o dtable.o environ.o errno.o exceptions.o exec.o external.o \
|
||||
fcntl.o fhandler.o fhandler_clipboard.o fhandler_console.o \
|
||||
fhandler_floppy.o fhandler_mem.o fhandler_random.o fhandler_raw.o \
|
||||
fhandler_serial.o fhandler_socket.o fhandler_tape.o \
|
||||
dlfcn.o dll_init.o dtable.o environ.o errno.o exceptions.o exec.o \
|
||||
external.o fcntl.o fhandler.o fhandler_clipboard.o fhandler_console.o \
|
||||
fhandler_dsp.o fhandler_floppy.o fhandler_mem.o fhandler_random.o \
|
||||
fhandler_raw.o fhandler_serial.o fhandler_socket.o fhandler_tape.o \
|
||||
fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \
|
||||
fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o \
|
||||
miscfuncs.o mmap.o net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o \
|
||||
|
@ -190,7 +189,7 @@ new-$(LIB_NAME): $(LIB_NAME)
|
|||
|
||||
new-$(DLL_NAME): $(DLL_OFILES) $(DEF_FILE) $(DLL_IMPORTS) $(LIBC) $(LIBM) Makefile winver_stamp
|
||||
$(CXX) $(CXXFLAGS) -nostdlib -Wl,-shared -o $@ -e $(DLL_ENTRY) $(DEF_FILE) $(DLL_OFILES) version.o \
|
||||
winver.o $(DLL_IMPORTS) $(MALLOC_OBJ) $(LIBM) $(LIBC) -lstdc++ -lshell32 -luuid -lgcc
|
||||
winver.o $(DLL_IMPORTS) $(MALLOC_OBJ) $(LIBM) $(LIBC) -lstdc++ -lgcc -lshell32 -luuid
|
||||
|
||||
dll_ofiles: $(DLL_OFILES)
|
||||
|
||||
|
|
|
@ -102,6 +102,8 @@ LoadDLLinitfunc (netapi32)
|
|||
netapi32_handle = h;
|
||||
else if (! netapi32_handle)
|
||||
api_fatal ("could not load netapi32.dll. %d", GetLastError ());
|
||||
|
||||
InterlockedDecrement (&here);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -228,19 +230,38 @@ LoadDLLinitfunc (ole32)
|
|||
|
||||
LoadDLLinitfunc (kernel32)
|
||||
{
|
||||
extern void wsock_init ();
|
||||
HANDLE h;
|
||||
|
||||
if ((h = LoadLibrary ("kernel32.dll")) != NULL)
|
||||
kernel32_handle = h;
|
||||
else if (!kernel32_handle)
|
||||
api_fatal ("could not load wsock32.dll. Is TCP/IP installed?");
|
||||
api_fatal ("could not load kernel32.dll, %E");
|
||||
else
|
||||
return 0; /* Already done by another thread? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LoadDLLinitfunc (winmm)
|
||||
{
|
||||
HANDLE h;
|
||||
static NO_COPY LONG here = -1L;
|
||||
|
||||
while (InterlockedIncrement (&here))
|
||||
{
|
||||
InterlockedDecrement (&here);
|
||||
Sleep (0);
|
||||
}
|
||||
|
||||
if ((h = LoadLibrary ("winmm.dll")) != NULL)
|
||||
winmm_handle = h;
|
||||
else if (! winmm_handle)
|
||||
api_fatal ("could not load winmm.dll. %d", GetLastError ());
|
||||
|
||||
InterlockedDecrement (&here);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __stdcall dummy_autoload (void) __attribute__ ((unused));
|
||||
static void __stdcall
|
||||
dummy_autoload (void)
|
||||
|
@ -396,5 +417,16 @@ LoadDLLfunc (CoCreateInstance, 20, ole32)
|
|||
|
||||
LoadDLLinit (kernel32)
|
||||
LoadDLLfuncEx (SignalObjectAndWait, 16, kernel32, 1)
|
||||
|
||||
LoadDLLinit (winmm)
|
||||
LoadDLLfuncEx (waveOutGetNumDevs, 0, winmm, 1)
|
||||
LoadDLLfuncEx (waveOutOpen, 24, winmm, 1)
|
||||
LoadDLLfuncEx (waveOutReset, 4, winmm, 1)
|
||||
LoadDLLfuncEx (waveOutClose, 4, winmm, 1)
|
||||
LoadDLLfuncEx (waveOutGetVolume, 8, winmm, 1)
|
||||
LoadDLLfuncEx (waveOutSetVolume, 8, winmm, 1)
|
||||
LoadDLLfuncEx (waveOutUnprepareHeader, 12, winmm, 1)
|
||||
LoadDLLfuncEx (waveOutPrepareHeader, 12, winmm, 1)
|
||||
LoadDLLfuncEx (waveOutWrite, 12, winmm, 1)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -316,6 +316,9 @@ dtable::build_fhandler (int fd, DWORD dev, const char *name, int unit)
|
|||
case FH_CLIPBOARD:
|
||||
fh = new (buf) fhandler_dev_clipboard (name);
|
||||
break;
|
||||
case FH_OSS_DSP:
|
||||
fh = new (buf) fhandler_dev_dsp (name);
|
||||
break;
|
||||
default:
|
||||
/* FIXME - this could recurse forever */
|
||||
return build_fhandler (fd, name, NULL);
|
||||
|
|
|
@ -88,7 +88,7 @@ enum
|
|||
FH_PIPEW = 0x0000000a, /* write end of a pipe */
|
||||
FH_SOCKET = 0x0000000b, /* is a socket */
|
||||
FH_WINDOWS = 0x0000000c, /* is a window */
|
||||
|
||||
FH_OSS_DSP = 0x0000000d, /* is the dsp audio device */
|
||||
FH_SLOW = 0x00000010, /* "slow" device if below this */
|
||||
|
||||
/* Fast devices */
|
||||
|
@ -941,6 +941,29 @@ public:
|
|||
int ready_for_read (int fd, DWORD howlong, int ignra);
|
||||
};
|
||||
|
||||
class fhandler_dev_dsp : public fhandler_base
|
||||
{
|
||||
private:
|
||||
int audioformat_;
|
||||
int audiofreq_;
|
||||
int audiobits_;
|
||||
int audiochannels_;
|
||||
bool setupwav(const char *pData, int nBytes);
|
||||
|
||||
public:
|
||||
fhandler_dev_dsp (const char *name = 0);
|
||||
~fhandler_dev_dsp();
|
||||
|
||||
int open (const char *path, int flags, mode_t mode = 0);
|
||||
int write (const void *ptr, size_t len);
|
||||
int read (void *ptr, size_t len);
|
||||
int ioctl (unsigned int cmd, void *);
|
||||
off_t lseek (off_t, int);
|
||||
int close (void);
|
||||
int dup (fhandler_base * child);
|
||||
void dump (void);
|
||||
};
|
||||
|
||||
#if 0
|
||||
/* You can't do this */
|
||||
typedef union
|
||||
|
|
|
@ -0,0 +1,604 @@
|
|||
/* fhandler_dev_dsp: code to emulate OSS sound model /dev/dsp
|
||||
|
||||
Copyright 2001 Red Hat, Inc
|
||||
|
||||
Written by Andy Younger (andy@snoogie.demon.co.uk)
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include "winsup.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "cygerrno.h"
|
||||
#include "fhandler.h"
|
||||
#include <windows.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Simple encapsulation of the win32 audio device.
|
||||
//
|
||||
static void CALLBACK wave_callback(HWAVE hWave, UINT msg, DWORD instance,
|
||||
DWORD param1, DWORD param2);
|
||||
class Audio
|
||||
{
|
||||
public:
|
||||
enum { MAX_BLOCKS = 8, BLOCK_SIZE = 16384 };
|
||||
|
||||
Audio ();
|
||||
~Audio ();
|
||||
|
||||
bool open (int rate, int bits, int channels, bool bCallback = false);
|
||||
void close ();
|
||||
int getvolume ();
|
||||
void setvolume (int newVolume);
|
||||
bool write (const void *pSampleData, int nBytes);
|
||||
int blocks ();
|
||||
void callback_sampledone (void *pData);
|
||||
|
||||
int numbytesoutput ();
|
||||
|
||||
private:
|
||||
char *initialisebuffer ();
|
||||
void waitforcallback ();
|
||||
bool flush ();
|
||||
|
||||
HWAVEOUT dev_;
|
||||
volatile int nBlocksInQue_;
|
||||
int nBytesWritten_;
|
||||
char *buffer_;
|
||||
int bufferIndex_;
|
||||
CRITICAL_SECTION lock_;
|
||||
char *freeblocks_[MAX_BLOCKS];
|
||||
|
||||
char bigwavebuffer_[MAX_BLOCKS * BLOCK_SIZE];
|
||||
};
|
||||
|
||||
Audio::Audio()
|
||||
{
|
||||
int size = BLOCK_SIZE + sizeof(WAVEHDR);
|
||||
|
||||
InitializeCriticalSection(&lock_);
|
||||
memset(freeblocks_, 0, sizeof(freeblocks_));
|
||||
for (int i = 0; i < MAX_BLOCKS; i++)
|
||||
{
|
||||
char *pBuffer = &bigwavebuffer_[ i * size ];
|
||||
memset(pBuffer, 0, size);
|
||||
freeblocks_[i] = pBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
Audio::~Audio()
|
||||
{
|
||||
if (dev_)
|
||||
close();
|
||||
DeleteCriticalSection(&lock_);
|
||||
}
|
||||
|
||||
bool
|
||||
Audio::open(int rate, int bits, int channels, bool bCallback = false)
|
||||
{
|
||||
WAVEFORMATEX format;
|
||||
int nDevices = waveOutGetNumDevs();
|
||||
|
||||
nBytesWritten_ = 0L;
|
||||
bufferIndex_ = 0;
|
||||
buffer_ = 0L;
|
||||
debug_printf("number devices %d\n", nDevices);
|
||||
if (nDevices <= 0)
|
||||
return false;
|
||||
|
||||
debug_printf("trying to map device freq %d, bits %d, "
|
||||
"channels %d, callback %d\n", rate, bits, channels,
|
||||
bCallback);
|
||||
|
||||
int bytesperSample = bits / 8;
|
||||
|
||||
memset(&format, 0, sizeof(format));
|
||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
format.wBitsPerSample = bits;
|
||||
format.nChannels = channels;
|
||||
format.nSamplesPerSec = rate;
|
||||
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nChannels *
|
||||
bytesperSample;
|
||||
format.nBlockAlign = format.nChannels * bytesperSample;
|
||||
|
||||
nBlocksInQue_ = 0;
|
||||
HRESULT res = waveOutOpen(&dev_, WAVE_MAPPER, &format, (DWORD)wave_callback,
|
||||
(DWORD)this, bCallback ? CALLBACK_FUNCTION : 0);
|
||||
if (res == S_OK)
|
||||
{
|
||||
debug_printf("Sucessfully opened!");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf("failed to open");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Audio::close()
|
||||
{
|
||||
if (dev_)
|
||||
{
|
||||
flush(); // force out last block whatever size..
|
||||
|
||||
while (blocks()) // block till finished..
|
||||
waitforcallback();
|
||||
|
||||
waveOutReset(dev_);
|
||||
waveOutClose(dev_);
|
||||
dev_ = 0L;
|
||||
}
|
||||
nBytesWritten_ = 0L;
|
||||
}
|
||||
|
||||
int
|
||||
Audio::numbytesoutput()
|
||||
{
|
||||
return nBytesWritten_;
|
||||
}
|
||||
|
||||
int
|
||||
Audio::getvolume()
|
||||
{
|
||||
DWORD volume;
|
||||
|
||||
waveOutGetVolume(dev_, &volume);
|
||||
return ((volume >> 16) + (volume & 0xffff)) >> 1;
|
||||
}
|
||||
|
||||
void
|
||||
Audio::setvolume(int newVolume)
|
||||
{
|
||||
waveOutSetVolume(dev_, (newVolume<<16)|newVolume);
|
||||
}
|
||||
|
||||
char *
|
||||
Audio::initialisebuffer()
|
||||
{
|
||||
EnterCriticalSection(&lock_);
|
||||
WAVEHDR *pHeader = 0L;
|
||||
for (int i = 0; i < MAX_BLOCKS; i++)
|
||||
{
|
||||
char *pData = freeblocks_[i];
|
||||
if (pData)
|
||||
{
|
||||
pHeader = (WAVEHDR *)pData;
|
||||
if (pHeader->dwFlags & WHDR_DONE)
|
||||
{
|
||||
waveOutUnprepareHeader(dev_, pHeader, sizeof(WAVEHDR));
|
||||
}
|
||||
freeblocks_[i] = 0L;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&lock_);
|
||||
|
||||
if (pHeader)
|
||||
{
|
||||
memset(pHeader, 0, sizeof(WAVEHDR));
|
||||
pHeader->dwBufferLength = BLOCK_SIZE;
|
||||
pHeader->lpData = (LPSTR)(&pHeader[1]);
|
||||
return (char *)pHeader->lpData;
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
bool
|
||||
Audio::write(const void *pSampleData, int nBytes)
|
||||
{
|
||||
// split up big blocks into smaller BLOCK_SIZE chunks
|
||||
while (nBytes > BLOCK_SIZE)
|
||||
{
|
||||
write(pSampleData, BLOCK_SIZE);
|
||||
nBytes -= BLOCK_SIZE;
|
||||
pSampleData = (void *)((char *)pSampleData + BLOCK_SIZE);
|
||||
}
|
||||
|
||||
// Block till next sound is flushed
|
||||
if (blocks() == MAX_BLOCKS)
|
||||
waitforcallback();
|
||||
|
||||
// Allocate new wave buffer if necessary
|
||||
if (buffer_ == 0L)
|
||||
{
|
||||
buffer_ = initialisebuffer();
|
||||
if (buffer_ == 0L)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Handle gathering blocks into larger buffer
|
||||
int sizeleft = BLOCK_SIZE - bufferIndex_;
|
||||
if (nBytes < sizeleft)
|
||||
{
|
||||
memcpy(&buffer_[bufferIndex_], pSampleData, nBytes);
|
||||
bufferIndex_ += nBytes;
|
||||
nBytesWritten_ += nBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// flushing when we reach our limit of BLOCK_SIZE
|
||||
memcpy(&buffer_[bufferIndex_], pSampleData, sizeleft);
|
||||
bufferIndex_ += sizeleft;
|
||||
nBytesWritten_ += sizeleft;
|
||||
flush();
|
||||
|
||||
// change pointer to rest of sample, and size accordingly
|
||||
pSampleData = (void *)((char *)pSampleData + sizeleft);
|
||||
nBytes -= sizeleft;
|
||||
|
||||
// if we still have some sample left over write it out
|
||||
if (nBytes)
|
||||
return write(pSampleData, nBytes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// return number of blocks back.
|
||||
int
|
||||
Audio::blocks()
|
||||
{
|
||||
EnterCriticalSection(&lock_);
|
||||
int ret = nBlocksInQue_;
|
||||
LeaveCriticalSection(&lock_);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This is called on an interupt so use locking.. Note nBlocksInQue_ is
|
||||
// modified by it so we should wrap all references to it in locks.
|
||||
void
|
||||
Audio::callback_sampledone(void *pData)
|
||||
{
|
||||
EnterCriticalSection(&lock_);
|
||||
|
||||
nBlocksInQue_--;
|
||||
for (int i = 0; i < MAX_BLOCKS; i++)
|
||||
if (!freeblocks_[i])
|
||||
{
|
||||
freeblocks_[i] = (char *)pData;
|
||||
break;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock_);
|
||||
}
|
||||
|
||||
void
|
||||
Audio::waitforcallback()
|
||||
{
|
||||
int n = blocks();
|
||||
if (!n)
|
||||
return;
|
||||
do
|
||||
{
|
||||
Sleep(250);
|
||||
}
|
||||
while (n == blocks());
|
||||
}
|
||||
|
||||
bool
|
||||
Audio::flush()
|
||||
{
|
||||
if (!buffer_)
|
||||
return false;
|
||||
|
||||
// Send internal buffer out to the soundcard
|
||||
WAVEHDR *pHeader = ((WAVEHDR *)buffer_) - 1;
|
||||
pHeader->dwBufferLength = bufferIndex_;
|
||||
if (waveOutPrepareHeader(dev_, pHeader, sizeof(WAVEHDR)) == S_OK &&
|
||||
waveOutWrite(dev_, pHeader, sizeof (WAVEHDR)) == S_OK)
|
||||
{
|
||||
EnterCriticalSection(&lock_);
|
||||
nBlocksInQue_++;
|
||||
LeaveCriticalSection(&lock_);
|
||||
bufferIndex_ = 0;
|
||||
buffer_ = 0L;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterCriticalSection(&lock_);
|
||||
for (int i = 0; i < MAX_BLOCKS; i++)
|
||||
if (!freeblocks_[i])
|
||||
{
|
||||
freeblocks_[i] = (char *)pHeader;
|
||||
break;
|
||||
}
|
||||
LeaveCriticalSection(&lock_);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Call back routine
|
||||
static void CALLBACK
|
||||
wave_callback(HWAVE hWave, UINT msg, DWORD instance, DWORD param1, DWORD param2)
|
||||
{
|
||||
if (msg == WOM_DONE)
|
||||
{
|
||||
Audio *ptr = (Audio *)instance;
|
||||
ptr->callback_sampledone((void *)param1);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// /dev/dsp handler
|
||||
static Audio s_audio; // static instance of the Audio handler
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// wav file detection..
|
||||
#pragma pack(1)
|
||||
struct wavchunk
|
||||
{
|
||||
char id[4];
|
||||
unsigned int len;
|
||||
};
|
||||
struct wavformat
|
||||
{
|
||||
unsigned short wFormatTag;
|
||||
unsigned short wChannels;
|
||||
unsigned int dwSamplesPerSec;
|
||||
unsigned int dwAvgBytesPerSec;
|
||||
unsigned short wBlockAlign;
|
||||
unsigned short wBitsPerSample;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
bool
|
||||
fhandler_dev_dsp::setupwav(const char *pData, int nBytes)
|
||||
{
|
||||
int len;
|
||||
const char *end = pData + nBytes;
|
||||
|
||||
if (!(pData[0] == 'R' && pData[1] == 'I' &&
|
||||
pData[2] == 'F' && pData[3] == 'F'))
|
||||
return false;
|
||||
if (!(pData[8] == 'W' && pData[9] == 'A' &&
|
||||
pData[10] == 'V' && pData[11] == 'E'))
|
||||
return false;
|
||||
|
||||
len = *(int *)&pData[4];
|
||||
pData += 12;
|
||||
while (len && pData < end)
|
||||
{
|
||||
wavchunk *pChunk = (wavchunk *)pData;
|
||||
int blklen = pChunk->len;
|
||||
if (pChunk->id[0] == 'f' && pChunk->id[1] == 'm' &&
|
||||
pChunk->id[2] == 't' && pChunk->id[3] == ' ')
|
||||
{
|
||||
wavformat *format = (wavformat *)(pChunk+1);
|
||||
if ((char *)(format+1) > end)
|
||||
return false;
|
||||
|
||||
// Open up audio device with correct frequency for wav file
|
||||
//
|
||||
// FIXME: should through away all the header & not output
|
||||
// it to the soundcard.
|
||||
s_audio.close();
|
||||
if (s_audio.open(format->dwSamplesPerSec, format->wBitsPerSample,
|
||||
format->wChannels) == false)
|
||||
{
|
||||
s_audio.open(audiofreq_, audiobits_, audiochannels_);
|
||||
}
|
||||
else
|
||||
{
|
||||
audiofreq_ = format->dwSamplesPerSec;
|
||||
audiobits_ = format->wBitsPerSample;
|
||||
audiochannels_ = format->wChannels;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
pData += blklen + sizeof(wavchunk);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
fhandler_dev_dsp::fhandler_dev_dsp (const char *name)
|
||||
: fhandler_base (FH_OSS_DSP, name)
|
||||
{
|
||||
set_cb (sizeof *this);
|
||||
}
|
||||
|
||||
fhandler_dev_dsp::~fhandler_dev_dsp()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_dev_dsp::open (const char *path, int flags, mode_t mode = 0)
|
||||
{
|
||||
// currently we only support writing
|
||||
if ((flags & (O_WRONLY|O_RDONLY|O_RDWR)) != O_WRONLY)
|
||||
return 0;
|
||||
|
||||
set_flags(flags);
|
||||
|
||||
// Work out initial sample format & frequency
|
||||
if (strcmp(path, "/dev/dsp") == 0L)
|
||||
{
|
||||
// dev/dsp defaults
|
||||
audioformat_ = AFMT_S8;
|
||||
audiofreq_ = 8000;
|
||||
audiobits_ = 8;
|
||||
audiochannels_ = 1;
|
||||
}
|
||||
|
||||
if (s_audio.open(audiofreq_, audiobits_, audiochannels_))
|
||||
debug_printf("/dev/dsp: successfully opened\n");
|
||||
else
|
||||
debug_printf("/dev/dsp: failed to open\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_dev_dsp::write (const void *ptr, size_t len)
|
||||
{
|
||||
if (s_audio.numbytesoutput() == 0)
|
||||
{
|
||||
// check for wave file & setup frequencys properly if possible.
|
||||
setupwav((const char *)ptr, len);
|
||||
|
||||
// Open audio device properly with callbacks.
|
||||
s_audio.close();
|
||||
if (!s_audio.open(audiofreq_, audiobits_, audiochannels_, true))
|
||||
return 0;
|
||||
}
|
||||
|
||||
s_audio.write(ptr, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_dev_dsp::read (void *ptr, size_t len)
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
off_t
|
||||
fhandler_dev_dsp::lseek (off_t offset, int whence)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_dev_dsp::close (void)
|
||||
{
|
||||
s_audio.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_dev_dsp::dup (fhandler_base * child)
|
||||
{
|
||||
fhandler_dev_dsp *fhc = (fhandler_dev_dsp *)child;
|
||||
|
||||
fhc->set_flags(get_flags());
|
||||
fhc->audiochannels_ = audiochannels_;
|
||||
fhc->audiobits_ = audiobits_;
|
||||
fhc->audiofreq_ = audiofreq_;
|
||||
fhc->audioformat_ = audioformat_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_dev_dsp::ioctl(unsigned int cmd, void *ptr)
|
||||
{
|
||||
int *intptr = (int *)ptr;
|
||||
switch (cmd)
|
||||
{
|
||||
#define CASE(a) case a : debug_printf("/dev/dsp: ioctl %s\n", #a);
|
||||
|
||||
CASE(SNDCTL_DSP_RESET)
|
||||
audioformat_ = AFMT_S8;
|
||||
audiofreq_ = 8000;
|
||||
audiobits_ = 8;
|
||||
audiochannels_ = 1;
|
||||
return 1;
|
||||
|
||||
CASE(SNDCTL_DSP_GETBLKSIZE)
|
||||
*intptr = Audio::BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
CASE(SNDCTL_DSP_SETFMT)
|
||||
{
|
||||
int nBits = 0;
|
||||
if (*intptr == AFMT_S16_LE)
|
||||
nBits = 16;
|
||||
else if (*intptr == AFMT_S8)
|
||||
nBits = 8;
|
||||
if (nBits)
|
||||
{
|
||||
s_audio.close();
|
||||
if (s_audio.open(audiofreq_, nBits, audiochannels_) == true)
|
||||
{
|
||||
audiobits_ = nBits;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_audio.open(audiofreq_, audiobits_, audiochannels_);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
CASE(SNDCTL_DSP_SPEED)
|
||||
s_audio.close();
|
||||
if (s_audio.open(*intptr, audiobits_, audiochannels_) == true)
|
||||
{
|
||||
audiofreq_ = *intptr;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_audio.open(audiofreq_, audiobits_, audiochannels_);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
CASE(SNDCTL_DSP_STEREO)
|
||||
{
|
||||
int nChannels = *intptr + 1;
|
||||
|
||||
s_audio.close();
|
||||
if (s_audio.open(audiofreq_, audiobits_, nChannels) == true)
|
||||
{
|
||||
audiochannels_ = nChannels;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_audio.open(audiofreq_, audiobits_, audiochannels_);
|
||||
return -1;
|
||||
}
|
||||
} break;
|
||||
|
||||
CASE(SNDCTL_DSP_GETOSPACE)
|
||||
{
|
||||
audio_buf_info *p = (audio_buf_info *)ptr;
|
||||
|
||||
int nBlocks = s_audio.blocks();
|
||||
int leftblocks = ((Audio::MAX_BLOCKS - nBlocks)-1);
|
||||
if (leftblocks < 0) leftblocks = 0;
|
||||
if (leftblocks > 1)
|
||||
leftblocks = 1;
|
||||
int left = leftblocks * Audio::BLOCK_SIZE;
|
||||
|
||||
p->fragments = leftblocks;
|
||||
p->fragstotal = Audio::MAX_BLOCKS;
|
||||
p->fragsize = Audio::BLOCK_SIZE;
|
||||
p->bytes = left;
|
||||
|
||||
debug_printf("ptr: %p "
|
||||
"nblocks: %d "
|
||||
"leftblocks: %d "
|
||||
"left bytes: %d ", ptr, nBlocks, leftblocks, left);
|
||||
|
||||
|
||||
return 1;
|
||||
} break;
|
||||
|
||||
default:
|
||||
debug_printf("/dev/dsp: ioctl not handled yet! FIXME:\n");
|
||||
break;
|
||||
|
||||
#undef CASE
|
||||
};
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_dev_dsp::dump ()
|
||||
{
|
||||
paranoid_printf("here, fhandler_dev_dsp");
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -535,8 +535,9 @@ const char *windows_device_names[] =
|
|||
"\\dev\\pipew",
|
||||
"\\dev\\socket",
|
||||
"\\dev\\windows",
|
||||
|
||||
NULL, NULL, NULL,
|
||||
"\\dev\\dsp",
|
||||
|
||||
NULL, NULL,
|
||||
|
||||
"\\dev\\disk",
|
||||
"\\dev\\fd%d",
|
||||
|
@ -602,6 +603,8 @@ get_device_number (const char *name, int &unit, BOOL from_conv)
|
|||
devn = FH_PTYM;
|
||||
else if (deveq ("windows"))
|
||||
devn = FH_WINDOWS;
|
||||
else if (deveq ("dsp"))
|
||||
devn = FH_OSS_DSP;
|
||||
else if (deveq ("conin"))
|
||||
devn = FH_CONIN;
|
||||
else if (deveq ("conout"))
|
||||
|
|
Loading…
Reference in New Issue