Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2011-05-04 15:41:22 +0400
committerCorinna Vinschen <corinna@vinschen.de>2011-05-04 15:41:22 +0400
commit5152a53adeaa86135dd7ca1ce3ae64e7353b3729 (patch)
tree3dace1f3496f81a7248193f070deb1abd079d4f2 /winsup/cygwin/fhandler_dsp.cc
parent307b0a5d4b1801305ad4da3eb8447376d1260709 (diff)
* fhandler_dsp.cc (fhandler_dev_dsp::Audio): Add fh member.
(fhandler_dev_dsp::Audio_out::Audio_out): Take pointer to encapsulating fhandler_dev_dsp as parameter. (fhandler_dev_dsp::Audio_in::Audio_in): Ditto. (fhandler_dev_dsp::Audio::Audio): Take pointer to encapsulating fhandler_dev_dsp as parameter and store in fh. (fhandler_dev_dsp::Audio_out::write): Change return type to int and return number of bytes written. Return -1 if waitforspace returns false and no bytes have been written so far. (fhandler_dev_dsp::Audio_out::waitforspace): Change return type to bool. Handle O_NONBLOCK. Make waiting loop interruptible and cancelable. Return false in any of these cases, otherwise true. (fhandler_dev_dsp::Audio_in::read): Set returned nBytes to -1 if waitfordata returns false and nothing has been read so far. (fhandler_dev_dsp::Audio_in::waitfordata): Change return type to bool. Handle O_NONBLOCK. Make waiting loop interruptible and cancelable. Return false in any of these cases, otherwise true. (fhandler_dev_dsp::write): Call Audio_out constructor with this as parameter. (fhandler_dev_dsp::read): Call Audio_in constructor with this as parameter.
Diffstat (limited to 'winsup/cygwin/fhandler_dsp.cc')
-rw-r--r--winsup/cygwin/fhandler_dsp.cc120
1 files changed, 95 insertions, 25 deletions
diff --git a/winsup/cygwin/fhandler_dsp.cc b/winsup/cygwin/fhandler_dsp.cc
index 9095ba517..f784ca358 100644
--- a/winsup/cygwin/fhandler_dsp.cc
+++ b/winsup/cygwin/fhandler_dsp.cc
@@ -1,6 +1,6 @@
/* Fhandler_dev_dsp: code to emulate OSS sound model /dev/dsp
- Copyright 2001, 2002, 2003, 2004, 2008 Red Hat, Inc
+ Copyright 2001, 2002, 2003, 2004, 2008, 2011 Red Hat, Inc
Written by Andy Younger (andy@snoogie.demon.co.uk)
Extended by Gerd Spalink (Gerd.Spalink@t-online.de)
@@ -20,6 +20,7 @@ details. */
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
+#include "sigproc.h"
/*------------------------------------------------------------------------
Simple encapsulation of the win32 audio device.
@@ -49,7 +50,7 @@ details. */
class fhandler_dev_dsp::Audio
{ // This class contains functionality common to Audio_in and Audio_out
public:
- Audio ();
+ Audio (fhandler_dev_dsp *my_fh);
~Audio ();
class queue;
@@ -74,6 +75,8 @@ class fhandler_dev_dsp::Audio
char *bigwavebuffer_; // audio samples only
// Member variables below must be locked
queue *Qisr2app_; // blocks passed from wave callback
+
+ fhandler_dev_dsp *fh;
};
class fhandler_dev_dsp::Audio::queue
@@ -104,11 +107,13 @@ static void CALLBACK waveOut_callback (HWAVEOUT hWave, UINT msg, DWORD instance,
class fhandler_dev_dsp::Audio_out: public Audio
{
public:
+ Audio_out (fhandler_dev_dsp *my_fh) : Audio (my_fh) {}
+
void fork_fixup (HANDLE parent);
bool query (int rate, int bits, int channels);
bool start ();
void stop (bool immediately = false);
- bool write (const char *pSampleData, int nBytes);
+ int 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 parsewav (const char *&pData, int &nBytes,
@@ -117,7 +122,7 @@ class fhandler_dev_dsp::Audio_out: public Audio
private:
void init (unsigned blockSize);
void waitforallsent ();
- void waitforspace ();
+ bool waitforspace ();
bool sendcurrent ();
enum { MAX_BLOCKS = 12 };
@@ -135,6 +140,8 @@ static void CALLBACK waveIn_callback (HWAVEIN hWave, UINT msg, DWORD instance,
class fhandler_dev_dsp::Audio_in: public Audio
{
public:
+ Audio_in (fhandler_dev_dsp *my_fh) : Audio (my_fh) {}
+
void fork_fixup (HANDLE parent);
bool query (int rate, int bits, int channels);
bool start (int rate, int bits, int channels);
@@ -146,7 +153,7 @@ public:
private:
bool init (unsigned blockSize);
bool queueblock (WAVEHDR *pHdr);
- void waitfordata (); // blocks until we have a good pHdr_
+ bool waitfordata (); // blocks until we have a good pHdr_ unless O_NONBLOCK
HWAVEIN dev_;
};
@@ -222,11 +229,12 @@ fhandler_dev_dsp::Audio::queue::query ()
}
// Audio class implements functionality need for both read and write
-fhandler_dev_dsp::Audio::Audio ()
+fhandler_dev_dsp::Audio::Audio (fhandler_dev_dsp *my_fh)
{
bigwavebuffer_ = NULL;
Qisr2app_ = new queue (MAX_BLOCKS);
convert_ = &fhandler_dev_dsp::Audio::convert_none;
+ fh = my_fh;
}
fhandler_dev_dsp::Audio::~Audio ()
@@ -452,18 +460,24 @@ fhandler_dev_dsp::Audio_out::init (unsigned blockSize)
pHdr_ = NULL;
}
-bool
+int
fhandler_dev_dsp::Audio_out::write (const char *pSampleData, int nBytes)
{
- while (nBytes != 0)
+ int bytes_to_write = nBytes;
+ while (bytes_to_write != 0)
{ // Block if all blocks used until at least one is free
- waitforspace ();
+ if (!waitforspace ())
+ {
+ if (bytes_to_write != nBytes)
+ break;
+ return -1;
+ }
int sizeleft = (int)pHdr_->dwUser - bufferIndex_;
- if (nBytes < sizeleft)
+ if (bytes_to_write < sizeleft)
{ // all data fits into the current block, with some space left
- memcpy (&pHdr_->lpData[bufferIndex_], pSampleData, nBytes);
- bufferIndex_ += nBytes;
+ memcpy (&pHdr_->lpData[bufferIndex_], pSampleData, bytes_to_write);
+ bufferIndex_ += bytes_to_write;
break;
}
else
@@ -472,10 +486,10 @@ fhandler_dev_dsp::Audio_out::write (const char *pSampleData, int nBytes)
bufferIndex_ += sizeleft;
sendcurrent ();
pSampleData += sizeleft;
- nBytes -= sizeleft;
+ bytes_to_write -= sizeleft;
}
}
- return true;
+ return nBytes - bytes_to_write;
}
void
@@ -511,18 +525,39 @@ fhandler_dev_dsp::Audio_out::callback_sampledone (WAVEHDR *pHdr)
Qisr2app_->send (pHdr);
}
-void
+bool
fhandler_dev_dsp::Audio_out::waitforspace ()
{
WAVEHDR *pHdr;
MMRESULT rc = WAVERR_STILLPLAYING;
if (pHdr_ != NULL)
- return;
+ return true;
while (!Qisr2app_->recv (&pHdr))
{
+ if (fh->is_nonblocking ())
+ {
+ set_errno (EAGAIN);
+ return false;
+ }
+ HANDLE w4[2] = { signal_arrived, pthread::get_cancel_event () };
+ DWORD cnt = w4[1] ? 2 : 1;
debug_printf ("100ms");
- Sleep (100);
+ switch (WaitForMultipleObjects (cnt, w4, FALSE, 100))
+ {
+ case WAIT_OBJECT_0:
+ if (!_my_tls.call_signal_handler ())
+ {
+ set_errno (EINTR);
+ return false;
+ }
+ break;
+ case WAIT_OBJECT_0 + 1:
+ pthread::static_cancel_self ();
+ /*NOTREACHED*/
+ default:
+ break;
+ }
}
if (pHdr->dwFlags)
{
@@ -533,6 +568,7 @@ fhandler_dev_dsp::Audio_out::waitforspace ()
}
pHdr_ = pHdr;
bufferIndex_ = 0;
+ return true;
}
void
@@ -830,7 +866,13 @@ fhandler_dev_dsp::Audio_in::read (char *pSampleData, int &nBytes)
debug_printf ("pSampleData=%08x nBytes=%d", pSampleData, bytes_to_read);
while (bytes_to_read != 0)
{ // Block till next sound has been read
- waitfordata ();
+ if (!waitfordata ())
+ {
+ if (nBytes)
+ return true;
+ nBytes = -1;
+ return false;
+ }
// Handle gathering our blocks into smaller or larger buffer
int sizeleft = pHdr_->dwBytesRecorded - bufferIndex_;
@@ -863,18 +905,39 @@ fhandler_dev_dsp::Audio_in::read (char *pSampleData, int &nBytes)
return true;
}
-void
+bool
fhandler_dev_dsp::Audio_in::waitfordata ()
{
WAVEHDR *pHdr;
MMRESULT rc;
if (pHdr_ != NULL)
- return;
+ return true;
while (!Qisr2app_->recv (&pHdr))
{
+ if (fh->is_nonblocking ())
+ {
+ set_errno (EAGAIN);
+ return false;
+ }
+ HANDLE w4[2] = { signal_arrived, pthread::get_cancel_event () };
+ DWORD cnt = w4[1] ? 2 : 1;
debug_printf ("100ms");
- Sleep (100);
+ switch (WaitForMultipleObjects (cnt, w4, FALSE, 100))
+ {
+ case WAIT_OBJECT_0:
+ if (!_my_tls.call_signal_handler ())
+ {
+ set_errno (EINTR);
+ return false;
+ }
+ break;
+ case WAIT_OBJECT_0 + 1:
+ pthread::static_cancel_self ();
+ /*NOTREACHED*/
+ default:
+ break;
+ }
}
if (pHdr->dwFlags) /* Zero if queued following error in queueblock */
{
@@ -885,6 +948,7 @@ fhandler_dev_dsp::Audio_in::waitfordata ()
}
pHdr_ = pHdr;
bufferIndex_ = 0;
+ return true;
}
void
@@ -1012,7 +1076,7 @@ fhandler_dev_dsp::write (const void *ptr, size_t len)
else if (IS_WRITE ())
{
debug_printf ("Allocating");
- if (!(audio_out_ = new Audio_out))
+ if (!(audio_out_ = new Audio_out (this)))
return -1;
/* check for wave file & get parameters & skip header if possible. */
@@ -1036,8 +1100,14 @@ fhandler_dev_dsp::write (const void *ptr, size_t len)
return -1;
}
- audio_out_->write (ptr_s, len_s);
- return len;
+ int written = audio_out_->write (ptr_s, len_s);
+ if (written < 0)
+ {
+ if (len - len_s > 0)
+ return len - len_s;
+ return -1;
+ }
+ return len - len_s + written;
}
void __stdcall
@@ -1052,7 +1122,7 @@ fhandler_dev_dsp::read (void *ptr, size_t& len)
else if (IS_READ ())
{
debug_printf ("Allocating");
- if (!(audio_in_ = new Audio_in))
+ if (!(audio_in_ = new Audio_in (this)))
{
len = (size_t)-1;
return;