newlib-cygwin/winsup/cygwin/fhandler_dsp.cc

654 lines
14 KiB
C++
Raw Normal View History

/* fhandler_dev_dsp: code to emulate OSS sound model /dev/dsp
Copyright 2001, 2002, 2003 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 <windows.h>
#include <sys/soundcard.h>
#include <mmsystem.h>
#include "cygerrno.h"
#include "security.h"
#include "fhandler.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 = 12,
BLOCK_SIZE = 16384,
TOT_BLOCK_SIZE = BLOCK_SIZE + sizeof (WAVEHDR)
};
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);
void setformat (int format) {formattype_ = format;}
int numbytesoutput ();
void *operator new (size_t, void *p) {return p;}
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];
int formattype_;
char bigwavebuffer_[MAX_BLOCKS * TOT_BLOCK_SIZE];
};
static char audio_buf[sizeof (class Audio)];
Audio::Audio ()
{
InitializeCriticalSection (&lock_);
memset (bigwavebuffer_, 0, sizeof (bigwavebuffer_));
for (int i = 0; i < MAX_BLOCKS; i++)
freeblocks_[i] = &bigwavebuffer_[i * TOT_BLOCK_SIZE];
}
Audio::~Audio ()
{
if (dev_)
close ();
DeleteCriticalSection (&lock_);
}
bool
Audio::open (int rate, int bits, int channels, bool bCallback)
{
WAVEFORMATEX format;
int nDevices = waveOutGetNumDevs ();
nBytesWritten_ = 0L;
bufferIndex_ = 0;
buffer_ = 0L;
debug_printf ("number devices %d", nDevices);
if (nDevices <= 0)
return false;
debug_printf ("trying to map device freq %d, bits %d, "
"channels %d, callback %d", 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_;
// Quick bit of sample buffer conversion
if (formattype_ == AFMT_S8)
{
unsigned char *p = ((unsigned char *) buffer_);
for (int i = 0; i < bufferIndex_; i++)
{
p[i] -= 0x7f;
}
}
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 ():
fhandler_base (FH_OSS_DSP)
{
}
fhandler_dev_dsp::~fhandler_dev_dsp ()
{
}
int
fhandler_dev_dsp::open (path_conv *, int flags, mode_t mode)
{
// currently we only support writing
if ((flags & (O_WRONLY | O_RDONLY | O_RDWR)) != O_WRONLY)
{
set_errno (EACCES);
return 0;
}
set_flags ((flags & ~O_TEXT) | O_BINARY);
if (!s_audio)
s_audio = new (audio_buf) Audio;
// Work out initial sample format & frequency
// dev/dsp defaults
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 10:34:20 +08:00
audioformat_ = AFMT_S8;
audiofreq_ = 8000;
audiobits_ = 8;
audiochannels_ = 1;
Remove fcntl.h includes throughout. * fhandler.h: Move fcntl.h include here. (fhandler_base::set_flags): Accept supplied_bin argument. Make non-inlined. * dtable.cc (dtable::init_std_file_from_handle): Just use binmode from pc. (reset_to_open_binmode): Use set_flags. * cygwin.din (open): Avoid newlib wrapper. (read): Ditto. (unlink): Ditto. (write): Ditto. * fhandler.cc (fhandler_base::set_flags): Accept supplied_bin argument. Make binmode decisions here. (fhandler_base::open): Avoid using pc if it is NULL. Eliminate binmode logic. Just call set_flags with binmode argument. (fhandler_base::init): Call set_flags with binmode argument. * fhandler_clipboard.cc (fhandler_dev_clipboard::open): Ditto. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::init): Force binary on open. * fhandler_disk_file.cc (fhandler_disk_file::open): Don't set binmode here. Let it happen in base class. * fhandler_dsp.cc (fhandler_dev_dsp::open): Force binmode open. Set return value appropriately if unable to open. * fhandler_proc.cc (fhandler_proc::open): Make sure flags are set before open_status. * fhandler_process.cc (fhandler_process::open): Ditto. * fhandler_registry.cc (fhandler_registry::open): Ditto. * fhandler_random.cc (fhandler_dev_random::fhandler_dev_random): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Force O_BINARY by default. * fhandler_serial.cc (fhandler_serial::init): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_virtual.cc (fhandler_virtual::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * net.cc (fdsock): Ditto. * path.cc (path_conv::check): Avoid checking for extension when error or directory. (set_flags): Set PATH_TEXT explicitly, when appropriate. (mount_info::conv_to_win32_path): Use set_flags() to set path flags. * path.h (PATH_TEXT): New enum. (path_conv::binmode): Return appropriate constant based on binmode. * pipe.cc (make_pipe): Set binmode to O_TEXT xor O_BINARY. * syscalls.cc (setmode_helper): Make debugging message a little clearer. (setmode): Set binmode via set_flags.
2002-06-05 09:42:28 +08:00
int res;
if (!s_audio->open (audiofreq_, audiobits_, audiochannels_))
Remove fcntl.h includes throughout. * fhandler.h: Move fcntl.h include here. (fhandler_base::set_flags): Accept supplied_bin argument. Make non-inlined. * dtable.cc (dtable::init_std_file_from_handle): Just use binmode from pc. (reset_to_open_binmode): Use set_flags. * cygwin.din (open): Avoid newlib wrapper. (read): Ditto. (unlink): Ditto. (write): Ditto. * fhandler.cc (fhandler_base::set_flags): Accept supplied_bin argument. Make binmode decisions here. (fhandler_base::open): Avoid using pc if it is NULL. Eliminate binmode logic. Just call set_flags with binmode argument. (fhandler_base::init): Call set_flags with binmode argument. * fhandler_clipboard.cc (fhandler_dev_clipboard::open): Ditto. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::init): Force binary on open. * fhandler_disk_file.cc (fhandler_disk_file::open): Don't set binmode here. Let it happen in base class. * fhandler_dsp.cc (fhandler_dev_dsp::open): Force binmode open. Set return value appropriately if unable to open. * fhandler_proc.cc (fhandler_proc::open): Make sure flags are set before open_status. * fhandler_process.cc (fhandler_process::open): Ditto. * fhandler_registry.cc (fhandler_registry::open): Ditto. * fhandler_random.cc (fhandler_dev_random::fhandler_dev_random): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Force O_BINARY by default. * fhandler_serial.cc (fhandler_serial::init): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_virtual.cc (fhandler_virtual::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * net.cc (fdsock): Ditto. * path.cc (path_conv::check): Avoid checking for extension when error or directory. (set_flags): Set PATH_TEXT explicitly, when appropriate. (mount_info::conv_to_win32_path): Use set_flags() to set path flags. * path.h (PATH_TEXT): New enum. (path_conv::binmode): Return appropriate constant based on binmode. * pipe.cc (make_pipe): Set binmode to O_TEXT xor O_BINARY. * syscalls.cc (setmode_helper): Make debugging message a little clearer. (setmode): Set binmode via set_flags.
2002-06-05 09:42:28 +08:00
res = 0;
else
{
set_open_status ();
Remove fcntl.h includes throughout. * fhandler.h: Move fcntl.h include here. (fhandler_base::set_flags): Accept supplied_bin argument. Make non-inlined. * dtable.cc (dtable::init_std_file_from_handle): Just use binmode from pc. (reset_to_open_binmode): Use set_flags. * cygwin.din (open): Avoid newlib wrapper. (read): Ditto. (unlink): Ditto. (write): Ditto. * fhandler.cc (fhandler_base::set_flags): Accept supplied_bin argument. Make binmode decisions here. (fhandler_base::open): Avoid using pc if it is NULL. Eliminate binmode logic. Just call set_flags with binmode argument. (fhandler_base::init): Call set_flags with binmode argument. * fhandler_clipboard.cc (fhandler_dev_clipboard::open): Ditto. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::init): Force binary on open. * fhandler_disk_file.cc (fhandler_disk_file::open): Don't set binmode here. Let it happen in base class. * fhandler_dsp.cc (fhandler_dev_dsp::open): Force binmode open. Set return value appropriately if unable to open. * fhandler_proc.cc (fhandler_proc::open): Make sure flags are set before open_status. * fhandler_process.cc (fhandler_process::open): Ditto. * fhandler_registry.cc (fhandler_registry::open): Ditto. * fhandler_random.cc (fhandler_dev_random::fhandler_dev_random): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Force O_BINARY by default. * fhandler_serial.cc (fhandler_serial::init): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_virtual.cc (fhandler_virtual::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * net.cc (fdsock): Ditto. * path.cc (path_conv::check): Avoid checking for extension when error or directory. (set_flags): Set PATH_TEXT explicitly, when appropriate. (mount_info::conv_to_win32_path): Use set_flags() to set path flags. * path.h (PATH_TEXT): New enum. (path_conv::binmode): Return appropriate constant based on binmode. * pipe.cc (make_pipe): Set binmode to O_TEXT xor O_BINARY. * syscalls.cc (setmode_helper): Make debugging message a little clearer. (setmode): Set binmode via set_flags.
2002-06-05 09:42:28 +08:00
res = 1;
}
Remove fcntl.h includes throughout. * fhandler.h: Move fcntl.h include here. (fhandler_base::set_flags): Accept supplied_bin argument. Make non-inlined. * dtable.cc (dtable::init_std_file_from_handle): Just use binmode from pc. (reset_to_open_binmode): Use set_flags. * cygwin.din (open): Avoid newlib wrapper. (read): Ditto. (unlink): Ditto. (write): Ditto. * fhandler.cc (fhandler_base::set_flags): Accept supplied_bin argument. Make binmode decisions here. (fhandler_base::open): Avoid using pc if it is NULL. Eliminate binmode logic. Just call set_flags with binmode argument. (fhandler_base::init): Call set_flags with binmode argument. * fhandler_clipboard.cc (fhandler_dev_clipboard::open): Ditto. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::init): Force binary on open. * fhandler_disk_file.cc (fhandler_disk_file::open): Don't set binmode here. Let it happen in base class. * fhandler_dsp.cc (fhandler_dev_dsp::open): Force binmode open. Set return value appropriately if unable to open. * fhandler_proc.cc (fhandler_proc::open): Make sure flags are set before open_status. * fhandler_process.cc (fhandler_process::open): Ditto. * fhandler_registry.cc (fhandler_registry::open): Ditto. * fhandler_random.cc (fhandler_dev_random::fhandler_dev_random): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Force O_BINARY by default. * fhandler_serial.cc (fhandler_serial::init): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_virtual.cc (fhandler_virtual::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * net.cc (fdsock): Ditto. * path.cc (path_conv::check): Avoid checking for extension when error or directory. (set_flags): Set PATH_TEXT explicitly, when appropriate. (mount_info::conv_to_win32_path): Use set_flags() to set path flags. * path.h (PATH_TEXT): New enum. (path_conv::binmode): Return appropriate constant based on binmode. * pipe.cc (make_pipe): Set binmode to O_TEXT xor O_BINARY. * syscalls.cc (setmode_helper): Make debugging message a little clearer. (setmode): Set binmode via set_flags.
2002-06-05 09:42:28 +08:00
debug_printf ("returns %d", res);
return res;
}
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;
}
void __stdcall
fhandler_dev_dsp::read (void *ptr, size_t& len)
{
return;
}
* cygwin.din (fstat64): New symbol. (ftruncate64): Ditto. (lseek64): Ditto. (lstat64): Ditto. (mmap64): Ditto. (seekdir64): Ditto. (stat64): Ditto. (telldir64): Ditto. (truncate64): Ditto. * dir.cc (telldir64): New function. (telldir): Call telldir64(). (seekdir64): New function. (seekdir): Call seekdir64(). * fhandler.h: Redefine all methods using __off32_t to use __off64_t. * fhandler.cc: Use __off64_t and struct __stat64 throughout. * fhandler_clipboard.cc: Ditto. * fhandler_disk_file.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_floppy.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_socket.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_zero.cc: Ditto. * pipe.cc: Ditto. * glob.c: Ditto, call lstat64 and stat64 in Cygwin. * mmap.cc: Use __off64_t throughout. (mmap64): New function. * sec_acl.cc (acl_worker): Use struct __stat64, call stat64 and lstat64. * syscalls.cc (lseek64): New function. (stat64_to_stat32): Ditto. (fstat64): Ditto. (stat64): Ditto. (lstat64): Ditto. (ftruncate64): Ditto. (truncate64): Ditto. (_fstat): Call fstat64. (_stat): Call stat64. (cygwin_lstat): Rename to avoid declaration problem. Call lstat64. (stat_worker): Use struct __stat64. (access): Ditto. (ftruncate): Call ftruncate64. (truncate): Call truncate64. * wincap.cc: Set flag has_64bit_file_access appropriately. * wincap.h: Add flag has_64bit_file_access. * winsup.h (ILLEGAL_SEEK): Define as __off64_t. (stat_dev): Declare using struct __stat64. (stat_worker): Ditto. * include/cygwin/stat.h (struct __stat32): Define if compiling Cygwin. (struct __stat64): Ditto. (struct stat): Revert definition with explicitly sized datatypes. Eliminate sized field names. * include/cygwin/types.h (blksize_t): New type. (__blkcnt32_t): Ditto. (__blkcnt64_t): Ditto. (blkcnt_t): Ditto.
2002-02-26 01:47:51 +08:00
__off64_t
fhandler_dev_dsp::lseek (__off64_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", #a);
CASE (SNDCTL_DSP_RESET)
audioformat_ = AFMT_S8;
audiofreq_ = 8000;
audiobits_ = 8;
audiochannels_ = 1;
return 0;
CASE (SNDCTL_DSP_GETBLKSIZE)
*intptr = Audio::BLOCK_SIZE;
2001-11-05 14:09:15 +08:00
return 0;
CASE (SNDCTL_DSP_SETFMT)
{
int nBits = 0;
if (*intptr == AFMT_S16_LE)
nBits = 16;
else if (*intptr == AFMT_U8)
nBits = 8;
else if (*intptr == AFMT_S8)
nBits = 8;
if (nBits)
{
s_audio->setformat (*intptr);
s_audio->close ();
if (s_audio->open (audiofreq_, nBits, audiochannels_) == true)
{
audiobits_ = nBits;
return 0;
}
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 0;
}
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 0;
}
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 0;
}
break;
CASE (SNDCTL_DSP_SETFRAGMENT)
{
// Fake!! esound & mikmod require this on non PowerPC platforms.
//
return 0;
}
break;
CASE (SNDCTL_DSP_GETFMTS)
{
*intptr = AFMT_S16_LE | AFMT_U8 | AFMT_S8; // more?
return 0;
}
break;
default:
debug_printf ("/dev/dsp: ioctl not handled yet! FIXME:");
break;
#undef CASE
};
return -1;
}
void
fhandler_dev_dsp::dump ()
{
paranoid_printf ("here, fhandler_dev_dsp");
}
void
fhandler_dev_dsp::fixup_after_exec (HANDLE)
{
/* FIXME: Is there a better way to do this? */
s_audio = new (audio_buf) Audio;
}