OSDN Git Service

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