OSDN Git Service

Remove unneeded header files from source files throughout.
[pf3gnuchains/sourceware.git] / winsup / cygwin / fhandler_dsp.cc
1 /* Fhandler_dev_dsp: code to emulate OSS sound model /dev/dsp
2
3    Copyright 2001, 2002, 2003, 2004, 2008 Red Hat, Inc
4
5    Written by Andy Younger (andy@snoogie.demon.co.uk)
6    Extended by Gerd Spalink (Gerd.Spalink@t-online.de)
7      to support recording from the audio input
8
9 This file is part of Cygwin.
10
11 This software is a copyrighted work licensed under the terms of the
12 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
13 details. */
14
15 #include "winsup.h"
16 #include <sys/soundcard.h>
17 #include "cygerrno.h"
18 #include "security.h"
19 #include "path.h"
20 #include "fhandler.h"
21 #include "dtable.h"
22 #include "cygheap.h"
23
24 /*------------------------------------------------------------------------
25   Simple encapsulation of the win32 audio device.
26
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._
41
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.
47  */
48
49 class fhandler_dev_dsp::Audio
50 { // This class contains functionality common to Audio_in and Audio_out
51  public:
52    Audio ();
53    ~Audio ();
54
55   class queue;
56
57   bool isvalid ();
58   void setconvert (int format);
59   void convert_none (unsigned char *buffer, int size_bytes) { }
60   void convert_U8_S8 (unsigned char *buffer, int size_bytes);
61   void convert_S16LE_U16LE (unsigned char *buffer, int size_bytes);
62   void convert_S16LE_U16BE (unsigned char *buffer, int size_bytes);
63   void convert_S16LE_S16BE (unsigned char *buffer, int size_bytes);
64   void fillFormat (WAVEFORMATEX * format,
65                    int rate, int bits, int channels);
66   unsigned blockSize (int rate, int bits, int channels);
67   void (fhandler_dev_dsp::Audio::*convert_)
68     (unsigned char *buffer, int size_bytes);
69
70   enum { MAX_BLOCKS = 12 };
71   int bufferIndex_;  // offset into pHdr_->lpData
72   WAVEHDR *pHdr_;    // data to be filled by write
73   WAVEHDR wavehdr_[MAX_BLOCKS];
74   char *bigwavebuffer_; // audio samples only
75   // Member variables below must be locked
76   queue *Qisr2app_; // blocks passed from wave callback
77 };
78
79 class fhandler_dev_dsp::Audio::queue
80 { // non-blocking fixed size queues for buffer management
81  public:
82    queue (int depth = 4);
83   ~queue ();
84
85   bool send (WAVEHDR *);  // queue an item, returns true if successful
86   bool recv (WAVEHDR **); // retrieve an item, returns true if successful
87   void reset ();
88   int query (); // return number of items queued
89   inline void lock () { EnterCriticalSection (&lock_); }
90   inline void unlock () { LeaveCriticalSection (&lock_); }
91   inline void dellock () { debug_printf ("Deleting Critical Section"); DeleteCriticalSection (&lock_); }
92   bool isvalid () { return storage_; }
93  private:
94   CRITICAL_SECTION lock_;
95   int head_;
96   int tail_;
97   int depth_;
98   WAVEHDR **storage_;
99 };
100
101 static void CALLBACK waveOut_callback (HWAVEOUT hWave, UINT msg, DWORD instance,
102                                        DWORD param1, DWORD param2);
103
104 class fhandler_dev_dsp::Audio_out: public Audio
105 {
106  public:
107   void fork_fixup (HANDLE parent);
108   bool query (int rate, int bits, int channels);
109   bool start ();
110   void stop (bool immediately = false);
111   bool write (const char *pSampleData, int nBytes);
112   void buf_info (audio_buf_info *p, int rate, int bits, int channels);
113   void callback_sampledone (WAVEHDR *pHdr);
114   bool parsewav (const char *&pData, int &nBytes,
115                  int rate, int bits, int channels);
116
117  private:
118   void init (unsigned blockSize);
119   void waitforallsent ();
120   void waitforspace ();
121   bool sendcurrent ();
122
123   enum { MAX_BLOCKS = 12 };
124   HWAVEOUT dev_;     // The wave device
125   /* Private copies of audiofreq_, audiobits_, audiochannels_,
126      possibly set from wave file */
127   int freq_;
128   int bits_;
129   int channels_;
130 };
131
132 static void CALLBACK waveIn_callback (HWAVEIN hWave, UINT msg, DWORD instance,
133                                       DWORD param1, DWORD param2);
134
135 class fhandler_dev_dsp::Audio_in: public Audio
136 {
137 public:
138   void fork_fixup (HANDLE parent);
139   bool query (int rate, int bits, int channels);
140   bool start (int rate, int bits, int channels);
141   void stop ();
142   bool read (char *pSampleData, int &nBytes);
143   void buf_info (audio_buf_info *p, int rate, int bits, int channels);
144   void callback_blockfull (WAVEHDR *pHdr);
145
146 private:
147   bool init (unsigned blockSize);
148   bool queueblock (WAVEHDR *pHdr);
149   void waitfordata (); // blocks until we have a good pHdr_
150
151   HWAVEIN dev_;
152 };
153
154 /* --------------------------------------------------------------------
155    Implementation */
156
157 // Simple fixed length FIFO queue implementation for audio buffer management
158 fhandler_dev_dsp::Audio::queue::queue (int depth)
159 {
160   // allow space for one extra object in the queue
161   // so we can distinguish full and empty status
162   depth_ = depth;
163   storage_ = new WAVEHDR *[depth_ + 1];
164 }
165
166 fhandler_dev_dsp::Audio::queue::~queue ()
167 {
168   delete[] storage_;
169 }
170
171 void
172 fhandler_dev_dsp::Audio::queue::reset ()
173  {
174    /* When starting, after reset and after fork */
175    head_ = tail_ = 0;
176    debug_printf ("InitializeCriticalSection");
177    memset (&lock_, 0, sizeof (lock_));
178    InitializeCriticalSection (&lock_);
179  }
180
181 bool
182 fhandler_dev_dsp::Audio::queue::send (WAVEHDR *x)
183 {
184   bool res = false;
185   lock ();
186   if (query () == depth_)
187     system_printf ("Queue overflow");
188   else
189     {
190       storage_[tail_] = x;
191       if (++tail_ > depth_)
192         tail_ = 0;
193       res = true;
194     }
195   unlock ();
196   return res;
197 }
198
199 bool
200 fhandler_dev_dsp::Audio::queue::recv (WAVEHDR **x)
201 {
202   bool res = false;
203   lock ();
204   if (query () != 0)
205     {
206       *x = storage_[head_];
207       if (++head_ > depth_)
208         head_ = 0;
209       res = true;
210     }
211   unlock ();
212   return res;
213 }
214
215 int
216 fhandler_dev_dsp::Audio::queue::query ()
217 {
218   int n = tail_ - head_;
219   if (n < 0)
220     n += depth_ + 1;
221   return n;
222 }
223
224 // Audio class implements functionality need for both read and write
225 fhandler_dev_dsp::Audio::Audio ()
226 {
227   bigwavebuffer_ = NULL;
228   Qisr2app_ = new queue (MAX_BLOCKS);
229   convert_ = &fhandler_dev_dsp::Audio::convert_none;
230 }
231
232 fhandler_dev_dsp::Audio::~Audio ()
233 {
234   debug_printf("");
235   delete Qisr2app_;
236   delete[] bigwavebuffer_;
237 }
238
239 inline bool
240 fhandler_dev_dsp::Audio::isvalid ()
241 {
242   return bigwavebuffer_ && Qisr2app_ && Qisr2app_->isvalid ();
243 }
244
245 void
246 fhandler_dev_dsp::Audio::setconvert (int format)
247 {
248   switch (format)
249     {
250     case AFMT_S8:
251       convert_ = &fhandler_dev_dsp::Audio::convert_U8_S8;
252       debug_printf ("U8_S8");
253       break;
254     case AFMT_U16_LE:
255       convert_ = &fhandler_dev_dsp::Audio::convert_S16LE_U16LE;
256       debug_printf ("S16LE_U16LE");
257       break;
258     case AFMT_U16_BE:
259       convert_ = &fhandler_dev_dsp::Audio::convert_S16LE_U16BE;
260       debug_printf ("S16LE_U16BE");
261       break;
262     case AFMT_S16_BE:
263       convert_ = &fhandler_dev_dsp::Audio::convert_S16LE_S16BE;
264       debug_printf ("S16LE_S16BE");
265       break;
266     default:
267       convert_ = &fhandler_dev_dsp::Audio::convert_none;
268       debug_printf ("none");
269     }
270 }
271
272 void
273 fhandler_dev_dsp::Audio::convert_U8_S8 (unsigned char *buffer,
274                                         int size_bytes)
275 {
276   while (size_bytes-- > 0)
277     {
278       *buffer ^= (unsigned char)0x80;
279       buffer++;
280     }
281 }
282
283 void
284 fhandler_dev_dsp::Audio::convert_S16LE_U16BE (unsigned char *buffer,
285                                               int size_bytes)
286 {
287   int size_samples = size_bytes / 2;
288   unsigned char hi, lo;
289   while (size_samples-- > 0)
290     {
291       hi = buffer[0];
292       lo = buffer[1];
293       *buffer++ = lo;
294       *buffer++ = hi ^ (unsigned char)0x80;
295     }
296 }
297
298 void
299 fhandler_dev_dsp::Audio::convert_S16LE_U16LE (unsigned char *buffer,
300                                               int size_bytes)
301 {
302   int size_samples = size_bytes / 2;
303   while (size_samples-- > 0)
304     {
305       buffer++;
306       *buffer ^= (unsigned char)0x80;
307       buffer++;
308     }
309 }
310
311 void
312 fhandler_dev_dsp::Audio::convert_S16LE_S16BE (unsigned char *buffer,
313                                               int size_bytes)
314 {
315   int size_samples = size_bytes / 2;
316   unsigned char hi, lo;
317   while (size_samples-- > 0)
318     {
319       hi = buffer[0];
320       lo = buffer[1];
321       *buffer++ = lo;
322       *buffer++ = hi;
323     }
324 }
325
326 void
327 fhandler_dev_dsp::Audio::fillFormat (WAVEFORMATEX * format,
328                                      int rate, int bits, int channels)
329 {
330   memset (format, 0, sizeof (*format));
331   format->wFormatTag = WAVE_FORMAT_PCM;
332   format->wBitsPerSample = bits;
333   format->nChannels = channels;
334   format->nSamplesPerSec = rate;
335   format->nAvgBytesPerSec = format->nSamplesPerSec * format->nChannels
336     * (bits / 8);
337   format->nBlockAlign = format->nChannels * (bits / 8);
338 }
339
340 // calculate a good block size
341 unsigned
342 fhandler_dev_dsp::Audio::blockSize (int rate, int bits, int channels)
343 {
344   unsigned blockSize;
345   blockSize = ((bits / 8) * channels * rate) / 8; // approx 125ms per block
346   // round up to multiple of 64
347   blockSize +=  0x3f;
348   blockSize &= ~0x3f;
349   return blockSize;
350 }
351
352 //=======================================================================
353 void
354 fhandler_dev_dsp::Audio_out::fork_fixup (HANDLE parent)
355 {
356   /* Null dev_.
357      It will be necessary to reset the queue, open the device
358      and create a lock when writing */
359   debug_printf ("parent=0x%08x", parent);
360   dev_ = NULL;
361 }
362
363
364 bool
365 fhandler_dev_dsp::Audio_out::query (int rate, int bits, int channels)
366 {
367   WAVEFORMATEX format;
368   MMRESULT rc;
369
370   fillFormat (&format, rate, bits, channels);
371   rc = waveOutOpen (NULL, WAVE_MAPPER, &format, 0L, 0L, WAVE_FORMAT_QUERY);
372   debug_printf ("%d = waveOutOpen (freq=%d bits=%d channels=%d)", rc, rate, bits, channels);
373   return (rc == MMSYSERR_NOERROR);
374 }
375
376 bool
377 fhandler_dev_dsp::Audio_out::start ()
378 {
379   WAVEFORMATEX format;
380   MMRESULT rc;
381   unsigned bSize = blockSize (freq_, bits_, channels_);
382
383   if (dev_)
384     return true;
385
386   /* In case of fork bigwavebuffer may already exist */
387   if (!bigwavebuffer_)
388     bigwavebuffer_ = new char[MAX_BLOCKS * bSize];
389
390   if (!isvalid ())
391     return false;
392
393   fillFormat (&format, freq_, bits_, channels_);
394   rc = waveOutOpen (&dev_, WAVE_MAPPER, &format, (DWORD) waveOut_callback,
395                      (DWORD) this, CALLBACK_FUNCTION);
396   if (rc == MMSYSERR_NOERROR)
397     init (bSize);
398
399   debug_printf ("%d = waveOutOpen (freq=%d bits=%d channels=%d)", rc, freq_, bits_, channels_);
400
401   return (rc == MMSYSERR_NOERROR);
402 }
403
404 void
405 fhandler_dev_dsp::Audio_out::stop (bool immediately)
406 {
407   MMRESULT rc;
408   WAVEHDR *pHdr;
409
410   debug_printf ("dev_=%08x", (int)dev_);
411   if (dev_)
412     {
413       if (!immediately)
414         {
415           sendcurrent ();       // force out last block whatever size..
416           waitforallsent ();    // block till finished..
417         }
418
419       rc = waveOutReset (dev_);
420       debug_printf ("%d = waveOutReset ()", rc);
421       while (Qisr2app_->recv (&pHdr))
422         {
423           rc = waveOutUnprepareHeader (dev_, pHdr, sizeof (WAVEHDR));
424           debug_printf ("%d = waveOutUnprepareHeader (0x%08x)", rc, pHdr);
425         }
426
427       rc = waveOutClose (dev_);
428       debug_printf ("%d = waveOutClose ()", rc);
429
430       Qisr2app_->dellock ();
431     }
432 }
433
434 void
435 fhandler_dev_dsp::Audio_out::init (unsigned blockSize)
436 {
437   int i;
438
439   // internally queue all of our buffer for later use by write
440   Qisr2app_->reset ();
441   for (i = 0; i < MAX_BLOCKS; i++)
442     {
443       wavehdr_[i].lpData = &bigwavebuffer_[i * blockSize];
444       wavehdr_[i].dwUser = (int) blockSize;
445       wavehdr_[i].dwFlags = 0;
446       if (!Qisr2app_->send (&wavehdr_[i]))
447         {
448           system_printf ("Internal Error i=%d", i);
449           break; // should not happen
450         }
451     }
452   pHdr_ = NULL;
453 }
454
455 bool
456 fhandler_dev_dsp::Audio_out::write (const char *pSampleData, int nBytes)
457 {
458   while (nBytes != 0)
459     { // Block if all blocks used until at least one is free
460       waitforspace ();
461
462       int sizeleft = (int)pHdr_->dwUser - bufferIndex_;
463       if (nBytes < sizeleft)
464         { // all data fits into the current block, with some space left
465           memcpy (&pHdr_->lpData[bufferIndex_], pSampleData, nBytes);
466           bufferIndex_ += nBytes;
467           break;
468         }
469       else
470         { // data will fill up the current block
471           memcpy (&pHdr_->lpData[bufferIndex_], pSampleData, sizeleft);
472           bufferIndex_ += sizeleft;
473           sendcurrent ();
474           pSampleData += sizeleft;
475           nBytes -= sizeleft;
476         }
477     }
478   return true;
479 }
480
481 void
482 fhandler_dev_dsp::Audio_out::buf_info (audio_buf_info *p,
483                                        int rate, int bits, int channels)
484 {
485   p->fragstotal = MAX_BLOCKS;
486   if (this && dev_)
487     {
488       /* If the device is running we use the internal values,
489          possibly set from the wave file. */
490       p->fragsize = blockSize (freq_, bits_, channels_);
491       p->fragments = Qisr2app_->query ();
492       if (pHdr_ != NULL)
493         p->bytes = (int)pHdr_->dwUser - bufferIndex_
494           + p->fragsize * p->fragments;
495       else
496         p->bytes = p->fragsize * p->fragments;
497     }
498   else
499     {
500       p->fragsize = blockSize (rate, bits, channels);
501       p->fragments = MAX_BLOCKS;
502       p->bytes = p->fragsize * p->fragments;
503     }
504 }
505
506 /* This is called on an interupt so use locking.. Note Qisr2app_
507    is used so we should wrap all references to it in locks. */
508 inline void
509 fhandler_dev_dsp::Audio_out::callback_sampledone (WAVEHDR *pHdr)
510 {
511   Qisr2app_->send (pHdr);
512 }
513
514 void
515 fhandler_dev_dsp::Audio_out::waitforspace ()
516 {
517   WAVEHDR *pHdr;
518   MMRESULT rc = WAVERR_STILLPLAYING;
519
520   if (pHdr_ != NULL)
521     return;
522   while (!Qisr2app_->recv (&pHdr))
523     {
524       debug_printf ("100ms");
525       Sleep (100);
526     }
527   if (pHdr->dwFlags)
528     {
529       /* Errors are ignored here. They will probbaly cause a failure
530          in the subsequent PrepareHeader */
531       rc = waveOutUnprepareHeader (dev_, pHdr, sizeof (WAVEHDR));
532       debug_printf ("%d = waveOutUnprepareHeader (0x%08x)", rc, pHdr);
533     }
534   pHdr_ = pHdr;
535   bufferIndex_ = 0;
536 }
537
538 void
539 fhandler_dev_dsp::Audio_out::waitforallsent ()
540 {
541   while (Qisr2app_->query () != MAX_BLOCKS)
542     {
543       debug_printf ("%d blocks in Qisr2app", Qisr2app_->query ());
544       Sleep (100);
545     }
546 }
547
548 // send the block described by pHdr_ and bufferIndex_ to wave device
549 bool
550 fhandler_dev_dsp::Audio_out::sendcurrent ()
551 {
552   WAVEHDR *pHdr = pHdr_;
553   MMRESULT rc;
554   debug_printf ("pHdr=0x%08x bytes=%d", pHdr, bufferIndex_);
555
556   if (pHdr_ == NULL)
557     return false;
558   pHdr_ = NULL;
559
560   // Sample buffer conversion
561   (this->*convert_) ((unsigned char *)pHdr->lpData, bufferIndex_);
562
563   // Send internal buffer out to the soundcard
564   pHdr->dwBufferLength = bufferIndex_;
565   rc = waveOutPrepareHeader (dev_, pHdr, sizeof (WAVEHDR));
566   debug_printf ("%d = waveOutPrepareHeader (0x%08x)", rc, pHdr);
567   if (rc == MMSYSERR_NOERROR)
568     {
569       rc = waveOutWrite (dev_, pHdr, sizeof (WAVEHDR));
570       debug_printf ("%d = waveOutWrite (0x%08x)", rc, pHdr);
571     }
572   if (rc == MMSYSERR_NOERROR)
573     return true;
574
575   /* FIXME: Should we return an error instead ?*/
576   pHdr->dwFlags = 0; /* avoid calling UnprepareHeader again */
577   Qisr2app_->send (pHdr);
578   return false;
579 }
580
581 //------------------------------------------------------------------------
582 // Call back routine
583 static void CALLBACK
584 waveOut_callback (HWAVEOUT hWave, UINT msg, DWORD instance, DWORD param1,
585                   DWORD param2)
586 {
587   if (msg == WOM_DONE)
588     {
589       fhandler_dev_dsp::Audio_out *ptr =
590         (fhandler_dev_dsp::Audio_out *) instance;
591       ptr->callback_sampledone ((WAVEHDR *) param1);
592     }
593 }
594
595 //------------------------------------------------------------------------
596 // wav file detection..
597 #pragma pack(1)
598 struct wavchunk
599 {
600   char id[4];
601   unsigned int len;
602 };
603 struct wavformat
604 {
605   unsigned short wFormatTag;
606   unsigned short wChannels;
607   unsigned int dwSamplesPerSec;
608   unsigned int dwAvgBytesPerSec;
609   unsigned short wBlockAlign;
610   unsigned short wBitsPerSample;
611 };
612 #pragma pack()
613
614 bool
615 fhandler_dev_dsp::Audio_out::parsewav (const char * &pData, int &nBytes,
616                                        int dev_freq, int dev_bits, int dev_channels)
617 {
618   int len;
619   const char *end = pData + nBytes;
620   const char *pDat;
621   int skip = 0;
622
623   /* Start with default values from the device handler */
624   freq_ = dev_freq;
625   bits_ = dev_bits;
626   channels_ = dev_channels;
627   setconvert (bits_ == 8 ? AFMT_U8 : AFMT_S16_LE);
628
629   // Check alignment first: A lot of the code below depends on it
630   if (((int)pData & 0x3) != 0)
631     return false;
632   if (!(pData[0] == 'R' && pData[1] == 'I'
633         && pData[2] == 'F' && pData[3] == 'F'))
634     return false;
635   if (!(pData[8] == 'W' && pData[9] == 'A'
636         && pData[10] == 'V' && pData[11] == 'E'))
637     return false;
638
639   len = *(int *) &pData[4];
640   len -= 12;
641   pDat = pData + 12;
642   skip = 12;
643   while ((len > 0) && (pDat + sizeof (wavchunk) < end))
644     { /* We recognize two kinds of wavchunk:
645          "fmt " for the PCM parameters (only PCM supported here)
646          "data" for the start of PCM data */
647       wavchunk * pChunk = (wavchunk *) pDat;
648       int blklen = pChunk-> len;
649       if (pChunk->id[0] == 'f' && pChunk->id[1] == 'm'
650           && pChunk->id[2] == 't' && pChunk->id[3] == ' ')
651         {
652           wavformat *format = (wavformat *) (pChunk + 1);
653           if ((char *) (format + 1) >= end)
654             return false;
655           // We have found the parameter chunk
656           if (format->wFormatTag == 0x0001)
657             { // Micr*s*ft PCM; check if parameters work with our device
658               if (query (format->dwSamplesPerSec, format->wBitsPerSample,
659                          format->wChannels))
660                 { // return the parameters we found
661                   freq_ = format->dwSamplesPerSec;
662                   bits_ = format->wBitsPerSample;
663                   channels_ = format->wChannels;
664                 }
665             }
666         }
667       else
668         {
669           if (pChunk->id[0] == 'd' && pChunk->id[1] == 'a'
670               && pChunk->id[2] == 't' && pChunk->id[3] == 'a')
671             { // throw away all the header & not output it to the soundcard.
672               skip += sizeof (wavchunk);
673               debug_printf ("Discard %d bytes wave header", skip);
674               pData += skip;
675               nBytes -= skip;
676               setconvert (bits_ == 8 ? AFMT_U8 : AFMT_S16_LE);
677               return true;
678             }
679         }
680       pDat += blklen + sizeof (wavchunk);
681       skip += blklen + sizeof (wavchunk);
682       len -= blklen + sizeof (wavchunk);
683     }
684   return false;
685 }
686
687 /* ========================================================================
688    Buffering concept for Audio_in:
689    On the first read, we queue all blocks of our bigwavebuffer
690    for reception and start the wave-in device.
691    We manage queues of pointers to WAVEHDR
692    When a block has been filled, the callback puts the corresponding
693    WAVEHDR pointer into a queue.
694    The function read() blocks (polled, sigh) until at least one good buffer
695    has arrived, then the data is copied into the buffer provided to read().
696    After a buffer has been fully used by read(), it is queued again
697    to the wave-in device immediately.
698    The function read() iterates until all data requested has been
699    received, there is no way to interrupt it */
700
701 void
702 fhandler_dev_dsp::Audio_in::fork_fixup (HANDLE parent)
703 {
704   /* Null dev_.
705      It will be necessary to reset the queue, open the device
706      and create a lock when reading */
707   debug_printf ("parent=0x%08x", parent);
708   dev_ = NULL;
709 }
710
711 bool
712 fhandler_dev_dsp::Audio_in::query (int rate, int bits, int channels)
713 {
714   WAVEFORMATEX format;
715   MMRESULT rc;
716
717   fillFormat (&format, rate, bits, channels);
718   rc = waveInOpen (NULL, WAVE_MAPPER, &format, 0L, 0L, WAVE_FORMAT_QUERY);
719   debug_printf ("%d = waveInOpen (freq=%d bits=%d channels=%d)", rc, rate, bits, channels);
720   return (rc == MMSYSERR_NOERROR);
721 }
722
723 bool
724 fhandler_dev_dsp::Audio_in::start (int rate, int bits, int channels)
725 {
726   WAVEFORMATEX format;
727   MMRESULT rc;
728   unsigned bSize = blockSize (rate, bits, channels);
729
730   if (dev_)
731     return true;
732
733   /* In case of fork bigwavebuffer may already exist */
734   if (!bigwavebuffer_)
735     bigwavebuffer_ = new char[MAX_BLOCKS * bSize];
736
737   if (!isvalid ())
738     return false;
739
740   fillFormat (&format, rate, bits, channels);
741   rc = waveInOpen (&dev_, WAVE_MAPPER, &format, (DWORD) waveIn_callback,
742                    (DWORD) this, CALLBACK_FUNCTION);
743   debug_printf ("%d = waveInOpen (rate=%d bits=%d channels=%d)", rc, rate, bits, channels);
744
745   if (rc == MMSYSERR_NOERROR)
746     {
747       if (!init (bSize))
748         return false;
749     }
750   return (rc == MMSYSERR_NOERROR);
751 }
752
753 void
754 fhandler_dev_dsp::Audio_in::stop ()
755 {
756   MMRESULT rc;
757   WAVEHDR *pHdr;
758
759   debug_printf ("dev_=%08x", (int)dev_);
760   if (dev_)
761     {
762       /* Note that waveInReset calls our callback for all incomplete buffers.
763          Since all the win32 wave functions appear to use a common lock,
764          we must not call into the wave API from the callback.
765          Otherwise we end up in a deadlock. */
766       rc = waveInReset (dev_);
767       debug_printf ("%d = waveInReset ()", rc);
768
769       while (Qisr2app_->recv (&pHdr))
770         {
771           rc = waveInUnprepareHeader (dev_, pHdr, sizeof (WAVEHDR));
772           debug_printf ("%d = waveInUnprepareHeader (0x%08x)", rc, pHdr);
773         }
774
775       rc = waveInClose (dev_);
776       debug_printf ("%d = waveInClose ()", rc);
777
778       Qisr2app_->dellock ();
779     }
780 }
781
782 bool
783 fhandler_dev_dsp::Audio_in::queueblock (WAVEHDR *pHdr)
784 {
785   MMRESULT rc;
786   rc = waveInPrepareHeader (dev_, pHdr, sizeof (WAVEHDR));
787   debug_printf ("%d = waveInPrepareHeader (0x%08x)", rc, pHdr);
788   if (rc == MMSYSERR_NOERROR)
789     {
790       rc = waveInAddBuffer (dev_, pHdr, sizeof (WAVEHDR));
791       debug_printf ("%d = waveInAddBuffer (0x%08x)", rc, pHdr);
792     }
793   if (rc == MMSYSERR_NOERROR)
794     return true;
795
796   /* FIXME: Should the calling function return an error instead ?*/
797   pHdr->dwFlags = 0;  /* avoid calling UnprepareHeader again */
798   pHdr->dwBytesRecorded = 0;  /* no data will have been read */
799   Qisr2app_->send (pHdr);
800   return false;
801 }
802
803 bool
804 fhandler_dev_dsp::Audio_in::init (unsigned blockSize)
805 {
806   MMRESULT rc;
807   int i;
808
809   // try to queue all of our buffer for reception
810   Qisr2app_->reset ();
811   for (i = 0; i < MAX_BLOCKS; i++)
812     {
813       wavehdr_[i].lpData = &bigwavebuffer_[i * blockSize];
814       wavehdr_[i].dwBufferLength = blockSize;
815       wavehdr_[i].dwFlags = 0;
816       if (!queueblock (&wavehdr_[i]))
817         break;
818     }
819   pHdr_ = NULL;
820   rc = waveInStart (dev_);
821   debug_printf ("%d = waveInStart (), queued=%d", rc, i);
822   return (rc == MMSYSERR_NOERROR);
823 }
824
825 bool
826 fhandler_dev_dsp::Audio_in::read (char *pSampleData, int &nBytes)
827 {
828   int bytes_to_read = nBytes;
829   nBytes = 0;
830   debug_printf ("pSampleData=%08x nBytes=%d", pSampleData, bytes_to_read);
831   while (bytes_to_read != 0)
832     { // Block till next sound has been read
833       waitfordata ();
834
835       // Handle gathering our blocks into smaller or larger buffer
836       int sizeleft = pHdr_->dwBytesRecorded - bufferIndex_;
837       if (bytes_to_read < sizeleft)
838         { // The current buffer holds more data than requested
839           memcpy (pSampleData, &pHdr_->lpData[bufferIndex_], bytes_to_read);
840           (this->*convert_) ((unsigned char *)pSampleData, bytes_to_read);
841           nBytes += bytes_to_read;
842           bufferIndex_ += bytes_to_read;
843           debug_printf ("got %d", bytes_to_read);
844           break; // done; use remaining data in next call to read
845         }
846       else
847         { // not enough or exact amount in the current buffer
848           if (sizeleft)
849             { // use up what we have
850               memcpy (pSampleData, &pHdr_->lpData[bufferIndex_], sizeleft);
851               (this->*convert_) ((unsigned char *)pSampleData, sizeleft);
852               nBytes += sizeleft;
853               bytes_to_read -= sizeleft;
854               pSampleData += sizeleft;
855               debug_printf ("got %d", sizeleft);
856             }
857           queueblock (pHdr_); // re-queue this block to ISR
858           pHdr_ = NULL;       // need to wait for a new block
859           // if more samples are needed, we need a new block now
860         }
861     }
862   debug_printf ("end nBytes=%d", nBytes);
863   return true;
864 }
865
866 void
867 fhandler_dev_dsp::Audio_in::waitfordata ()
868 {
869   WAVEHDR *pHdr;
870   MMRESULT rc;
871
872   if (pHdr_ != NULL)
873     return;
874   while (!Qisr2app_->recv (&pHdr))
875     {
876       debug_printf ("100ms");
877       Sleep (100);
878     }
879   if (pHdr->dwFlags) /* Zero if queued following error in queueblock */
880     {
881       /* Errors are ignored here. They will probbaly cause a failure
882          in the subsequent PrepareHeader */
883       rc = waveInUnprepareHeader (dev_, pHdr, sizeof (WAVEHDR));
884       debug_printf ("%d = waveInUnprepareHeader (0x%08x)", rc, pHdr);
885     }
886   pHdr_ = pHdr;
887   bufferIndex_ = 0;
888 }
889
890 void
891 fhandler_dev_dsp::Audio_in::buf_info (audio_buf_info *p,
892                                       int rate, int bits, int channels)
893 {
894   p->fragstotal = MAX_BLOCKS;
895   p->fragsize = blockSize (rate, bits, channels);
896   if (this && dev_)
897     {
898       p->fragments = Qisr2app_->query ();
899       if (pHdr_ != NULL)
900         p->bytes = pHdr_->dwBytesRecorded - bufferIndex_
901           + p->fragsize * p->fragments;
902       else
903         p->bytes = p->fragsize * p->fragments;
904     }
905   else
906     {
907       p->fragments = 0;
908       p->bytes = 0;
909     }
910 }
911
912 inline void
913 fhandler_dev_dsp::Audio_in::callback_blockfull (WAVEHDR *pHdr)
914 {
915   Qisr2app_->send (pHdr);
916 }
917
918 static void CALLBACK
919 waveIn_callback (HWAVEIN hWave, UINT msg, DWORD instance, DWORD param1,
920                  DWORD param2)
921 {
922   if (msg == WIM_DATA)
923     {
924       fhandler_dev_dsp::Audio_in *ptr =
925         (fhandler_dev_dsp::Audio_in *) instance;
926       ptr->callback_blockfull ((WAVEHDR *) param1);
927     }
928 }
929
930
931 /* ------------------------------------------------------------------------
932    /dev/dsp handler
933    ------------------------------------------------------------------------ */
934 fhandler_dev_dsp::fhandler_dev_dsp ():
935   fhandler_base ()
936 {
937   debug_printf ("0x%08x", (int)this);
938   audio_in_ = NULL;
939   audio_out_ = NULL;
940 }
941
942 int
943 fhandler_dev_dsp::open (int flags, mode_t mode)
944 {
945   if (cygheap->fdtab.find_archetype (dev ()))
946     {
947       set_errno (EBUSY);
948       return 0;
949     }
950   int err = 0;
951   UINT num_in = 0, num_out = 0;
952   set_flags ((flags & ~O_TEXT) | O_BINARY);
953   // Work out initial sample format & frequency, /dev/dsp defaults
954   audioformat_ = AFMT_U8;
955   audiofreq_ = 8000;
956   audiobits_ = 8;
957   audiochannels_ = 1;
958   switch (flags & O_ACCMODE)
959     {
960     case O_RDWR:
961       if ((num_in = waveInGetNumDevs ()) == 0)
962         err = ENXIO;
963       /* Fall through */
964     case O_WRONLY:
965       if ((num_out = waveOutGetNumDevs ()) == 0)
966         err = ENXIO;
967       break;
968     case O_RDONLY:
969       if ((num_in = waveInGetNumDevs ()) == 0)
970         err = ENXIO;
971       break;
972     default:
973       err = EINVAL;
974     }
975
976   if (!err)
977     {
978       set_open_status ();
979       need_fork_fixup (true);
980       nohandle (true);
981
982       // FIXME: Do this better someday
983       fhandler_dev_dsp *arch = (fhandler_dev_dsp *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this));
984       archetype = arch;
985       *((fhandler_dev_dsp **) cygheap->fdtab.add_archetype ()) = arch;
986       *arch = *this;
987       archetype->usecount = 1;
988     }
989   else
990     set_errno (err);
991
992   debug_printf ("ACCMODE=0x%08x audio_in=%d audio_out=%d, err=%d",
993                 flags & O_ACCMODE, num_in, num_out, err);
994   return !err;
995 }
996
997 #define IS_WRITE() ((get_flags() & O_ACCMODE) != O_RDONLY)
998 #define IS_READ() ((get_flags() & O_ACCMODE) != O_WRONLY)
999
1000 int
1001 fhandler_dev_dsp::write (const void *ptr, size_t len)
1002 {
1003   debug_printf ("ptr=%08x len=%d", ptr, len);
1004   if ((fhandler_dev_dsp *) archetype != this)
1005     return ((fhandler_dev_dsp *)archetype)->write(ptr, len);
1006
1007   int len_s = len;
1008   const char *ptr_s = static_cast <const char *> (ptr);
1009
1010   if (!audio_out_)
1011     if (IS_WRITE ())
1012       {
1013         debug_printf ("Allocating");
1014         if (!(audio_out_ = new Audio_out))
1015           return -1;
1016
1017         /* check for wave file & get parameters & skip header if possible. */
1018
1019         if (audio_out_->parsewav (ptr_s, len_s,
1020                                   audiofreq_, audiobits_, audiochannels_))
1021           debug_printf ("=> ptr_s=%08x len_s=%d", ptr_s, len_s);
1022       }
1023     else
1024       {
1025         set_errno (EBADF); // device was opened for read?
1026         return -1;
1027       }
1028
1029   /* Open audio device properly with callbacks.
1030      Private parameters were set in call to parsewav.
1031      This is a no-op when there are successive writes in the same process */
1032   if (!audio_out_->start ())
1033     {
1034       set_errno (EIO);
1035       return -1;
1036     }
1037
1038   audio_out_->write (ptr_s, len_s);
1039   return len;
1040 }
1041
1042 void __stdcall
1043 fhandler_dev_dsp::read (void *ptr, size_t& len)
1044 {
1045   debug_printf ("ptr=%08x len=%d", ptr, len);
1046   if ((fhandler_dev_dsp *) archetype != this)
1047     return ((fhandler_dev_dsp *)archetype)->read(ptr, len);
1048
1049   if (!audio_in_)
1050     if (IS_READ ())
1051       {
1052         debug_printf ("Allocating");
1053         if (!(audio_in_ = new Audio_in))
1054           {
1055             len = (size_t)-1;
1056             return;
1057           }
1058         audio_in_->setconvert (audioformat_);
1059       }
1060     else
1061       {
1062         len = (size_t)-1;
1063         set_errno (EBADF); // device was opened for write?
1064         return;
1065       }
1066
1067   /* Open audio device properly with callbacks.
1068      This is a noop when there are successive reads in the same process */
1069   if (!audio_in_->start (audiofreq_, audiobits_, audiochannels_))
1070     {
1071       len = (size_t)-1;
1072       set_errno (EIO);
1073       return;
1074     }
1075
1076   audio_in_->read ((char *)ptr, (int&)len);
1077 }
1078
1079 _off64_t
1080 fhandler_dev_dsp::lseek (_off64_t offset, int whence)
1081 {
1082   return 0;
1083 }
1084
1085 void
1086 fhandler_dev_dsp::close_audio_in ()
1087 {
1088   if (audio_in_)
1089     {
1090       audio_in_->stop ();
1091       delete audio_in_;
1092       audio_in_ = NULL;
1093     }
1094 }
1095
1096 void
1097 fhandler_dev_dsp::close_audio_out (bool immediately)
1098 {
1099   if (audio_out_)
1100     {
1101       audio_out_->stop (immediately);
1102       delete audio_out_;
1103       audio_out_ = NULL;
1104     }
1105 }
1106
1107 int
1108 fhandler_dev_dsp::close ()
1109 {
1110   debug_printf ("audio_in=%08x audio_out=%08x",
1111                 (int)audio_in_, (int)audio_out_);
1112   if (!hExeced)
1113     {
1114       if ((fhandler_dev_dsp *) archetype != this)
1115         return ((fhandler_dev_dsp *) archetype)->close ();
1116
1117       if (--usecount == 0)
1118         {
1119           close_audio_in ();
1120           close_audio_out (exit_state != ES_NOT_EXITING);
1121         }
1122     }
1123   return 0;
1124 }
1125
1126 int
1127 fhandler_dev_dsp::dup (fhandler_base * child)
1128 {
1129   debug_printf ("");
1130   child->archetype = archetype;
1131   child->set_flags (get_flags ());
1132   archetype->usecount++;
1133   return 0;
1134 }
1135
1136 int
1137 fhandler_dev_dsp::ioctl (unsigned int cmd, void *ptr)
1138 {
1139   debug_printf ("audio_in=%08x audio_out=%08x",
1140                 (int)audio_in_, (int)audio_out_);
1141   if ((fhandler_dev_dsp *) archetype != this)
1142     return ((fhandler_dev_dsp *)archetype)->ioctl(cmd, ptr);
1143
1144   int *intptr = (int *) ptr;
1145   switch (cmd)
1146     {
1147 #define CASE(a) case a : debug_printf ("/dev/dsp: ioctl %s", #a);
1148
1149       CASE (SNDCTL_DSP_RESET)
1150         close_audio_in ();
1151         close_audio_out (true);
1152         return 0;
1153         break;
1154
1155       CASE (SNDCTL_DSP_GETBLKSIZE)
1156         /* This is valid even if audio_X is NULL */
1157         if (IS_WRITE ())
1158           {
1159             *intptr = audio_out_->blockSize (audiofreq_,
1160                                              audiobits_,
1161                                              audiochannels_);
1162           }
1163         else
1164           { // I am very sure that IS_READ is valid
1165             *intptr = audio_in_->blockSize (audiofreq_,
1166                                             audiobits_,
1167                                             audiochannels_);
1168           }
1169         return 0;
1170
1171       CASE (SNDCTL_DSP_SETFMT)
1172       {
1173         int nBits;
1174         switch (*intptr)
1175           {
1176           case AFMT_QUERY:
1177             *intptr = audioformat_;
1178             return 0;
1179             break;
1180           case AFMT_U16_BE:
1181           case AFMT_U16_LE:
1182           case AFMT_S16_BE:
1183           case AFMT_S16_LE:
1184             nBits = 16;
1185             break;
1186           case AFMT_U8:
1187           case AFMT_S8:
1188             nBits = 8;
1189             break;
1190           default:
1191             nBits = 0;
1192           }
1193         if (nBits && IS_WRITE ())
1194           {
1195             close_audio_out ();
1196             if (audio_out_->query (audiofreq_, nBits, audiochannels_))
1197               {
1198                 audiobits_ = nBits;
1199                 audioformat_ = *intptr;
1200               }
1201             else
1202               {
1203                 *intptr = audiobits_;
1204                 return -1;
1205               }
1206           }
1207         if (nBits && IS_READ ())
1208           {
1209             close_audio_in ();
1210             if (audio_in_->query (audiofreq_, nBits, audiochannels_))
1211               {
1212                 audiobits_ = nBits;
1213                 audioformat_ = *intptr;
1214               }
1215             else
1216               {
1217                 *intptr = audiobits_;
1218                 return -1;
1219               }
1220           }
1221         return 0;
1222       }
1223
1224       CASE (SNDCTL_DSP_SPEED)
1225         if (IS_WRITE ())
1226           {
1227             close_audio_out ();
1228             if (audio_out_->query (*intptr, audiobits_, audiochannels_))
1229               audiofreq_ = *intptr;
1230             else
1231               {
1232                 *intptr = audiofreq_;
1233                 return -1;
1234               }
1235           }
1236         if (IS_READ ())
1237           {
1238             close_audio_in ();
1239             if (audio_in_->query (*intptr, audiobits_, audiochannels_))
1240               audiofreq_ = *intptr;
1241             else
1242               {
1243                 *intptr = audiofreq_;
1244                 return -1;
1245               }
1246           }
1247         return 0;
1248
1249       CASE (SNDCTL_DSP_STEREO)
1250       {
1251         int nChannels = *intptr + 1;
1252         int res = ioctl (SNDCTL_DSP_CHANNELS, &nChannels);
1253         *intptr = nChannels - 1;
1254         return res;
1255       }
1256
1257       CASE (SNDCTL_DSP_CHANNELS)
1258       {
1259         int nChannels = *intptr;
1260
1261         if (IS_WRITE ())
1262           {
1263             close_audio_out ();
1264             if (audio_out_->query (audiofreq_, audiobits_, nChannels))
1265               audiochannels_ = nChannels;
1266             else
1267               {
1268                 *intptr = audiochannels_;
1269                 return -1;
1270               }
1271           }
1272         if (IS_READ ())
1273           {
1274             close_audio_in ();
1275             if (audio_in_->query (audiofreq_, audiobits_, nChannels))
1276               audiochannels_ = nChannels;
1277             else
1278               {
1279                 *intptr = audiochannels_;
1280                 return -1;
1281               }
1282           }
1283         return 0;
1284       }
1285
1286       CASE (SNDCTL_DSP_GETOSPACE)
1287       {
1288         if (!IS_WRITE ())
1289           {
1290             set_errno(EBADF);
1291             return -1;
1292           }
1293         audio_buf_info *p = (audio_buf_info *) ptr;
1294         audio_out_->buf_info (p, audiofreq_, audiobits_, audiochannels_);
1295         debug_printf ("ptr=%p frags=%d fragsize=%d bytes=%d",
1296                       ptr, p->fragments, p->fragsize, p->bytes);
1297         return 0;
1298       }
1299
1300       CASE (SNDCTL_DSP_GETISPACE)
1301       {
1302         if (!IS_READ ())
1303           {
1304             set_errno(EBADF);
1305             return -1;
1306           }
1307         audio_buf_info *p = (audio_buf_info *) ptr;
1308         audio_in_->buf_info (p, audiofreq_, audiobits_, audiochannels_);
1309         debug_printf ("ptr=%p frags=%d fragsize=%d bytes=%d",
1310                       ptr, p->fragments, p->fragsize, p->bytes);
1311         return 0;
1312       }
1313
1314       CASE (SNDCTL_DSP_SETFRAGMENT)
1315         // Fake!! esound & mikmod require this on non PowerPC platforms.
1316         //
1317         return 0;
1318
1319       CASE (SNDCTL_DSP_GETFMTS)
1320         *intptr = AFMT_S16_LE | AFMT_U8; // only native formats returned here
1321         return 0;
1322
1323       CASE (SNDCTL_DSP_GETCAPS)
1324         *intptr = DSP_CAP_BATCH | DSP_CAP_DUPLEX;
1325         return 0;
1326
1327       CASE (SNDCTL_DSP_POST)
1328       CASE (SNDCTL_DSP_SYNC)
1329         // Stop audio out device
1330         close_audio_out ();
1331         // Stop audio in device
1332         close_audio_in ();
1333         return 0;
1334
1335     default:
1336       debug_printf ("/dev/dsp: ioctl 0x%08x not handled yet! FIXME:", cmd);
1337       break;
1338
1339 #undef CASE
1340     };
1341   set_errno (EINVAL);
1342   return -1;
1343 }
1344
1345 void
1346 fhandler_dev_dsp::fixup_after_fork (HANDLE parent)
1347 { // called from new child process
1348   debug_printf ("audio_in=%08x audio_out=%08x",
1349                 (int)audio_in_, (int)audio_out_);
1350   if (archetype != this)
1351     return ((fhandler_dev_dsp *)archetype)->fixup_after_fork (parent);
1352
1353   if (audio_in_)
1354     audio_in_ ->fork_fixup (parent);
1355   if (audio_out_)
1356     audio_out_->fork_fixup (parent);
1357 }
1358
1359 void
1360 fhandler_dev_dsp::fixup_after_exec ()
1361 {
1362   debug_printf ("audio_in=%08x audio_out=%08x, close_on_exec %d",
1363                 (int) audio_in_, (int) audio_out_, close_on_exec ());
1364   if (!close_on_exec ())
1365     {
1366       if (archetype != this)
1367         return ((fhandler_dev_dsp *) archetype)->fixup_after_exec ();
1368
1369       audio_in_ = NULL;
1370       audio_out_ = NULL;
1371     }
1372 }