From 37194b25f6d1228fef067f0d29e75f77fda3cf4b Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 13 Apr 2004 09:38:32 +0000 Subject: [PATCH] * fhandler_dsp.cc (fhandler_dev_dsp::Audio_out::stop): Add optional boolean argument so that playing can be stopped without playing pending buffers. (fhandler_dev_dsp::ioctl): Stop playback immediately for SNDCTL_DSP_RESET. Do not reset audio parameters in this case. Add support for ioctl SNDCTL_DSP_GETISPACE. (fhandler_dev_dsp::Audio_out::emptyblocks): Now returns the number of completely empty blocks. (fhandler_dev_dsp::Audio_out::buf_info): p->fragments is now the number of completely empty blocks. This conforms with the OSS specification. (fhandler_dev_dsp::Audio_out::parsewav): Ignore wave headers that are not aligned on four byte boundary. (fhandler_dev_dsp::Audio_in::buf_info): New, needed for SNDCTL_DSP_GETISPACE. --- winsup/cygwin/ChangeLog | 17 ++++++++ winsup/cygwin/fhandler_dsp.cc | 75 +++++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 43663a964..5ef03f5bf 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,20 @@ +2004-04-13 Gerd Spalink + + * fhandler_dsp.cc (fhandler_dev_dsp::Audio_out::stop): Add optional + boolean argument so that playing can be stopped without playing + pending buffers. + (fhandler_dev_dsp::ioctl): Stop playback immediately for + SNDCTL_DSP_RESET. Do not reset audio parameters in this case. + Add support for ioctl SNDCTL_DSP_GETISPACE. + (fhandler_dev_dsp::Audio_out::emptyblocks): Now returns the number of + completely empty blocks. + (fhandler_dev_dsp::Audio_out::buf_info): p->fragments is now the number + of completely empty blocks. This conforms with the OSS specification. + (fhandler_dev_dsp::Audio_out::parsewav): Ignore wave headers that are + not aligned on four byte boundary. + (fhandler_dev_dsp::Audio_in::buf_info): New, needed for + SNDCTL_DSP_GETISPACE. + 2004-04-13 Corinna Vinschen * winsup.h (IMPLEMENT_STATUS_FLAG): New macro to define status flag diff --git a/winsup/cygwin/fhandler_dsp.cc b/winsup/cygwin/fhandler_dsp.cc index cf7fe8d0b..a2ddef4f2 100644 --- a/winsup/cygwin/fhandler_dsp.cc +++ b/winsup/cygwin/fhandler_dsp.cc @@ -113,7 +113,7 @@ class fhandler_dev_dsp::Audio_out: public Audio bool query (int rate, int bits, int channels); bool start (int rate, int bits, int channels); - void stop (); + void stop (bool immediately = false); bool write (const char *pSampleData, int nBytes); void buf_info (audio_buf_info *p, int rate, int bits, int channels); void callback_sampledone (WAVEHDR *pHdr); @@ -152,6 +152,7 @@ public: bool start (int rate, int bits, int channels); void stop (); bool read (char *pSampleData, int &nBytes); + void buf_info (audio_buf_info *p, int rate, int bits, int channels); void callback_blockfull (WAVEHDR *pHdr); private: @@ -418,7 +419,7 @@ fhandler_dev_dsp::Audio_out::start (int rate, int bits, int channels) } void -fhandler_dev_dsp::Audio_out::stop () +fhandler_dev_dsp::Audio_out::stop (bool immediately) { MMRESULT rc; WAVEHDR *pHdr; @@ -428,8 +429,11 @@ fhandler_dev_dsp::Audio_out::stop () GetCurrentProcessId (), getOwner ()); if (getOwner () && !denyAccess ()) { - sendcurrent (); // force out last block whatever size.. - waitforallsent (); // block till finished.. + if (!immediately) + { + sendcurrent (); // force out last block whatever size.. + waitforallsent (); // block till finished.. + } rc = waveOutReset (dev_); debug_printf ("waveOutReset rc=%d", rc); @@ -507,7 +511,7 @@ fhandler_dev_dsp::Audio_out::write (const char *pSampleData, int nBytes) return true; } -// return number of (partially) empty blocks back. +// return number of (completely) empty blocks back. int fhandler_dev_dsp::Audio_out::emptyblocks () { @@ -516,8 +520,6 @@ fhandler_dev_dsp::Audio_out::emptyblocks () n = Qisr2app_->query (); unlock (); n += Qapp2app_->query (); - if (pHdr_ != NULL) - n++; return n; } @@ -531,8 +533,8 @@ fhandler_dev_dsp::Audio_out::buf_info (audio_buf_info *p, { p->fragments = emptyblocks (); if (pHdr_ != NULL) - p->bytes = p->fragsize - bufferIndex_ + - p->fragsize * (p->fragments - 1); + p->bytes = (int)pHdr_->dwUser - bufferIndex_ + + p->fragsize * p->fragments; else p->bytes = p->fragsize * p->fragments; } @@ -685,7 +687,9 @@ fhandler_dev_dsp::Audio_out::parsewav (const char * &pData, int &nBytes, const char *end = pData + nBytes; const char *pDat; int skip = 0; - + // Check alignment first: A lot of the code below depends on it + if (((int)pData & 0x3) != 0) + return false; if (!(pData[0] == 'R' && pData[1] == 'I' && pData[2] == 'F' && pData[3] == 'F')) return false; @@ -971,6 +975,31 @@ fhandler_dev_dsp::Audio_in::waitfordata () bufferIndex_ = 0; } +void +fhandler_dev_dsp::Audio_in::buf_info (audio_buf_info *p, + int rate, int bits, int channels) +{ + p->fragstotal = MAX_BLOCKS; + p->fragsize = blockSize (rate, bits, channels); + if (getOwner ()) + { + lock (); + p->fragments = Qisr2app_->query (); + unlock (); + p->fragments += Qapp2app_->query (); + if (pHdr_ != NULL) + p->bytes = pHdr_->dwBytesRecorded - bufferIndex_ + + p->fragsize * p->fragments; + else + p->bytes = p->fragsize * p->fragments; + } + else + { + p->fragments = 0; + p->bytes = 0; + } +} + // This is called on an interrupt so use locking.. void fhandler_dev_dsp::Audio_in::callback_blockfull (WAVEHDR *pHdr) @@ -1214,22 +1243,12 @@ fhandler_dev_dsp::ioctl (unsigned int cmd, void *ptr) if (audio_out_) { RETURN_ERROR_WHEN_BUSY (audio_out_); - audioformat_ = AFMT_U8; - audiofreq_ = 8000; - audiobits_ = 8; - audiochannels_ = 1; - audio_out_->stop (); - audio_out_->setformat (audioformat_); + audio_out_->stop (true); } if (audio_in_) { RETURN_ERROR_WHEN_BUSY (audio_in_); - audioformat_ = AFMT_U8; - audiofreq_ = 8000; - audiobits_ = 8; - audiochannels_ = 1; audio_in_->stop (); - audio_in_->setformat (audioformat_); } return 0; break; @@ -1416,6 +1435,20 @@ fhandler_dev_dsp::ioctl (unsigned int cmd, void *ptr) } break; + CASE (SNDCTL_DSP_GETISPACE) + { + audio_buf_info *p = (audio_buf_info *) ptr; + if (audio_in_) + { + RETURN_ERROR_WHEN_BUSY (audio_in_); + audio_in_->buf_info (p, audiofreq_, audiobits_, audiochannels_); + debug_printf ("ptr=%p frags=%d fragsize=%d bytes=%d", + ptr, p->fragments, p->fragsize, p->bytes); + } + return 0; + } + break; + CASE (SNDCTL_DSP_SETFRAGMENT) { // Fake!! esound & mikmod require this on non PowerPC platforms.