* 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.
This commit is contained in:
		| @@ -1,3 +1,27 @@ | |||||||
|  | 2011-05-04  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	* 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. | ||||||
|  |  | ||||||
| 2011-05-04  Christopher Faylor  <me.cygwin2011@cgf.cx> | 2011-05-04  Christopher Faylor  <me.cygwin2011@cgf.cx> | ||||||
|  |  | ||||||
| 	* thread.h (pthread::static_cancel_self): Mark as noreturn. | 	* thread.h (pthread::static_cancel_self): Mark as noreturn. | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| /* Fhandler_dev_dsp: code to emulate OSS sound model /dev/dsp | /* 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) |    Written by Andy Younger (andy@snoogie.demon.co.uk) | ||||||
|    Extended by Gerd Spalink (Gerd.Spalink@t-online.de) |    Extended by Gerd Spalink (Gerd.Spalink@t-online.de) | ||||||
| @@ -20,6 +20,7 @@ details. */ | |||||||
| #include "fhandler.h" | #include "fhandler.h" | ||||||
| #include "dtable.h" | #include "dtable.h" | ||||||
| #include "cygheap.h" | #include "cygheap.h" | ||||||
|  | #include "sigproc.h" | ||||||
|  |  | ||||||
| /*------------------------------------------------------------------------ | /*------------------------------------------------------------------------ | ||||||
|   Simple encapsulation of the win32 audio device. |   Simple encapsulation of the win32 audio device. | ||||||
| @@ -49,7 +50,7 @@ details. */ | |||||||
| class fhandler_dev_dsp::Audio | class fhandler_dev_dsp::Audio | ||||||
| { // This class contains functionality common to Audio_in and Audio_out | { // This class contains functionality common to Audio_in and Audio_out | ||||||
|  public: |  public: | ||||||
|    Audio (); |    Audio (fhandler_dev_dsp *my_fh); | ||||||
|    ~Audio (); |    ~Audio (); | ||||||
|  |  | ||||||
|   class queue; |   class queue; | ||||||
| @@ -74,6 +75,8 @@ class fhandler_dev_dsp::Audio | |||||||
|   char *bigwavebuffer_; // audio samples only |   char *bigwavebuffer_; // audio samples only | ||||||
|   // Member variables below must be locked |   // Member variables below must be locked | ||||||
|   queue *Qisr2app_; // blocks passed from wave callback |   queue *Qisr2app_; // blocks passed from wave callback | ||||||
|  |  | ||||||
|  |   fhandler_dev_dsp *fh; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class fhandler_dev_dsp::Audio::queue | 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 | class fhandler_dev_dsp::Audio_out: public Audio | ||||||
| { | { | ||||||
|  public: |  public: | ||||||
|  |   Audio_out (fhandler_dev_dsp *my_fh) : Audio (my_fh) {} | ||||||
|  |  | ||||||
|   void fork_fixup (HANDLE parent); |   void fork_fixup (HANDLE parent); | ||||||
|   bool query (int rate, int bits, int channels); |   bool query (int rate, int bits, int channels); | ||||||
|   bool start (); |   bool start (); | ||||||
|   void stop (bool immediately = false); |   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 buf_info (audio_buf_info *p, int rate, int bits, int channels); | ||||||
|   void callback_sampledone (WAVEHDR *pHdr); |   void callback_sampledone (WAVEHDR *pHdr); | ||||||
|   bool parsewav (const char *&pData, int &nBytes, |   bool parsewav (const char *&pData, int &nBytes, | ||||||
| @@ -117,7 +122,7 @@ class fhandler_dev_dsp::Audio_out: public Audio | |||||||
|  private: |  private: | ||||||
|   void init (unsigned blockSize); |   void init (unsigned blockSize); | ||||||
|   void waitforallsent (); |   void waitforallsent (); | ||||||
|   void waitforspace (); |   bool waitforspace (); | ||||||
|   bool sendcurrent (); |   bool sendcurrent (); | ||||||
|  |  | ||||||
|   enum { MAX_BLOCKS = 12 }; |   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 | class fhandler_dev_dsp::Audio_in: public Audio | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  |   Audio_in (fhandler_dev_dsp *my_fh) : Audio (my_fh) {} | ||||||
|  |  | ||||||
|   void fork_fixup (HANDLE parent); |   void fork_fixup (HANDLE parent); | ||||||
|   bool query (int rate, int bits, int channels); |   bool query (int rate, int bits, int channels); | ||||||
|   bool start (int rate, int bits, int channels); |   bool start (int rate, int bits, int channels); | ||||||
| @@ -146,7 +153,7 @@ public: | |||||||
| private: | private: | ||||||
|   bool init (unsigned blockSize); |   bool init (unsigned blockSize); | ||||||
|   bool queueblock (WAVEHDR *pHdr); |   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_; |   HWAVEIN dev_; | ||||||
| }; | }; | ||||||
| @@ -222,11 +229,12 @@ fhandler_dev_dsp::Audio::queue::query () | |||||||
| } | } | ||||||
|  |  | ||||||
| // Audio class implements functionality need for both read and write | // 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; |   bigwavebuffer_ = NULL; | ||||||
|   Qisr2app_ = new queue (MAX_BLOCKS); |   Qisr2app_ = new queue (MAX_BLOCKS); | ||||||
|   convert_ = &fhandler_dev_dsp::Audio::convert_none; |   convert_ = &fhandler_dev_dsp::Audio::convert_none; | ||||||
|  |   fh = my_fh; | ||||||
| } | } | ||||||
|  |  | ||||||
| fhandler_dev_dsp::Audio::~Audio () | fhandler_dev_dsp::Audio::~Audio () | ||||||
| @@ -452,18 +460,24 @@ fhandler_dev_dsp::Audio_out::init (unsigned blockSize) | |||||||
|   pHdr_ = NULL; |   pHdr_ = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool | int | ||||||
| fhandler_dev_dsp::Audio_out::write (const char *pSampleData, int nBytes) | 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 |     { // 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_; |       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 | 	{ // all data fits into the current block, with some space left | ||||||
| 	  memcpy (&pHdr_->lpData[bufferIndex_], pSampleData, nBytes); | 	  memcpy (&pHdr_->lpData[bufferIndex_], pSampleData, bytes_to_write); | ||||||
| 	  bufferIndex_ += nBytes; | 	  bufferIndex_ += bytes_to_write; | ||||||
| 	  break; | 	  break; | ||||||
| 	} | 	} | ||||||
|       else |       else | ||||||
| @@ -472,10 +486,10 @@ fhandler_dev_dsp::Audio_out::write (const char *pSampleData, int nBytes) | |||||||
| 	  bufferIndex_ += sizeleft; | 	  bufferIndex_ += sizeleft; | ||||||
| 	  sendcurrent (); | 	  sendcurrent (); | ||||||
| 	  pSampleData += sizeleft; | 	  pSampleData += sizeleft; | ||||||
| 	  nBytes -= sizeleft; | 	  bytes_to_write -= sizeleft; | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|   return true; |   return nBytes - bytes_to_write; | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| @@ -511,18 +525,39 @@ fhandler_dev_dsp::Audio_out::callback_sampledone (WAVEHDR *pHdr) | |||||||
|   Qisr2app_->send (pHdr); |   Qisr2app_->send (pHdr); | ||||||
| } | } | ||||||
|  |  | ||||||
| void | bool | ||||||
| fhandler_dev_dsp::Audio_out::waitforspace () | fhandler_dev_dsp::Audio_out::waitforspace () | ||||||
| { | { | ||||||
|   WAVEHDR *pHdr; |   WAVEHDR *pHdr; | ||||||
|   MMRESULT rc = WAVERR_STILLPLAYING; |   MMRESULT rc = WAVERR_STILLPLAYING; | ||||||
|  |  | ||||||
|   if (pHdr_ != NULL) |   if (pHdr_ != NULL) | ||||||
|     return; |     return true; | ||||||
|   while (!Qisr2app_->recv (&pHdr)) |   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"); |       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) |   if (pHdr->dwFlags) | ||||||
|     { |     { | ||||||
| @@ -533,6 +568,7 @@ fhandler_dev_dsp::Audio_out::waitforspace () | |||||||
|     } |     } | ||||||
|   pHdr_ = pHdr; |   pHdr_ = pHdr; | ||||||
|   bufferIndex_ = 0; |   bufferIndex_ = 0; | ||||||
|  |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void | 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); |   debug_printf ("pSampleData=%08x nBytes=%d", pSampleData, bytes_to_read); | ||||||
|   while (bytes_to_read != 0) |   while (bytes_to_read != 0) | ||||||
|     { // Block till next sound has been read |     { // 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 |       // Handle gathering our blocks into smaller or larger buffer | ||||||
|       int sizeleft = pHdr_->dwBytesRecorded - bufferIndex_; |       int sizeleft = pHdr_->dwBytesRecorded - bufferIndex_; | ||||||
| @@ -863,18 +905,39 @@ fhandler_dev_dsp::Audio_in::read (char *pSampleData, int &nBytes) | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void | bool | ||||||
| fhandler_dev_dsp::Audio_in::waitfordata () | fhandler_dev_dsp::Audio_in::waitfordata () | ||||||
| { | { | ||||||
|   WAVEHDR *pHdr; |   WAVEHDR *pHdr; | ||||||
|   MMRESULT rc; |   MMRESULT rc; | ||||||
|  |  | ||||||
|   if (pHdr_ != NULL) |   if (pHdr_ != NULL) | ||||||
|     return; |     return true; | ||||||
|   while (!Qisr2app_->recv (&pHdr)) |   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"); |       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 */ |   if (pHdr->dwFlags) /* Zero if queued following error in queueblock */ | ||||||
|     { |     { | ||||||
| @@ -885,6 +948,7 @@ fhandler_dev_dsp::Audio_in::waitfordata () | |||||||
|     } |     } | ||||||
|   pHdr_ = pHdr; |   pHdr_ = pHdr; | ||||||
|   bufferIndex_ = 0; |   bufferIndex_ = 0; | ||||||
|  |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| @@ -1012,7 +1076,7 @@ fhandler_dev_dsp::write (const void *ptr, size_t len) | |||||||
|   else if (IS_WRITE ()) |   else if (IS_WRITE ()) | ||||||
|     { |     { | ||||||
|       debug_printf ("Allocating"); |       debug_printf ("Allocating"); | ||||||
|       if (!(audio_out_ = new Audio_out)) |       if (!(audio_out_ = new Audio_out (this))) | ||||||
| 	return -1; | 	return -1; | ||||||
|  |  | ||||||
|       /* check for wave file & get parameters & skip header if possible. */ |       /* 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; |       return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   audio_out_->write (ptr_s, len_s); |   int written = audio_out_->write (ptr_s, len_s); | ||||||
|   return len; |   if (written < 0) | ||||||
|  |     { | ||||||
|  |       if (len - len_s > 0) | ||||||
|  | 	return len - len_s; | ||||||
|  |       return -1; | ||||||
|  |     } | ||||||
|  |   return len - len_s + written; | ||||||
| } | } | ||||||
|  |  | ||||||
| void __stdcall | void __stdcall | ||||||
| @@ -1052,7 +1122,7 @@ fhandler_dev_dsp::read (void *ptr, size_t& len) | |||||||
|   else if (IS_READ ()) |   else if (IS_READ ()) | ||||||
|     { |     { | ||||||
|       debug_printf ("Allocating"); |       debug_printf ("Allocating"); | ||||||
|       if (!(audio_in_ = new Audio_in)) |       if (!(audio_in_ = new Audio_in (this))) | ||||||
| 	{ | 	{ | ||||||
| 	  len = (size_t)-1; | 	  len = (size_t)-1; | ||||||
| 	  return; | 	  return; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user