+2004-04-13 Gerd Spalink <Gerd.Spalink@t-online.de>
+
+ * 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 <corinna@vinschen.de>
* winsup.h (IMPLEMENT_STATUS_FLAG): New macro to define status flag
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);
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:
}
void
-fhandler_dev_dsp::Audio_out::stop ()
+fhandler_dev_dsp::Audio_out::stop (bool immediately)
{
MMRESULT rc;
WAVEHDR *pHdr;
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);
return true;
}
-// return number of (partially) empty blocks back.
+// return number of (completely) empty blocks back.
int
fhandler_dev_dsp::Audio_out::emptyblocks ()
{
n = Qisr2app_->query ();
unlock ();
n += Qapp2app_->query ();
- if (pHdr_ != NULL)
- n++;
return n;
}
{
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;
}
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;
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)
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;
}
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.