Cygwin: cygtls: rename sig to current_sig
[newlib-cygwin.git] / winsup / cygwin / fhandler / dsp.cc
blob605a048f3964618056b7df6579b69ca36c525274
1 /* fhandler_dev_dsp: code to emulate OSS sound model /dev/dsp
3 Written by Andy Younger (andy@snoogie.demon.co.uk)
4 Extended by Gerd Spalink (Gerd.Spalink@t-online.de)
5 to support recording from the audio input
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 details. */
13 #include "winsup.h"
14 #include <sys/soundcard.h>
15 #include "cygerrno.h"
16 #include "security.h"
17 #include "path.h"
18 #include "fhandler.h"
19 #include "dtable.h"
20 #include "cygheap.h"
21 #include "sigproc.h"
22 #include "cygwait.h"
24 /*------------------------------------------------------------------------
25 Simple encapsulation of the win32 audio device.
27 Implementation Notes
28 1. Audio structures are malloced just before the first read or
29 write to /dev/dsp. The actual buffer size is determined at that time,
30 such that one buffer holds about 125ms of audio data.
31 At the time of this writing, 12 buffers are allocated,
32 so that up to 1.5 seconds can be buffered within Win32.
33 The buffer size can be queried with the ioctl SNDCTL_DSP_GETBLKSIZE,
34 but for this implementation only returns meaningful results if
35 sampling rate, number of channels and number of bits per sample
36 are not changed afterwards.
37 The audio structures are freed when the device is reset or closed,
38 and they are not passed to exec'ed processes.
39 The dev_ member is cleared after a fork. This forces the child
40 to reopen the audio device._
42 2. Every open call creates a new instance of the handler. After a
43 successful open, every subsequent open from the same process
44 to the device fails with EBUSY.
45 The structures are shared between duped handles, but not with
46 children. They only inherit the settings from the parent.
49 enum { DEFAULT_BLOCKS = 12, MAX_BLOCKS = 256 };
51 class fhandler_dev_dsp::Audio
52 { // This class contains functionality common to Audio_in and Audio_out
53 public:
54 Audio (fhandler_dev_dsp *my_fh);
55 ~Audio ();
57 class queue;
59 bool isvalid ();
60 void setconvert (int format);
61 void convert_none (unsigned char *buffer, int size_bytes) { }
62 void convert_U8_S8 (unsigned char *buffer, int size_bytes);
63 void convert_S16LE_U16LE (unsigned char *buffer, int size_bytes);
64 void convert_S16LE_U16BE (unsigned char *buffer, int size_bytes);
65 void convert_S16LE_S16BE (unsigned char *buffer, int size_bytes);
66 void fillFormat (WAVEFORMATEX * format,
67 int rate, int bits, int channels);
68 static unsigned blockSize (double ms, int rate, int bits, int channels);
69 void (fhandler_dev_dsp::Audio::*convert_)
70 (unsigned char *buffer, int size_bytes);
72 int bufferIndex_; // offset into pHdr_->lpData
73 WAVEHDR *pHdr_; // data to be filled by write
74 WAVEHDR wavehdr_[MAX_BLOCKS];
75 char *bigwavebuffer_; // audio samples only
76 // Member variables below must be locked
77 queue *Qisr2app_; // blocks passed from wave callback
79 fhandler_dev_dsp *fh;
82 class fhandler_dev_dsp::Audio::queue
83 { // non-blocking fixed size queues for buffer management
84 public:
85 queue (int depth = 4);
86 ~queue ();
88 bool send (WAVEHDR *); // queue an item, returns true if successful
89 bool recv (WAVEHDR **); // retrieve an item, returns true if successful
90 void reset ();
91 int query (); // return number of items queued
92 inline void lock () { EnterCriticalSection (&lock_); }
93 inline void unlock () { LeaveCriticalSection (&lock_); }
94 inline void dellock () { debug_printf ("Deleting Critical Section"); DeleteCriticalSection (&lock_); }
95 bool isvalid () { return storage_; }
96 private:
97 CRITICAL_SECTION lock_;
98 int head_;
99 int tail_;
100 int depth_;
101 WAVEHDR **storage_;
104 static void CALLBACK waveOut_callback (HWAVEOUT hWave, UINT msg,
105 DWORD_PTR instance, DWORD_PTR param1,
106 DWORD_PTR param2);
108 class fhandler_dev_dsp::Audio_out: public Audio
110 public:
111 Audio_out (fhandler_dev_dsp *my_fh) : Audio (my_fh) {}
113 void fork_fixup (HANDLE parent);
114 bool query (int rate, int bits, int channels);
115 bool start ();
116 void stop (bool immediately = false);
117 int write (const char *pSampleData, int nBytes);
118 void buf_info (audio_buf_info *p, int rate, int bits, int channels);
119 static void default_buf_info (audio_buf_info *p, int rate, int bits, int channels);
120 void callback_sampledone (WAVEHDR *pHdr);
121 bool parsewav (const char *&pData, int &nBytes,
122 int rate, int bits, int channels);
124 private:
125 void init (unsigned blockSize);
126 void waitforallsent ();
127 bool waitforspace ();
128 bool sendcurrent ();
130 HWAVEOUT dev_; // The wave device
131 /* Private copies of audiofreq_, audiobits_, audiochannels_,
132 possibly set from wave file */
133 int freq_;
134 int bits_;
135 int channels_;
137 friend fhandler_dev_dsp;
140 static void CALLBACK waveIn_callback (HWAVEIN hWave, UINT msg,
141 DWORD_PTR instance, DWORD_PTR param1,
142 DWORD_PTR param2);
144 class fhandler_dev_dsp::Audio_in: public Audio
146 public:
147 Audio_in (fhandler_dev_dsp *my_fh) : Audio (my_fh) {}
149 void fork_fixup (HANDLE parent);
150 bool query (int rate, int bits, int channels);
151 bool start (int rate, int bits, int channels);
152 void stop ();
153 bool read (char *pSampleData, int &nBytes);
154 void buf_info (audio_buf_info *p, int rate, int bits, int channels);
155 static void default_buf_info (audio_buf_info *p, int rate, int bits, int channels);
156 void callback_blockfull (WAVEHDR *pHdr);
158 private:
159 bool init (unsigned blockSize);
160 bool queueblock (WAVEHDR *pHdr);
161 bool waitfordata (); // blocks until we have a good pHdr_ unless O_NONBLOCK
163 HWAVEIN dev_;
166 /* --------------------------------------------------------------------
167 Implementation */
169 // Simple fixed length FIFO queue implementation for audio buffer management
170 fhandler_dev_dsp::Audio::queue::queue (int depth)
172 // allow space for one extra object in the queue
173 // so we can distinguish full and empty status
174 depth_ = depth;
175 storage_ = new WAVEHDR *[depth_ + 1];
178 fhandler_dev_dsp::Audio::queue::~queue ()
180 delete[] storage_;
183 void
184 fhandler_dev_dsp::Audio::queue::reset ()
186 /* When starting, after reset and after fork */
187 head_ = tail_ = 0;
188 debug_printf ("InitializeCriticalSection");
189 memset (&lock_, 0, sizeof (lock_));
190 InitializeCriticalSection (&lock_);
193 bool
194 fhandler_dev_dsp::Audio::queue::send (WAVEHDR *x)
196 bool res = false;
197 lock ();
198 if (query () == depth_)
199 system_printf ("Queue overflow");
200 else
202 storage_[tail_] = x;
203 if (++tail_ > depth_)
204 tail_ = 0;
205 res = true;
207 unlock ();
208 return res;
211 bool
212 fhandler_dev_dsp::Audio::queue::recv (WAVEHDR **x)
214 bool res = false;
215 lock ();
216 if (query () != 0)
218 *x = storage_[head_];
219 if (++head_ > depth_)
220 head_ = 0;
221 res = true;
223 unlock ();
224 return res;
228 fhandler_dev_dsp::Audio::queue::query ()
230 int n = tail_ - head_;
231 if (n < 0)
232 n += depth_ + 1;
233 return n;
236 // Audio class implements functionality need for both read and write
237 fhandler_dev_dsp::Audio::Audio (fhandler_dev_dsp *my_fh)
239 bigwavebuffer_ = NULL;
240 fh = my_fh;
241 Qisr2app_ = new queue (fh->fragstotal_);
242 convert_ = &fhandler_dev_dsp::Audio::convert_none;
245 fhandler_dev_dsp::Audio::~Audio ()
247 debug_printf("");
248 delete Qisr2app_;
249 delete[] bigwavebuffer_;
252 inline bool
253 fhandler_dev_dsp::Audio::isvalid ()
255 return bigwavebuffer_ && Qisr2app_ && Qisr2app_->isvalid ();
258 void
259 fhandler_dev_dsp::Audio::setconvert (int format)
261 switch (format)
263 case AFMT_S8:
264 convert_ = &fhandler_dev_dsp::Audio::convert_U8_S8;
265 debug_printf ("U8_S8");
266 break;
267 case AFMT_U16_LE:
268 convert_ = &fhandler_dev_dsp::Audio::convert_S16LE_U16LE;
269 debug_printf ("S16LE_U16LE");
270 break;
271 case AFMT_U16_BE:
272 convert_ = &fhandler_dev_dsp::Audio::convert_S16LE_U16BE;
273 debug_printf ("S16LE_U16BE");
274 break;
275 case AFMT_S16_BE:
276 convert_ = &fhandler_dev_dsp::Audio::convert_S16LE_S16BE;
277 debug_printf ("S16LE_S16BE");
278 break;
279 default:
280 convert_ = &fhandler_dev_dsp::Audio::convert_none;
281 debug_printf ("none");
285 void
286 fhandler_dev_dsp::Audio::convert_U8_S8 (unsigned char *buffer,
287 int size_bytes)
289 while (size_bytes-- > 0)
291 *buffer ^= (unsigned char)0x80;
292 buffer++;
296 void
297 fhandler_dev_dsp::Audio::convert_S16LE_U16BE (unsigned char *buffer,
298 int size_bytes)
300 int size_samples = size_bytes / 2;
301 unsigned char hi, lo;
302 while (size_samples-- > 0)
304 hi = buffer[0];
305 lo = buffer[1];
306 *buffer++ = lo;
307 *buffer++ = hi ^ (unsigned char)0x80;
311 void
312 fhandler_dev_dsp::Audio::convert_S16LE_U16LE (unsigned char *buffer,
313 int size_bytes)
315 int size_samples = size_bytes / 2;
316 while (size_samples-- > 0)
318 buffer++;
319 *buffer ^= (unsigned char)0x80;
320 buffer++;
324 void
325 fhandler_dev_dsp::Audio::convert_S16LE_S16BE (unsigned char *buffer,
326 int size_bytes)
328 int size_samples = size_bytes / 2;
329 unsigned char hi, lo;
330 while (size_samples-- > 0)
332 hi = buffer[0];
333 lo = buffer[1];
334 *buffer++ = lo;
335 *buffer++ = hi;
339 void
340 fhandler_dev_dsp::Audio::fillFormat (WAVEFORMATEX * format,
341 int rate, int bits, int channels)
343 memset (format, 0, sizeof (*format));
344 format->wFormatTag = WAVE_FORMAT_PCM;
345 format->wBitsPerSample = bits;
346 format->nChannels = channels;
347 format->nSamplesPerSec = rate;
348 format->nAvgBytesPerSec = format->nSamplesPerSec * format->nChannels
349 * (bits / 8);
350 format->nBlockAlign = format->nChannels * (bits / 8);
353 // calculate a good block size
354 unsigned
355 fhandler_dev_dsp::Audio::blockSize (double ms, int rate, int bits, int channels)
357 unsigned blockSize;
358 blockSize = ms * ((bits / 8) * channels * rate) / 1000;
359 // round up to multiple of 64
360 blockSize += 0x3f;
361 blockSize &= ~0x3f;
362 return blockSize;
365 //=======================================================================
366 void
367 fhandler_dev_dsp::Audio_out::fork_fixup (HANDLE parent)
369 /* Null dev_.
370 It will be necessary to reset the queue, open the device
371 and create a lock when writing */
372 debug_printf ("parent=%p", parent);
373 dev_ = NULL;
377 bool
378 fhandler_dev_dsp::Audio_out::query (int rate, int bits, int channels)
380 WAVEFORMATEX format;
381 MMRESULT rc;
383 fillFormat (&format, rate, bits, channels);
384 rc = waveOutOpen (NULL, WAVE_MAPPER, &format, 0L, 0L, WAVE_FORMAT_QUERY);
385 debug_printf ("%u = waveOutOpen(freq=%d bits=%d channels=%d)", rc, rate, bits, channels);
386 return (rc == MMSYSERR_NOERROR);
389 bool
390 fhandler_dev_dsp::Audio_out::start ()
392 WAVEFORMATEX format;
393 MMRESULT rc;
395 if (dev_)
396 return true;
398 /* In case of fork bigwavebuffer may already exist */
399 if (!bigwavebuffer_)
400 bigwavebuffer_ = new char[fh->fragstotal_ * fh->fragsize_];
402 if (!isvalid ())
403 return false;
405 fillFormat (&format, freq_, bits_, channels_);
406 rc = waveOutOpen (&dev_, WAVE_MAPPER, &format, (DWORD_PTR) waveOut_callback,
407 (DWORD_PTR) this, CALLBACK_FUNCTION);
408 if (rc == MMSYSERR_NOERROR)
409 init (fh->fragsize_);
411 debug_printf ("%u = waveOutOpen(freq=%d bits=%d channels=%d)", rc, freq_, bits_, channels_);
413 return (rc == MMSYSERR_NOERROR);
416 void
417 fhandler_dev_dsp::Audio_out::stop (bool immediately)
419 MMRESULT rc;
420 WAVEHDR *pHdr;
422 debug_printf ("dev_=%p", dev_);
423 if (dev_)
425 if (!immediately)
427 sendcurrent (); // force out last block whatever size..
428 waitforallsent (); // block till finished..
431 rc = waveOutReset (dev_);
432 debug_printf ("%u = waveOutReset()", rc);
433 while (Qisr2app_->recv (&pHdr))
435 rc = waveOutUnprepareHeader (dev_, pHdr, sizeof (WAVEHDR));
436 debug_printf ("%u = waveOutUnprepareHeader(%p)", rc, pHdr);
439 no_thread_exit_protect for_now (true);
440 rc = waveOutClose (dev_);
441 debug_printf ("%u = waveOutClose()", rc);
443 Qisr2app_->dellock ();
447 void
448 fhandler_dev_dsp::Audio_out::init (unsigned blockSize)
450 int i;
452 // internally queue all of our buffer for later use by write
453 Qisr2app_->reset ();
454 for (i = 0; i < fh->fragstotal_; i++)
456 wavehdr_[i].lpData = &bigwavebuffer_[i * blockSize];
457 wavehdr_[i].dwUser = (int) blockSize;
458 wavehdr_[i].dwFlags = 0;
459 if (!Qisr2app_->send (&wavehdr_[i]))
461 system_printf ("Internal Error i=%d", i);
462 break; // should not happen
465 pHdr_ = NULL;
469 fhandler_dev_dsp::Audio_out::write (const char *pSampleData, int nBytes)
471 int bytes_to_write = nBytes;
472 while (bytes_to_write != 0)
473 { // Block if all blocks used until at least one is free
474 if (!waitforspace ())
476 if (bytes_to_write != nBytes)
477 break;
478 return -1;
481 int sizeleft = (int)pHdr_->dwUser - bufferIndex_;
482 if (bytes_to_write < sizeleft)
483 { // all data fits into the current block, with some space left
484 memcpy (&pHdr_->lpData[bufferIndex_], pSampleData, bytes_to_write);
485 bufferIndex_ += bytes_to_write;
486 bytes_to_write = 0;
487 break;
489 else
490 { // data will fill up the current block
491 memcpy (&pHdr_->lpData[bufferIndex_], pSampleData, sizeleft);
492 bufferIndex_ += sizeleft;
493 sendcurrent ();
494 pSampleData += sizeleft;
495 bytes_to_write -= sizeleft;
498 return nBytes - bytes_to_write;
501 void
502 fhandler_dev_dsp::Audio_out::buf_info (audio_buf_info *p,
503 int rate, int bits, int channels)
505 if (dev_)
507 /* If the device is running we use the internal values,
508 possibly set from the wave file. */
509 p->fragstotal = fh->fragstotal_;
510 p->fragsize = fh->fragsize_;
511 p->fragments = Qisr2app_->query ();
512 if (pHdr_ != NULL)
513 p->bytes = (int)pHdr_->dwUser - bufferIndex_
514 + p->fragsize * p->fragments;
515 else
516 p->bytes = p->fragsize * p->fragments;
518 else
520 default_buf_info(p, rate, bits, channels);
524 void fhandler_dev_dsp::Audio_out::default_buf_info (audio_buf_info *p,
525 int rate, int bits, int channels)
527 p->fragstotal = DEFAULT_BLOCKS;
528 p->fragsize = blockSize (125, rate, bits, channels);
529 p->fragments = p->fragstotal;
530 p->bytes = p->fragsize * p->fragments;
533 /* This is called on an interupt so use locking.. Note Qisr2app_
534 is used so we should wrap all references to it in locks. */
535 inline void
536 fhandler_dev_dsp::Audio_out::callback_sampledone (WAVEHDR *pHdr)
538 Qisr2app_->send (pHdr);
539 ReleaseSemaphore (fh->get_select_sem (),
540 get_obj_handle_count (fh->get_select_sem ()), NULL);
543 bool
544 fhandler_dev_dsp::Audio_out::waitforspace ()
546 WAVEHDR *pHdr;
547 MMRESULT rc = WAVERR_STILLPLAYING;
549 if (pHdr_ != NULL)
550 return true;
551 while (!Qisr2app_->recv (&pHdr))
553 if (fh->is_nonblocking ())
555 set_errno (EAGAIN);
556 return false;
558 switch (cygwait (fh->get_select_sem (), 10))
560 case WAIT_SIGNALED:
561 if (!_my_tls.call_signal_handler ())
563 set_errno (EINTR);
564 return false;
566 break;
567 case WAIT_CANCELED:
568 pthread::static_cancel_self ();
569 /*NOTREACHED*/
570 default:
571 break;
574 if (pHdr->dwFlags)
576 /* Errors are ignored here. They will probbaly cause a failure
577 in the subsequent PrepareHeader */
578 rc = waveOutUnprepareHeader (dev_, pHdr, sizeof (WAVEHDR));
579 debug_printf ("%u = waveOutUnprepareHeader(%p)", rc, pHdr);
581 pHdr_ = pHdr;
582 bufferIndex_ = 0;
583 return true;
586 void
587 fhandler_dev_dsp::Audio_out::waitforallsent ()
589 while (Qisr2app_->query () != fh->fragstotal_)
591 debug_printf ("%d blocks in Qisr2app", Qisr2app_->query ());
592 cygwait (1);
593 sendcurrent ();
597 // send the block described by pHdr_ and bufferIndex_ to wave device
598 bool
599 fhandler_dev_dsp::Audio_out::sendcurrent ()
601 WAVEHDR *pHdr = pHdr_;
602 MMRESULT rc;
603 debug_printf ("pHdr=%p bytes=%d", pHdr, bufferIndex_);
605 if (pHdr_ == NULL)
606 return false;
607 pHdr_ = NULL;
609 // Sample buffer conversion
610 (this->*convert_) ((unsigned char *)pHdr->lpData, bufferIndex_);
612 // Send internal buffer out to the soundcard
613 pHdr->dwBufferLength = bufferIndex_;
614 rc = waveOutPrepareHeader (dev_, pHdr, sizeof (WAVEHDR));
615 debug_printf ("%u = waveOutPrepareHeader(%p)", rc, pHdr);
616 if (rc == MMSYSERR_NOERROR)
618 rc = waveOutWrite (dev_, pHdr, sizeof (WAVEHDR));
619 debug_printf ("%u = waveOutWrite(%p)", rc, pHdr);
621 if (rc == MMSYSERR_NOERROR)
622 return true;
624 /* FIXME: Should we return an error instead ?*/
625 pHdr->dwFlags = 0; /* avoid calling UnprepareHeader again */
626 Qisr2app_->send (pHdr);
627 return false;
630 //------------------------------------------------------------------------
631 // Call back routine
632 static void CALLBACK
633 waveOut_callback (HWAVEOUT hWave, UINT msg, DWORD_PTR instance,
634 DWORD_PTR param1, DWORD_PTR param2)
636 if (msg == WOM_DONE)
638 fhandler_dev_dsp::Audio_out *ptr =
639 (fhandler_dev_dsp::Audio_out *) instance;
640 ptr->callback_sampledone ((WAVEHDR *) param1);
644 //------------------------------------------------------------------------
645 // wav file detection..
646 #pragma pack(1)
647 struct wavchunk
649 char id[4];
650 unsigned int len;
652 struct wavformat
654 unsigned short wFormatTag;
655 unsigned short wChannels;
656 unsigned int dwSamplesPerSec;
657 unsigned int dwAvgBytesPerSec;
658 unsigned short wBlockAlign;
659 unsigned short wBitsPerSample;
661 #pragma pack()
663 bool
664 fhandler_dev_dsp::Audio_out::parsewav (const char * &pData, int &nBytes,
665 int dev_freq, int dev_bits, int dev_channels)
667 int len;
668 const char *end = pData + nBytes;
669 const char *pDat;
670 int skip = 0;
672 /* Start with default values from the device handler */
673 freq_ = dev_freq;
674 bits_ = dev_bits;
675 channels_ = dev_channels;
676 setconvert (bits_ == 8 ? AFMT_U8 : AFMT_S16_LE);
678 // Check alignment first: A lot of the code below depends on it
679 if (((uintptr_t)pData & 0x3) != 0)
680 return false;
681 if (!(pData[0] == 'R' && pData[1] == 'I'
682 && pData[2] == 'F' && pData[3] == 'F'))
683 return false;
684 if (!(pData[8] == 'W' && pData[9] == 'A'
685 && pData[10] == 'V' && pData[11] == 'E'))
686 return false;
688 len = *(int *) &pData[4];
689 len -= 12;
690 pDat = pData + 12;
691 skip = 12;
692 while ((len > 0) && (pDat + sizeof (wavchunk) < end))
693 { /* We recognize two kinds of wavchunk:
694 "fmt " for the PCM parameters (only PCM supported here)
695 "data" for the start of PCM data */
696 wavchunk * pChunk = (wavchunk *) pDat;
697 int blklen = pChunk-> len;
698 if (pChunk->id[0] == 'f' && pChunk->id[1] == 'm'
699 && pChunk->id[2] == 't' && pChunk->id[3] == ' ')
701 wavformat *format = (wavformat *) (pChunk + 1);
702 if ((char *) (format + 1) >= end)
703 return false;
704 // We have found the parameter chunk
705 if (format->wFormatTag == 0x0001)
706 { // Micr*s*ft PCM; check if parameters work with our device
707 if (query (format->dwSamplesPerSec, format->wBitsPerSample,
708 format->wChannels))
709 { // return the parameters we found
710 freq_ = format->dwSamplesPerSec;
711 bits_ = format->wBitsPerSample;
712 channels_ = format->wChannels;
716 else
718 if (pChunk->id[0] == 'd' && pChunk->id[1] == 'a'
719 && pChunk->id[2] == 't' && pChunk->id[3] == 'a')
720 { // throw away all the header & not output it to the soundcard.
721 skip += sizeof (wavchunk);
722 debug_printf ("Discard %d bytes wave header", skip);
723 pData += skip;
724 nBytes -= skip;
725 setconvert (bits_ == 8 ? AFMT_U8 : AFMT_S16_LE);
726 return true;
729 pDat += blklen + sizeof (wavchunk);
730 skip += blklen + sizeof (wavchunk);
731 len -= blklen + sizeof (wavchunk);
733 return false;
736 /* ========================================================================
737 Buffering concept for Audio_in:
738 On the first read, we queue all blocks of our bigwavebuffer
739 for reception and start the wave-in device.
740 We manage queues of pointers to WAVEHDR
741 When a block has been filled, the callback puts the corresponding
742 WAVEHDR pointer into a queue.
743 The function read() blocks (polled, sigh) until at least one good buffer
744 has arrived, then the data is copied into the buffer provided to read().
745 After a buffer has been fully used by read(), it is queued again
746 to the wave-in device immediately.
747 The function read() iterates until all data requested has been
748 received, there is no way to interrupt it */
750 void
751 fhandler_dev_dsp::Audio_in::fork_fixup (HANDLE parent)
753 /* Null dev_.
754 It will be necessary to reset the queue, open the device
755 and create a lock when reading */
756 debug_printf ("parent=%p", parent);
757 dev_ = NULL;
760 bool
761 fhandler_dev_dsp::Audio_in::query (int rate, int bits, int channels)
763 WAVEFORMATEX format;
764 MMRESULT rc;
766 fillFormat (&format, rate, bits, channels);
767 rc = waveInOpen (NULL, WAVE_MAPPER, &format, 0L, 0L, WAVE_FORMAT_QUERY);
768 debug_printf ("%u = waveInOpen(freq=%d bits=%d channels=%d)", rc, rate, bits, channels);
769 return (rc == MMSYSERR_NOERROR);
772 bool
773 fhandler_dev_dsp::Audio_in::start (int rate, int bits, int channels)
775 WAVEFORMATEX format;
776 MMRESULT rc;
778 if (dev_)
779 return true;
781 /* In case of fork bigwavebuffer may already exist */
782 if (!bigwavebuffer_)
783 bigwavebuffer_ = new char[fh->fragstotal_ * fh->fragsize_];
785 if (!isvalid ())
786 return false;
788 fillFormat (&format, rate, bits, channels);
789 rc = waveInOpen (&dev_, WAVE_MAPPER, &format, (DWORD_PTR) waveIn_callback,
790 (DWORD_PTR) this, CALLBACK_FUNCTION);
791 debug_printf ("%u = waveInOpen(rate=%d bits=%d channels=%d)", rc, rate, bits, channels);
793 if (rc == MMSYSERR_NOERROR)
795 if (!init (fh->fragsize_))
796 return false;
798 return (rc == MMSYSERR_NOERROR);
801 void
802 fhandler_dev_dsp::Audio_in::stop ()
804 MMRESULT rc;
805 WAVEHDR *pHdr;
807 debug_printf ("dev_=%p", dev_);
808 if (dev_)
810 /* Note that waveInReset calls our callback for all incomplete buffers.
811 Since all the win32 wave functions appear to use a common lock,
812 we must not call into the wave API from the callback.
813 Otherwise we end up in a deadlock. */
814 rc = waveInReset (dev_);
815 debug_printf ("%u = waveInReset()", rc);
817 while (Qisr2app_->recv (&pHdr))
819 rc = waveInUnprepareHeader (dev_, pHdr, sizeof (WAVEHDR));
820 debug_printf ("%u = waveInUnprepareHeader(%p)", rc, pHdr);
823 no_thread_exit_protect for_now (true);
824 rc = waveInClose (dev_);
825 debug_printf ("%u = waveInClose()", rc);
827 Qisr2app_->dellock ();
831 bool
832 fhandler_dev_dsp::Audio_in::queueblock (WAVEHDR *pHdr)
834 MMRESULT rc;
835 rc = waveInPrepareHeader (dev_, pHdr, sizeof (WAVEHDR));
836 debug_printf ("%u = waveInPrepareHeader(%p)", rc, pHdr);
837 if (rc == MMSYSERR_NOERROR)
839 rc = waveInAddBuffer (dev_, pHdr, sizeof (WAVEHDR));
840 debug_printf ("%u = waveInAddBuffer(%p)", rc, pHdr);
842 if (rc == MMSYSERR_NOERROR)
843 return true;
845 /* FIXME: Should the calling function return an error instead ?*/
846 pHdr->dwFlags = 0; /* avoid calling UnprepareHeader again */
847 pHdr->dwBytesRecorded = 0; /* no data will have been read */
848 Qisr2app_->send (pHdr);
849 return false;
852 bool
853 fhandler_dev_dsp::Audio_in::init (unsigned blockSize)
855 MMRESULT rc;
856 int i;
858 // try to queue all of our buffer for reception
859 Qisr2app_->reset ();
860 for (i = 0; i < fh->fragstotal_; i++)
862 wavehdr_[i].lpData = &bigwavebuffer_[i * blockSize];
863 wavehdr_[i].dwBufferLength = blockSize;
864 wavehdr_[i].dwFlags = 0;
865 if (!queueblock (&wavehdr_[i]))
866 break;
868 pHdr_ = NULL;
869 rc = waveInStart (dev_);
870 debug_printf ("%u = waveInStart(), queued=%d", rc, i);
871 return (rc == MMSYSERR_NOERROR);
874 bool
875 fhandler_dev_dsp::Audio_in::read (char *pSampleData, int &nBytes)
877 int bytes_to_read = nBytes;
878 nBytes = 0;
879 debug_printf ("pSampleData=%p nBytes=%d", pSampleData, bytes_to_read);
880 while (bytes_to_read != 0)
881 { // Block till next sound has been read
882 if (!waitfordata ())
884 if (nBytes)
885 return true;
886 nBytes = -1;
887 return false;
890 // Handle gathering our blocks into smaller or larger buffer
891 int sizeleft = pHdr_->dwBytesRecorded - bufferIndex_;
892 if (bytes_to_read < sizeleft)
893 { // The current buffer holds more data than requested
894 memcpy (pSampleData, &pHdr_->lpData[bufferIndex_], bytes_to_read);
895 (this->*convert_) ((unsigned char *)pSampleData, bytes_to_read);
896 nBytes += bytes_to_read;
897 bufferIndex_ += bytes_to_read;
898 debug_printf ("got %d", bytes_to_read);
899 break; // done; use remaining data in next call to read
901 else
902 { // not enough or exact amount in the current buffer
903 if (sizeleft)
904 { // use up what we have
905 memcpy (pSampleData, &pHdr_->lpData[bufferIndex_], sizeleft);
906 (this->*convert_) ((unsigned char *)pSampleData, sizeleft);
907 nBytes += sizeleft;
908 bytes_to_read -= sizeleft;
909 pSampleData += sizeleft;
910 debug_printf ("got %d", sizeleft);
912 queueblock (pHdr_); // re-queue this block to ISR
913 pHdr_ = NULL; // need to wait for a new block
914 // if more samples are needed, we need a new block now
917 debug_printf ("end nBytes=%d", nBytes);
918 return true;
921 bool
922 fhandler_dev_dsp::Audio_in::waitfordata ()
924 WAVEHDR *pHdr;
925 MMRESULT rc;
927 if (pHdr_ != NULL)
928 return true;
929 while (!Qisr2app_->recv (&pHdr))
931 if (fh->is_nonblocking ())
933 set_errno (EAGAIN);
934 return false;
936 switch (cygwait (fh->get_select_sem (), 10))
938 case WAIT_SIGNALED:
939 if (!_my_tls.call_signal_handler ())
941 set_errno (EINTR);
942 return false;
944 break;
945 case WAIT_CANCELED:
946 pthread::static_cancel_self ();
947 /*NOTREACHED*/
948 default:
949 break;
952 if (pHdr->dwFlags) /* Zero if queued following error in queueblock */
954 /* Errors are ignored here. They will probbaly cause a failure
955 in the subsequent PrepareHeader */
956 rc = waveInUnprepareHeader (dev_, pHdr, sizeof (WAVEHDR));
957 debug_printf ("%u = waveInUnprepareHeader(%p)", rc, pHdr);
959 pHdr_ = pHdr;
960 bufferIndex_ = 0;
961 return true;
964 void fhandler_dev_dsp::Audio_in::default_buf_info (audio_buf_info *p,
965 int rate, int bits, int channels)
967 p->fragstotal = DEFAULT_BLOCKS;
968 p->fragsize = blockSize (125, rate, bits, channels);
969 p->fragments = 0;
970 p->bytes = 0;
973 void
974 fhandler_dev_dsp::Audio_in::buf_info (audio_buf_info *p,
975 int rate, int bits, int channels)
977 if (dev_)
979 p->fragstotal = fh->fragstotal_;
980 p->fragsize = fh->fragsize_;
981 p->fragments = Qisr2app_->query ();
982 if (pHdr_ != NULL)
983 p->bytes = pHdr_->dwBytesRecorded - bufferIndex_
984 + p->fragsize * p->fragments;
985 else
986 p->bytes = p->fragsize * p->fragments;
988 else
990 default_buf_info(p, rate, bits, channels);
994 inline void
995 fhandler_dev_dsp::Audio_in::callback_blockfull (WAVEHDR *pHdr)
997 Qisr2app_->send (pHdr);
998 ReleaseSemaphore (fh->get_select_sem (),
999 get_obj_handle_count (fh->get_select_sem ()), NULL);
1002 static void CALLBACK
1003 waveIn_callback (HWAVEIN hWave, UINT msg, DWORD_PTR instance, DWORD_PTR param1,
1004 DWORD_PTR param2)
1006 if (msg == WIM_DATA)
1008 fhandler_dev_dsp::Audio_in *ptr =
1009 (fhandler_dev_dsp::Audio_in *) instance;
1010 ptr->callback_blockfull ((WAVEHDR *) param1);
1015 /* ------------------------------------------------------------------------
1016 /dev/dsp handler
1017 ------------------------------------------------------------------------ */
1018 fhandler_dev_dsp::fhandler_dev_dsp ():
1019 fhandler_base ()
1021 audio_in_ = NULL;
1022 audio_out_ = NULL;
1023 dev ().parse (FH_OSS_DSP);
1026 ssize_t
1027 fhandler_dev_dsp::write (const void *ptr, size_t len)
1029 return base ()->_write (ptr, len, this);
1032 void
1033 fhandler_dev_dsp::read (void *ptr, size_t& len)
1035 base ()->_read (ptr, len, this);
1039 fhandler_dev_dsp::ioctl (unsigned int cmd, void *buf)
1041 return base ()->_ioctl (cmd, buf, this);
1045 fhandler_dev_dsp::fcntl (int cmd, intptr_t arg)
1047 return base ()->_fcntl (cmd, arg);
1050 void
1051 fhandler_dev_dsp::fixup_after_fork (HANDLE parent)
1053 base ()->_fixup_after_fork (parent);
1056 void
1057 fhandler_dev_dsp::fixup_after_exec ()
1059 base ()->_fixup_after_exec ();
1064 fhandler_dev_dsp::open (int flags, mode_t mode)
1066 int ret = -1, err = 0;
1067 UINT num_in = 0, num_out = 0;
1068 // Work out initial sample format & frequency, /dev/dsp defaults
1069 audioformat_ = AFMT_U8;
1070 audiofreq_ = 8000;
1071 audiobits_ = 8;
1072 audiochannels_ = 1;
1073 fragstotal_ = DEFAULT_BLOCKS;
1074 fragment_has_been_set = false;
1075 switch (flags & O_ACCMODE)
1077 case O_RDWR:
1078 if ((num_in = waveInGetNumDevs ()) == 0)
1079 err = ENXIO;
1080 fallthrough;
1081 case O_WRONLY:
1082 if ((num_out = waveOutGetNumDevs ()) == 0)
1083 err = ENXIO;
1084 break;
1085 case O_RDONLY:
1086 if ((num_in = waveInGetNumDevs ()) == 0)
1087 err = ENXIO;
1088 break;
1089 default:
1090 err = EINVAL;
1093 if (err)
1094 set_errno (err);
1095 else
1096 ret = open_null (flags);
1098 select_sem = CreateSemaphore (sec_none_cloexec (mode), 0, INT32_MAX, NULL);
1100 debug_printf ("ACCMODE=%y audio_in=%d audio_out=%d, err=%d, ret=%d",
1101 flags & O_ACCMODE, num_in, num_out, err, ret);
1102 if (ret >= 0)
1103 being_closed = false;
1104 return ret;
1107 #define IS_WRITE() ((fh->get_flags() & O_ACCMODE) != O_RDONLY)
1108 #define IS_READ() ((fh->get_flags() & O_ACCMODE) != O_WRONLY)
1110 ssize_t
1111 fhandler_dev_dsp::_write (const void *ptr, size_t len, fhandler_dev_dsp *fh)
1113 debug_printf ("ptr=%p len=%ld", ptr, len);
1114 int len_s = len;
1115 const char *ptr_s = static_cast <const char *> (ptr);
1117 if (being_closed)
1119 set_errno (EBADF);
1120 return -1;
1123 if (audio_out_)
1124 /* nothing to do */;
1125 else if (IS_WRITE ())
1127 if (fragment_has_been_set)
1128 fragsize_ = max (Audio::blockSize (80.0 / fragstotal_, audiofreq_,
1129 audiobits_, audiochannels_),
1130 fragsize_);
1131 else
1132 fragsize_ = Audio::blockSize (125, audiofreq_, audiobits_,
1133 audiochannels_);
1134 debug_printf ("Allocating");
1135 if (!(audio_out_ = new Audio_out (this)))
1136 return -1;
1138 /* check for wave file & get parameters & skip header if possible. */
1140 if (audio_out_->parsewav (ptr_s, len_s,
1141 audiofreq_, audiobits_, audiochannels_))
1142 debug_printf ("=> ptr_s=%p len_s=%d", ptr_s, len_s);
1144 else
1146 set_errno (EBADF); // device was opened for read?
1147 return -1;
1150 /* Open audio device properly with callbacks.
1151 Private parameters were set in call to parsewav.
1152 This is a no-op when there are successive writes in the same process */
1153 if (!audio_out_->start ())
1155 set_errno (EIO);
1156 return -1;
1159 int written = audio_out_->write (ptr_s, len_s);
1160 if (written < 0)
1162 if (len - len_s > 0)
1163 return len - len_s;
1164 return -1;
1166 return len - len_s + written;
1169 void
1170 fhandler_dev_dsp::_read (void *ptr, size_t& len, fhandler_dev_dsp *fh)
1172 debug_printf ("ptr=%p len=%ld", ptr, len);
1174 if (audio_in_)
1175 /* nothing to do */;
1176 else if (IS_READ ())
1178 if (!fragment_has_been_set)
1179 fragsize_ = Audio::blockSize (125, audiofreq_, audiobits_,
1180 audiochannels_);
1181 debug_printf ("Allocating");
1182 if (!(audio_in_ = new Audio_in (this)))
1184 len = (size_t)-1;
1185 return;
1187 audio_in_->setconvert (audioformat_);
1189 else
1191 len = (size_t)-1;
1192 set_errno (EBADF); // device was opened for write?
1193 return;
1196 /* Open audio device properly with callbacks.
1197 This is a noop when there are successive reads in the same process */
1198 if (!audio_in_->start (audiofreq_, audiobits_, audiochannels_))
1200 len = (size_t)-1;
1201 set_errno (EIO);
1202 return;
1205 int res = len;
1206 audio_in_->read ((char *)ptr, res);
1207 len = (size_t)res;
1210 void
1211 fhandler_dev_dsp::close_audio_in ()
1213 if (audio_in_)
1215 audio_in_->stop ();
1216 delete audio_in_;
1217 audio_in_ = NULL;
1221 void
1222 fhandler_dev_dsp::close_audio_out (bool immediately)
1224 if (audio_out_)
1226 audio_out_->stop (immediately);
1227 delete audio_out_;
1228 audio_out_ = NULL;
1233 fhandler_dev_dsp::close ()
1235 debug_printf ("audio_in=%p audio_out=%p", audio_in_, audio_out_);
1236 being_closed = true;
1237 close_audio_in ();
1238 close_audio_out ();
1239 ReleaseSemaphore (select_sem, get_obj_handle_count (select_sem), NULL);
1240 CloseHandle (select_sem);
1241 select_sem = NULL;
1242 return fhandler_base::close ();
1246 fhandler_dev_dsp::_ioctl (unsigned int cmd, void *buf, fhandler_dev_dsp *fh)
1248 debug_printf ("audio_in=%p audio_out=%p", audio_in_, audio_out_);
1249 int *intbuf = (int *) buf;
1250 switch (cmd)
1252 #define CASE(a) case a : debug_printf ("/dev/dsp: ioctl %s", #a);
1254 CASE (SNDCTL_DSP_RESET)
1255 close_audio_in ();
1256 close_audio_out (true);
1257 return 0;
1258 break;
1260 CASE (SNDCTL_DSP_GETBLKSIZE)
1261 if (fragment_has_been_set)
1262 *intbuf = max (Audio::blockSize (80.0 / fragstotal_, audiofreq_,
1263 audiobits_, audiochannels_),
1264 fragsize_);
1265 else
1266 *intbuf = Audio::blockSize (125, audiofreq_, audiobits_,
1267 audiochannels_);
1268 return 0;
1270 CASE (SNDCTL_DSP_SETFMT)
1272 int nBits;
1273 switch (*intbuf)
1275 case AFMT_QUERY:
1276 *intbuf = audioformat_;
1277 return 0;
1278 break;
1279 case AFMT_U16_BE:
1280 case AFMT_U16_LE:
1281 case AFMT_S16_BE:
1282 case AFMT_S16_LE:
1283 nBits = 16;
1284 break;
1285 case AFMT_U8:
1286 case AFMT_S8:
1287 nBits = 8;
1288 break;
1289 default:
1290 nBits = 0;
1292 if (nBits && IS_WRITE ())
1294 close_audio_out ();
1295 if (audio_out_->query (audiofreq_, nBits, audiochannels_))
1297 audiobits_ = nBits;
1298 audioformat_ = *intbuf;
1300 else
1302 *intbuf = audiobits_;
1303 return -1;
1306 if (nBits && IS_READ ())
1308 close_audio_in ();
1309 if (audio_in_->query (audiofreq_, nBits, audiochannels_))
1311 audiobits_ = nBits;
1312 audioformat_ = *intbuf;
1314 else
1316 *intbuf = audiobits_;
1317 return -1;
1320 return 0;
1323 CASE (SNDCTL_DSP_SPEED)
1324 if (IS_WRITE ())
1326 close_audio_out ();
1327 if (audio_out_->query (*intbuf, audiobits_, audiochannels_))
1328 audiofreq_ = *intbuf;
1329 else
1331 *intbuf = audiofreq_;
1332 return -1;
1335 if (IS_READ ())
1337 close_audio_in ();
1338 if (audio_in_->query (*intbuf, audiobits_, audiochannels_))
1339 audiofreq_ = *intbuf;
1340 else
1342 *intbuf = audiofreq_;
1343 return -1;
1346 return 0;
1348 CASE (SNDCTL_DSP_STEREO)
1350 int nChannels = *intbuf + 1;
1351 int res = _ioctl (SNDCTL_DSP_CHANNELS, &nChannels, fh);
1352 *intbuf = nChannels - 1;
1353 return res;
1356 CASE (SNDCTL_DSP_CHANNELS)
1358 int nChannels = *intbuf;
1360 if (IS_WRITE ())
1362 close_audio_out ();
1363 if (audio_out_->query (audiofreq_, audiobits_, nChannels))
1364 audiochannels_ = nChannels;
1365 else
1367 *intbuf = audiochannels_;
1368 return -1;
1371 if (IS_READ ())
1373 close_audio_in ();
1374 if (audio_in_->query (audiofreq_, audiobits_, nChannels))
1375 audiochannels_ = nChannels;
1376 else
1378 *intbuf = audiochannels_;
1379 return -1;
1382 return 0;
1385 CASE (SNDCTL_DSP_GETOSPACE)
1387 if (!IS_WRITE ())
1389 set_errno(EBADF);
1390 return -1;
1392 audio_buf_info *p = (audio_buf_info *) buf;
1393 if (audio_out_)
1394 audio_out_->buf_info (p, audiofreq_, audiobits_, audiochannels_);
1395 else if (fragment_has_been_set)
1397 p->fragsize = max (Audio::blockSize (80.0 / fragstotal_,
1398 audiofreq_, audiobits_,
1399 audiochannels_),
1400 fragsize_);
1401 p->bytes = p->fragsize * fragstotal_;
1402 p->fragstotal = fragstotal_;
1403 p->fragments = fragstotal_;
1405 else
1406 Audio_out::default_buf_info(p, audiofreq_, audiobits_, audiochannels_);
1407 debug_printf ("buf=%p frags=%d fragsize=%d bytes=%d",
1408 buf, p->fragments, p->fragsize, p->bytes);
1409 return 0;
1412 CASE (SNDCTL_DSP_GETISPACE)
1414 if (!IS_READ ())
1416 set_errno(EBADF);
1417 return -1;
1419 audio_buf_info *p = (audio_buf_info *) buf;
1420 if (audio_in_)
1421 audio_in_->buf_info (p, audiofreq_, audiobits_, audiochannels_);
1422 else if (fragment_has_been_set)
1424 p->bytes = 0;
1425 p->fragsize = max (Audio::blockSize (80.0 / fragstotal_,
1426 audiofreq_, audiobits_,
1427 audiochannels_),
1428 fragsize_);
1429 p->fragstotal = fragstotal_;
1430 p->fragments = 0;
1432 else
1433 Audio_in::default_buf_info(p, audiofreq_, audiobits_, audiochannels_);
1434 debug_printf ("buf=%p frags=%d fragsize=%d bytes=%d",
1435 buf, p->fragments, p->fragsize, p->bytes);
1436 return 0;
1439 CASE (SNDCTL_DSP_SETFRAGMENT)
1441 if (audio_out_ || audio_in_)
1442 return 0; /* Too late to set fragment. Ignore. */
1443 int *p = (int *) buf;
1444 fragstotal_ = min (*p >> 16, MAX_BLOCKS);
1445 fragsize_ = 1 << (*p & 0xffff);
1446 if (fragstotal_ < 2)
1447 fragstotal_ = 2;
1448 fragment_has_been_set = true;
1449 return 0;
1452 CASE (SNDCTL_DSP_GETFMTS)
1453 *intbuf = AFMT_S16_LE | AFMT_U8; // only native formats returned here
1454 return 0;
1456 CASE (SNDCTL_DSP_GETCAPS)
1457 *intbuf = DSP_CAP_BATCH | DSP_CAP_DUPLEX;
1458 return 0;
1460 CASE (SNDCTL_DSP_POST)
1461 if (audio_out_)
1462 audio_out_->sendcurrent (); // force out last block whatever size..
1463 return 0;
1465 CASE (SNDCTL_DSP_SYNC)
1466 if (audio_out_)
1468 audio_out_->sendcurrent (); // force out last block whatever size..
1469 audio_out_->waitforallsent (); // block till finished..
1471 return 0;
1473 default:
1474 return fhandler_base::ioctl (cmd, buf);
1475 break;
1477 #undef CASE
1482 fhandler_dev_dsp::_fcntl (int cmd, intptr_t arg)
1484 return fhandler_base::fcntl(cmd, arg);
1487 void
1488 fhandler_dev_dsp::_fixup_after_fork (HANDLE parent)
1489 { // called from new child process
1490 debug_printf ("audio_in=%p audio_out=%p",
1491 audio_in_, audio_out_);
1493 fhandler_base::fixup_after_fork (parent);
1494 if (audio_in_)
1495 audio_in_->fork_fixup (parent);
1496 if (audio_out_)
1497 audio_out_->fork_fixup (parent);
1500 void
1501 fhandler_dev_dsp::_fixup_after_exec ()
1503 debug_printf ("audio_in=%p audio_out=%p, close_on_exec %d",
1504 audio_in_, audio_out_, close_on_exec ());
1505 if (!close_on_exec ())
1507 audio_in_ = NULL;
1508 audio_out_ = NULL;
1512 bool
1513 fhandler_dev_dsp::_write_ready ()
1515 audio_buf_info info;
1516 if (audio_out_)
1518 audio_out_->buf_info (&info, audiofreq_, audiobits_, audiochannels_);
1519 return info.bytes > 0;
1521 else
1522 return true;
1525 bool
1526 fhandler_dev_dsp::_read_ready ()
1528 audio_buf_info info;
1529 if (audio_in_)
1531 audio_in_->buf_info (&info, audiofreq_, audiobits_, audiochannels_);
1532 return info.bytes > 0;
1534 else
1535 return true;
1538 bool
1539 fhandler_dev_dsp::write_ready ()
1541 return base ()->_write_ready ();
1544 bool
1545 fhandler_dev_dsp::read_ready ()
1547 return base ()->_read_ready ();
1550 bool
1551 fhandler_dev_dsp::open_setup (int flags)
1553 set_flags ((flags & ~O_TEXT) | O_BINARY);
1554 return fhandler_base::open_setup (flags);