Implement A->W call for GetNamedSecurityInfo.
[wine] / dlls / winmm / winejack / audio.c
1 /* -*- tab-width: 8; c-basic-offset: 2 -*- */
2 /*
3  * Wine Driver for jack Sound Server
4  *   http://jackit.sourceforge.net
5  *
6  * Copyright 1994 Martin Ayotte
7  * Copyright 1999 Eric Pouech (async playing in waveOut/waveIn)
8  * Copyright 2000 Eric Pouech (loops in waveOut)
9  * Copyright 2002 Chris Morgan (jack version of this file)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 /*
27  * TODO:
28  *  implement audio stream resampling for any arbitrary frequenty
29  *    right now we use the winmm layer to do resampling although it would 
30  *    be nice to have a full set of algorithms to choose from based on cpu 
31  *    time
32  *
33  * FIXME:
34  *  pause in waveOut during loop is not handled correctly
35  */
36
37 #include "config.h"
38
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <string.h>
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46 #include <fcntl.h>
47 #include "windef.h"
48 #include "winbase.h"
49 #include "wingdi.h"
50 #include "winerror.h"
51 #include "wine/winuser16.h"
52 #include "mmddk.h"
53 #include "dsound.h"
54 #include "dsdriver.h"
55 #include "jack.h"
56 #include "wine/debug.h"
57
58 #ifdef HAVE_JACK_JACK_H
59 #include <jack/jack.h>
60 #endif
61
62
63 WINE_DEFAULT_DEBUG_CHANNEL(wave);
64
65 #ifdef HAVE_JACK_JACK_H
66
67 #define MAKE_FUNCPTR(f) static typeof(f) * fp_##f = NULL;
68
69 /* Function pointers for dynamic loading of libjack */
70 /* these are prefixed with "fp_", ie. "fp_jack_client_new" */
71 MAKE_FUNCPTR(jack_activate);
72 MAKE_FUNCPTR(jack_connect);
73 MAKE_FUNCPTR(jack_client_new);
74 MAKE_FUNCPTR(jack_client_close);
75 MAKE_FUNCPTR(jack_deactivate);
76 MAKE_FUNCPTR(jack_set_process_callback);
77 MAKE_FUNCPTR(jack_set_buffer_size_callback);
78 MAKE_FUNCPTR(jack_set_sample_rate_callback);
79 MAKE_FUNCPTR(jack_on_shutdown);
80 MAKE_FUNCPTR(jack_get_sample_rate);
81 MAKE_FUNCPTR(jack_port_register);
82 MAKE_FUNCPTR(jack_port_get_buffer);
83 MAKE_FUNCPTR(jack_get_ports);
84 MAKE_FUNCPTR(jack_port_name);
85 MAKE_FUNCPTR(jack_get_buffer_size);
86 #undef MAKE_FUNCPTR
87
88 /* define the below to work around a bug in jack where closing a port */
89 /* takes a very long time, so to get around this we actually don't */
90 /* close the port when the device is closed but instead mark the */
91 /* corresponding device as unused */
92 #define JACK_CLOSE_HACK    1
93
94 typedef jack_default_audio_sample_t sample_t;
95 typedef jack_nframes_t nframes_t;
96
97 /* only allow 10 output devices through this driver, this ought to be adequate */
98 #define MAX_WAVEOUTDRV  (10)
99 #define MAX_WAVEINDRV   (10)
100
101 /* state diagram for waveOut writing:
102  *
103  * +---------+-------------+---------------+---------------------------------+
104  * |  state  |  function   |     event     |            new state            |
105  * +---------+-------------+---------------+---------------------------------+
106  * |         | open()      |               | STOPPED                         |
107  * | PAUSED  | write()     |               | PAUSED                          |
108  * | STOPPED | write()     | <thrd create> | PLAYING                         |
109  * | PLAYING | write()     | HEADER        | PLAYING                         |
110  * | (other) | write()     | <error>       |                                 |
111  * | (any)   | pause()     | PAUSING       | PAUSED                          |
112  * | PAUSED  | restart()   | RESTARTING    | PLAYING (if no thrd => STOPPED) |
113  * | (any)   | reset()     | RESETTING     | STOPPED                         |
114  * | (any)   | close()     | CLOSING       | CLOSED                          |
115  * +---------+-------------+---------------+---------------------------------+
116  */
117
118 /* states of the playing device */
119 #define WINE_WS_PLAYING   0
120 #define WINE_WS_PAUSED    1
121 #define WINE_WS_STOPPED   2
122 #define WINE_WS_CLOSED    3
123
124 typedef struct {
125     volatile int      state;      /* one of the WINE_WS_ manifest constants */
126     WAVEOPENDESC      waveDesc;
127     WORD              wFlags;
128     PCMWAVEFORMAT     format;
129     WAVEOUTCAPSA      caps;
130     WORD              wDevID;
131     char              interface_name[32];
132
133     jack_port_t*      out_port_l;   /* ports for left and right channels */
134     jack_port_t*      out_port_r;
135     jack_client_t*    client;
136     long              sample_rate;        /* jack server sample rate */
137
138 #if JACK_CLOSE_HACK
139     BOOL              in_use; /* TRUE if this device is in use */
140 #endif
141
142     char*             sound_buffer;
143     unsigned long     buffer_size;
144
145     DWORD             volume_left;
146     DWORD             volume_right;
147
148     LPWAVEHDR         lpQueuePtr;   /* start of queued WAVEHDRs (waiting to be notified) */
149     LPWAVEHDR         lpPlayPtr;    /* start of not yet fully played buffers */
150     DWORD             dwPartialOffset;  /* Offset of not yet written bytes in lpPlayPtr */
151
152     LPWAVEHDR         lpLoopPtr;    /* pointer of first buffer in loop, if any */
153     DWORD             dwLoops;      /* private copy of loop counter */
154     
155     DWORD             dwPlayedTotal;    /* number of bytes actually played since opening */
156     DWORD             dwWrittenTotal;   /* number of bytes written to jack since opening */
157
158     DWORD             bytesInJack; /* bytes that we wrote during the previous JACK_Callback() */
159     DWORD             tickCountMS; /* time in MS of last JACK_Callback() */
160
161     /* synchronization stuff */
162     CRITICAL_SECTION    access_crst;
163 } WINE_WAVEOUT;
164
165 typedef struct {
166     volatile int    state;
167     WAVEOPENDESC    waveDesc;
168     WORD            wFlags;
169     PCMWAVEFORMAT   format;
170     LPWAVEHDR       lpQueuePtr;
171     DWORD           dwTotalRecorded;
172     WAVEINCAPSA     caps;
173     BOOL            bTriggerSupport;
174     WORD              wDevID;
175     char              interface_name[32];
176
177     jack_port_t*      in_port_l;   /* ports for left and right channels */
178     jack_port_t*      in_port_r;
179     jack_client_t*    client;
180     long              sample_rate;        /* jack server sample rate */
181
182 #if JACK_CLOSE_HACK
183     BOOL              in_use; /* TRUE if this device is in use */
184 #endif
185
186     char*             sound_buffer;
187     unsigned long     buffer_size;
188
189     /* synchronization stuff */
190     CRITICAL_SECTION    access_crst;
191 } WINE_WAVEIN;
192
193 static WINE_WAVEOUT WOutDev   [MAX_WAVEOUTDRV];
194 static WINE_WAVEIN  WInDev    [MAX_WAVEINDRV ];
195
196 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
197 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
198 static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid);
199
200 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo);
201 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force);
202
203 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo);
204 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels);
205
206 #if JACK_CLOSE_HACK
207 static void     JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client);
208 #else
209 static void     JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo);
210 #endif
211
212 #if JACK_CLOSE_HACK
213 static void     JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client);
214 #else
215 static void     JACK_CloseWaveInDevice(WINE_WAVEIN* wwi);
216 #endif
217
218 static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
219                              PCMWAVEFORMAT* format)
220 {
221     TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
222           lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
223           format->wf.nChannels, format->wf.nAvgBytesPerSec);
224     TRACE("Position in bytes=%lu\n", position);
225
226     switch (lpTime->wType) {
227     case TIME_SAMPLES:
228         lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
229         TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
230         break;
231     case TIME_MS:
232         lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
233         TRACE("TIME_MS=%lu\n", lpTime->u.ms);
234         break;
235     case TIME_SMPTE:
236         position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
237         lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
238         position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
239         lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
240         lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
241         lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
242         lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
243         lpTime->u.smpte.fps = 30;
244         lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
245         position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
246         if (position != 0)
247         {
248             /* Round up */
249             lpTime->u.smpte.frame++;
250         }
251         TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
252               lpTime->u.smpte.hour, lpTime->u.smpte.min,
253               lpTime->u.smpte.sec, lpTime->u.smpte.frame);
254         break;
255     default:
256         FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
257         lpTime->wType = TIME_BYTES;
258         /* fall through */
259     case TIME_BYTES:
260         lpTime->u.cb = position;
261         TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
262         break;
263     }
264     return MMSYSERR_NOERROR;
265 }
266
267
268 /*======================================================================*
269  *                  Low level WAVE implementation                       *
270  *======================================================================*/
271
272 #define SAMPLE_MAX_16BIT  32767.0f
273
274 /* Alsaplayer function that applies volume changes to a buffer */
275 /* (C) Andy Lo A Foe */
276 /* Length is in terms of 32 bit samples */
277 void volume_effect32(void *buffer, int length, int left, int right)
278 {
279         short *data = (short *)buffer;
280         int i, v;
281     
282         if (right == -1) right = left;
283  
284         for(i = 0; i < length; i++) {
285                 v = (int) ((*(data) * left) / 100);
286                 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
287                 v = (int) ((*(data) * right) / 100);
288                 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
289         }
290 }
291
292 /* move 16 bit mono/stereo to 16 bit stereo */
293 void sample_move_d16_d16(short *dst, short *src,
294                   unsigned long nsamples, int nChannels)
295 {
296   while(nsamples--)
297   {
298     *dst = *src;
299     dst++;
300
301     if(nChannels == 2) src++;
302
303     *dst = *src;
304     dst++;
305
306     src++;
307   }
308 }
309
310 /* convert from 16 bit to floating point */
311 /* allow for copying of stereo data with alternating left/right */
312 /* channels to a buffer that will hold a single channel stream */
313 /* nsamples is in terms of 16bit samples */
314 /* src_skip is in terms of 16bit samples */
315 void sample_move_d16_s16 (sample_t *dst, short *src,
316                         unsigned long nsamples, unsigned long src_skip)
317 {
318   /* ALERT: signed sign-extension portability !!! */
319   while (nsamples--)
320   {
321     *dst = (*src) / SAMPLE_MAX_16BIT;
322     dst++;
323     src += src_skip;
324   }
325 }       
326
327 /* convert from floating point to 16 bit */
328 /* allow for copying of a buffer that will hold a single channel stream */
329 /* to stereo data with alternating left/right channels */
330 /* nsamples is in terms of float samples */
331 /* dst_skip is in terms of 16bit samples */
332 void sample_move_s16_d16 (short *dst, sample_t *src,
333                         unsigned long nsamples, unsigned long dst_skip)
334 {
335   /* ALERT: signed sign-extension portability !!! */
336   while (nsamples--)
337   {
338       *dst = (*src) * SAMPLE_MAX_16BIT;
339 /*      TRACE("src=(%.8f,%p) dst=(%d,%p)\n",*src,src,*dst,dst); */
340       dst += dst_skip;
341       src++;
342   }
343 }       
344
345
346 /* fill dst buffer with nsamples worth of silence */
347 void sample_silence_dS (sample_t *dst, unsigned long nsamples)
348 {
349   /* ALERT: signed sign-extension portability !!! */
350   while (nsamples--)
351   {
352     *dst = 0;
353     dst++;
354   }
355 }       
356
357 /******************************************************************
358  *    JACK_callback_wwo
359  */
360 /* everytime the jack server wants something from us it calls this 
361 function, so we either deliver it some sound to play or deliver it nothing 
362 to play */
363 int JACK_callback_wwo (nframes_t nframes, void *arg)
364 {
365   sample_t* out_l;
366   sample_t* out_r;
367   WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
368
369   TRACE("wDevID: %u, nframes %u state=%u\n", wwo->wDevID, nframes,wwo->state);
370
371   if(!wwo->client)
372     ERR("client is closed, this is weird...\n");
373     
374   out_l = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_l, nframes);
375   out_r = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_r, nframes);
376
377   if(wwo->state == WINE_WS_PLAYING)
378   {
379     DWORD jackFramesAvailable = nframes;
380     DWORD outputFramesAvailable;
381     DWORD numFramesToWrite;
382
383     long written = 0;
384     char* buffer;
385
386 #if JACK_CLOSE_HACK
387     if(wwo->in_use == FALSE)
388     {
389       /* output silence if nothing is being outputted */
390       sample_silence_dS(out_l, nframes);
391       sample_silence_dS(out_r, nframes);
392
393       return 0;
394     }
395 #endif
396
397     TRACE("wwo.state == WINE_WS_PLAYING\n");
398
399     /* see if our sound_buffer is large enough to hold the number of frames jack requested */
400     /* Note: sound_buffer is always filled with 16-bit stereo data, even for mono mode */
401     if(wwo->buffer_size < (nframes * sizeof(short) * 2))
402     {
403       ERR("for some reason JACK_BufSize() didn't allocate enough memory\n");
404       ERR("allocated %ld bytes, need %d bytes\n", wwo->buffer_size, (nframes * sizeof(short) * 2));
405       return 0;
406     }
407
408     /* while we have jackFramesAvailable and a wave header to be played */
409     while(jackFramesAvailable && wwo->lpPlayPtr)
410     {
411       /* find the amount of audio to be played at this time */
412       outputFramesAvailable = (wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset) / wwo->format.wf.nBlockAlign;
413
414       numFramesToWrite = min(jackFramesAvailable, outputFramesAvailable);
415       TRACE("dwBufferLength=(%ld) dwPartialOffset=(%ld)\n",wwo->lpPlayPtr->dwBufferLength,wwo->dwPartialOffset);
416       TRACE("outputFramesAvailable == %ld, jackFramesAvailable == %ld\n", outputFramesAvailable, jackFramesAvailable);
417
418       buffer = wwo->lpPlayPtr->lpData + wwo->dwPartialOffset;
419
420       /* convert from mono to stereo if necessary */
421       /* otherwise just memcpy to the output buffer */
422
423       if(wwo->format.wf.nChannels == 1)
424       {
425         sample_move_d16_d16((short*)wwo->sound_buffer + ((nframes - jackFramesAvailable) * sizeof(short)),
426                             (short*)buffer, numFramesToWrite, wwo->format.wf.nChannels);
427       } else /* just copy the memory over */
428       {
429         memcpy(wwo->sound_buffer + ((nframes - jackFramesAvailable) * wwo->format.wf.nBlockAlign),
430                buffer, numFramesToWrite * wwo->format.wf.nBlockAlign);
431       }
432
433       /* advance to the next wave header if possible, or advance pointer */
434       /* inside of the current header if we haven't completed it */
435       if(numFramesToWrite == outputFramesAvailable)
436       {
437         wodHelper_PlayPtrNext(wwo);            /* we wrote the whole waveheader, skip to the next one*/
438       }
439       else
440       {
441         wwo->dwPartialOffset+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* else advance by the bytes we took in to write */
442       }
443
444       written+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* add on what we wrote */
445       jackFramesAvailable-=numFramesToWrite; /* take away what was written in terms of output bytes */
446     }
447
448     wwo->tickCountMS = GetTickCount();    /* record the current time */
449     wwo->dwWrittenTotal+=written; /* update states on wave device */
450     wwo->dwPlayedTotal+=wwo->bytesInJack; /* we must have finished with the last bytes or we wouldn't be back inside of this callback again... */
451     wwo->bytesInJack = written; /* record the bytes inside of jack */
452
453     /* Now that we have finished filling the buffer either until it is full or until */
454     /* we have run out of application sound data to process, apply volume and output */
455     /* the audio to the jack server */
456
457     /* apply volume to the buffer */
458     volume_effect32(wwo->sound_buffer, (nframes - jackFramesAvailable), wwo->volume_left, wwo->volume_right);
459
460     /* convert from stereo 16 bit to single channel 32 bit float */
461     /* for each jack server channel */
462     /* NOTE: we skip over two sample since we want to only get either the left or right channel */
463     sample_move_d16_s16(out_l, (short*)wwo->sound_buffer,     (nframes - jackFramesAvailable), 2);
464     sample_move_d16_s16(out_r, (short*)wwo->sound_buffer + 1, (nframes - jackFramesAvailable), 2);
465
466     /* see if we still have jackBytesLeft here, if we do that means that we
467     ran out of wave data to play and had a buffer underrun, fill in
468     the rest of the space with zero bytes */
469     if(jackFramesAvailable)
470     {
471       ERR("buffer underrun of %ld frames\n", jackFramesAvailable);
472       sample_silence_dS(out_l + (nframes - jackFramesAvailable), jackFramesAvailable);
473       sample_silence_dS(out_r + (nframes - jackFramesAvailable), jackFramesAvailable);
474     }
475   }
476   else if(wwo->state == WINE_WS_PAUSED || 
477     wwo->state == WINE_WS_STOPPED ||
478     wwo->state == WINE_WS_CLOSED)
479   {
480       /* output silence if nothing is being outputted */
481       sample_silence_dS(out_l, nframes);
482       sample_silence_dS(out_r, nframes);
483   }
484
485   /* notify the client of completed wave headers */
486   EnterCriticalSection(&wwo->access_crst);
487   wodHelper_NotifyCompletions(wwo, FALSE);
488   LeaveCriticalSection(&wwo->access_crst);
489
490   return 0;
491 }
492
493 /******************************************************************
494  *              JACK_bufsize_wwo
495  *
496  *              Called whenever the jack server changes the the max number 
497  *              of frames passed to JACK_callback
498  */
499 int JACK_bufsize_wwo (nframes_t nframes, void *arg)
500 {
501   WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
502   DWORD buffer_required;
503   TRACE("wDevID=%d\n",wwo->wDevID);
504   TRACE("the maximum buffer size is now %u frames\n", nframes);
505
506   /* make sure the callback routine has adequate memory */
507     /* see if our buffer is large enough for the data we are writing */
508     /* ie. Buffer_size < (bytes we already wrote + bytes we are going to write in this loop) */
509   EnterCriticalSection(&wwo->access_crst);
510
511   /* wwo->sound_buffer is always filled with 16-bit stereo data, even for mono streams */
512   buffer_required = nframes * sizeof(short) * 2;
513   TRACE("wwo->buffer_size (%ld) buffer_required (%ld).\n", wwo->buffer_size,buffer_required);
514   if(wwo->buffer_size < buffer_required)
515   {
516     TRACE("expanding buffer from wwo->buffer_size == %ld, to %ld\n", 
517       wwo->buffer_size, buffer_required);
518     TRACE("GetProcessHeap() == %p\n", GetProcessHeap());
519     wwo->buffer_size = buffer_required;
520
521     if (wwo->sound_buffer)
522       wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, wwo->buffer_size);
523     else
524       wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, wwo->buffer_size);
525
526     /* if we don't have a buffer then error out */
527     if(!wwo->sound_buffer)
528     {
529         ERR("error allocating sound_buffer memory\n");
530         LeaveCriticalSection(&wwo->access_crst);
531         return 0;
532     }
533   }
534
535   LeaveCriticalSection(&wwo->access_crst);
536
537   TRACE("ending\n");
538
539   return 0;
540 }
541 /******************************************************************
542  *              JACK_bufsize_wwi
543  *
544  *              Called whenever the jack server changes the the max number 
545  *              of frames passed to JACK_callback
546  */
547 int JACK_bufsize_wwi (nframes_t nframes, void *arg)
548 {
549   TRACE("the maximum buffer size is now %u frames\n", nframes);
550   return 0;
551 }
552
553 /******************************************************************
554  *              JACK_srate
555  */
556 int JACK_srate (nframes_t nframes, void *arg)
557 {
558   TRACE("the sample rate is now %u/sec\n", nframes);
559   return 0;
560 }
561
562
563 /******************************************************************
564  *              JACK_shutdown_wwo
565  */
566 /* if this is called then jack shut down... handle this appropriately */
567 void JACK_shutdown_wwo(void* arg)
568 {
569   WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
570
571   wwo->client = 0; /* reset client */
572
573   TRACE("trying to reconnect after sleeping for a short while...\n");
574   
575   /* lets see if we can't reestablish the connection */
576   Sleep(750); /* pause for a short period of time */
577   if(!JACK_OpenWaveOutDevice(wwo))
578   {
579     ERR("unable to reconnect with jack...\n");
580   }
581 }
582
583 /******************************************************************
584  *              JACK_shutdown_wwi
585  */
586 /* if this is called then jack shut down... handle this appropriately */
587 void JACK_shutdown_wwi(void* arg)
588 {
589   WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
590
591   wwi->client = 0; /* reset client */
592
593   TRACE("trying to reconnect after sleeping for a short while...\n");
594   
595   /* lets see if we can't reestablish the connection */
596   Sleep(750); /* pause for a short period of time */
597   if(!JACK_OpenWaveInDevice(wwi,wwi->format.wf.nChannels))
598   {
599     ERR("unable to reconnect with jack...\n");
600   }
601 }
602
603
604 /******************************************************************
605  *              JACK_OpenWaveOutDevice
606  */
607 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo)
608 {
609   const char** ports;
610   int i;
611   char client_name[64];
612   jack_port_t* out_port_l;
613   jack_port_t* out_port_r;
614   jack_client_t* client;
615   int failed = 0;
616
617   TRACE("creating jack client and setting up callbacks\n");
618
619 #if JACK_CLOSE_HACK
620   /* see if this device is already open */
621         if(wwo->client)
622         {
623           /* if this device is already in use then it is bad for us to be in here */
624           if(wwo->in_use)
625             return 0;
626
627           TRACE("using existing client\n");
628           wwo->in_use = TRUE;
629           return 1;
630         }
631 #endif
632
633         /* zero out the buffer pointer and the size of the buffer */
634         wwo->sound_buffer = 0;
635         wwo->buffer_size = 0;
636
637         /* try to become a client of the JACK server */
638         snprintf(client_name, sizeof(client_name), "wine_jack_out_%d", wwo->wDevID);
639         TRACE("client name '%s'\n", client_name);
640         if ((client = fp_jack_client_new (client_name)) == 0)
641         {
642                 /* jack has problems with shutting down clients, so lets */
643                 /* wait a short while and try once more before we give up */
644                 Sleep(250);
645                 if ((client = fp_jack_client_new (client_name)) == 0)
646                 {
647                   ERR("jack server not running?\n");
648                   return 0;
649                 }
650         }
651                         
652         /* tell the JACK server to call `JACK_callback_wwo()' whenever
653            there is work to be done. */
654         fp_jack_set_process_callback (client, JACK_callback_wwo, wwo);
655         
656         /* tell the JACK server to call `JACK_bufsize_wwo()' whenever   
657            the maximum number of frames that will be passed
658            to `JACK_Callback()' changes */
659         fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwo, wwo);
660
661         /* tell the JACK server to call `srate()' whenever
662            the sample rate of the system changes. */
663         fp_jack_set_sample_rate_callback (client, JACK_srate, wwo);
664
665         /* tell the JACK server to call `jack_shutdown()' if
666            it ever shuts down, either entirely, or if it
667            just decides to stop calling us. */
668         fp_jack_on_shutdown (client, JACK_shutdown_wwo, wwo);
669         
670         /* display the current sample rate. once the client is activated
671            (see below), you should rely on your own sample rate
672            callback (see above) for this value. */
673         wwo->sample_rate = fp_jack_get_sample_rate(client);
674         TRACE("engine sample rate: %lu\n", wwo->sample_rate);
675           
676         /* create the left and right channel output ports */
677         /* jack's ports are all mono so for stereo you need two */
678         out_port_l = fp_jack_port_register (client, "out_l",
679                          JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
680
681         out_port_r = fp_jack_port_register (client, "out_r",
682                          JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
683
684         TRACE("Created ports. (%p) (%p)\n",out_port_l, out_port_r);
685
686         /* save away important values to the WINE_WAVEOUT struct */
687         wwo->client = client;
688         wwo->out_port_l = out_port_l;
689         wwo->out_port_r = out_port_r;
690
691 #if JACK_CLOSE_HACK
692         wwo->in_use = TRUE; /* mark this device as in use since it now is ;-) */
693 #endif
694
695         /* set initial buffer size */
696         JACK_bufsize_wwo (fp_jack_get_buffer_size(client),wwo);
697
698         /* tell the JACK server that we are ready to roll */
699         if (fp_jack_activate (client))
700         {
701           ERR( "cannot activate client\n");
702           return 0;
703         }
704
705         TRACE("jack activate.\n");
706         /* figure out what the ports that we want to output on are */
707         /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
708         /*   this way works if names are changed */
709         ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
710
711         /* display a trace of the output ports we found */
712         for(i = 0; ports[i]; i++)
713         {
714           TRACE("ports[%d] = '%s'\n", i, ports[i]);
715         }
716
717         if(!ports)
718         {
719           ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsInput'\n");
720         }
721
722         /* connect the ports. Note: you can't do this before
723            the client is activated (this may change in the future).
724         */ 
725         /* we want to connect to two ports so we have stereo output ;-) */
726
727         if(fp_jack_connect(client, fp_jack_port_name(out_port_l), ports[0]))
728         {
729           ERR ("cannot connect to output port %d('%s')\n", 0, ports[0]);
730           failed = 1;
731         }
732
733         if(fp_jack_connect(client, fp_jack_port_name(out_port_r), ports[1]))
734         {
735           ERR ("cannot connect to output port %d('%s')\n", 1, ports[1]);
736           failed = 1;
737         }
738
739         free(ports); /* free the returned array of ports */
740
741         /* if something failed we need to shut the client down and return 0 */
742         if(failed)
743         {
744 #if JACK_CLOSE_HACK
745           JACK_CloseWaveOutDevice(wwo, TRUE);
746 #else
747           JACK_CloseWaveOutDevice(wwo);
748 #endif
749           return 0;
750         }
751
752         return 1; /* return success */
753 }
754
755 /******************************************************************
756  *              JACK_CloseWaveOutDevice
757  *
758  *      Close the connection to the server cleanly.
759  *  If close_client is TRUE we close the client for this device instead of
760  *    just marking the device as in_use(JACK_CLOSE_HACK only)
761  */
762 #if JACK_CLOSE_HACK
763 static void     JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client)
764 #else
765 static void     JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
766 #endif
767 {
768 #if JACK_CLOSE_HACK
769   TRACE("wDevID: %d, close_client (wwo): %d\n", wwo->wDevID, close_client);
770 #else
771   TRACE("wDevID: %d\n", wwo->wDevID);
772 #endif
773
774 #if JACK_CLOSE_HACK
775   if(close_client)
776   {
777 #endif
778     fp_jack_deactivate(wwo->client); /* supposed to help the jack_client_close() to succeed */
779     fp_jack_client_close (wwo->client);
780
781     EnterCriticalSection(&wwo->access_crst);
782     wwo->client = 0; /* reset client */
783     HeapFree(GetProcessHeap(), 0, wwo->sound_buffer); /* free buffer memory */
784     wwo->sound_buffer = 0;
785     wwo->buffer_size = 0; /* zero out size of the buffer */
786     LeaveCriticalSection(&wwo->access_crst);
787 #if JACK_CLOSE_HACK
788   } else
789   {
790     EnterCriticalSection(&wwo->access_crst);
791     TRACE("setting in_use to FALSE\n");
792     wwo->in_use = FALSE;
793     LeaveCriticalSection(&wwo->access_crst);
794   }
795 #endif
796 }
797
798 /******************************************************************
799  *              JACK_CloseWaveInDevice
800  *
801  *      Close the connection to the server cleanly.
802  *  If close_client is TRUE we close the client for this device instead of
803  *    just marking the device as in_use(JACK_CLOSE_HACK only)
804  */
805 #if JACK_CLOSE_HACK
806 static void     JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client)
807 #else
808 static void     JACK_CloseWaveInDevice(WINE_WAVEIN* wwi)
809 #endif
810 {
811 #if JACK_CLOSE_HACK
812   TRACE("wDevID: %d, close_client (wwi): %d\n", wwi->wDevID, close_client);
813 #else
814   TRACE("wDevID: %d\n", wwi->wDevID);
815 #endif
816
817 #if JACK_CLOSE_HACK
818   if(close_client)
819   {
820 #endif
821     fp_jack_deactivate(wwi->client); /* supposed to help the jack_client_close() to succeed */
822     fp_jack_client_close (wwi->client);
823
824     EnterCriticalSection(&wwi->access_crst);
825     wwi->client = 0; /* reset client */
826     HeapFree(GetProcessHeap(), 0, wwi->sound_buffer); /* free buffer memory */
827     wwi->sound_buffer = 0;
828     wwi->buffer_size = 0; /* zero out size of the buffer */
829     LeaveCriticalSection(&wwi->access_crst);
830 #if JACK_CLOSE_HACK
831   } else
832   {
833     EnterCriticalSection(&wwi->access_crst);
834     TRACE("setting in_use to FALSE\n");
835     wwi->in_use = FALSE;
836     LeaveCriticalSection(&wwi->access_crst);
837   }
838 #endif
839 }
840
841 /******************************************************************
842  *              JACK_WaveRelease
843  *
844  *
845  */
846 LONG    JACK_WaveRelease(void)
847
848   int iDevice;
849
850   TRACE("closing all open waveout devices\n");
851
852   /* close all open output devices */
853   for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
854   {
855     TRACE("iDevice == %d\n", iDevice);
856     if(WOutDev[iDevice].client)
857     {
858 #if JACK_CLOSE_HACK
859       JACK_CloseWaveOutDevice(&WOutDev[iDevice], TRUE); /* close the device, FORCE the client to close */
860 #else
861       JACK_CloseWaveOutDevice(&WOutDev[iDevice]); /* close the device, FORCE the client to close */
862 #endif
863       DeleteCriticalSection(&(WOutDev[iDevice].access_crst)); /* delete the critical section */
864     }
865   }
866
867   TRACE("closing all open wavein devices\n");
868
869   /* close all open input devices */
870   for(iDevice = 0; iDevice < MAX_WAVEINDRV; iDevice++)
871   {
872     TRACE("iDevice == %d\n", iDevice);
873     if(WInDev[iDevice].client)
874     {
875 #if JACK_CLOSE_HACK
876       JACK_CloseWaveInDevice(&WInDev[iDevice], TRUE); /* close the device, FORCE the client to close */
877 #else
878       JACK_CloseWaveInDevice(&WInDev[iDevice]); /* close the device, FORCE the client to close */
879 #endif
880       DeleteCriticalSection(&(WInDev[iDevice].access_crst)); /* delete the critical section */
881     }
882   }
883
884   TRACE("returning 1\n");
885
886   return 1;
887 }
888
889 /******************************************************************
890  *              JACK_WaveInit
891  *
892  * Initialize internal structures from JACK server info
893  */
894 LONG JACK_WaveInit(void)
895 {
896     int i;
897
898     TRACE("called\n");
899
900     /* setup function pointers */
901 #define LOAD_FUNCPTR(f) if((fp_##f = wine_dlsym(jackhandle, #f, NULL, 0)) == NULL) goto sym_not_found;    
902     LOAD_FUNCPTR(jack_activate);
903     LOAD_FUNCPTR(jack_connect);
904     LOAD_FUNCPTR(jack_client_new);
905     LOAD_FUNCPTR(jack_client_close);
906     LOAD_FUNCPTR(jack_deactivate);
907     LOAD_FUNCPTR(jack_set_process_callback);
908     LOAD_FUNCPTR(jack_set_buffer_size_callback);
909     LOAD_FUNCPTR(jack_set_sample_rate_callback);
910     LOAD_FUNCPTR(jack_on_shutdown);
911     LOAD_FUNCPTR(jack_get_sample_rate);
912     LOAD_FUNCPTR(jack_port_register);
913     LOAD_FUNCPTR(jack_port_get_buffer);
914     LOAD_FUNCPTR(jack_get_ports);
915     LOAD_FUNCPTR(jack_port_name);
916     LOAD_FUNCPTR(jack_get_buffer_size);
917 #undef LOAD_FUNCPTR
918
919     /* start with output device */
920
921     for (i = 0; i < MAX_WAVEOUTDRV; ++i)
922     {
923       WOutDev[i].client = 0; /* initialize the client to 0 */
924
925 #if JACK_CLOSE_HACK
926       WOutDev[i].in_use = FALSE;
927       WInDev[i].in_use  = FALSE;
928 #endif
929
930       memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps));
931
932       /* FIXME: some programs compare this string against the content of the registry
933        * for MM drivers. The names have to match in order for the program to work 
934        * (e.g. MS win9x mplayer.exe)
935        */
936 #ifdef EMULATE_SB16
937       WOutDev[i].caps.wMid = 0x0002;
938       WOutDev[i].caps.wPid = 0x0104;
939       strcpy(WOutDev[i].caps.szPname, "SB16 Wave Out");
940 #else
941       WOutDev[i].caps.wMid = 0x00FF;    /* Manufac ID */
942       WOutDev[i].caps.wPid = 0x0001;    /* Product ID */
943       /*    strcpy(WOutDev[i].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/
944       strcpy(WOutDev[i].caps.szPname, "CS4236/37/38");
945 #endif
946
947       snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "winejack: %d", i);
948
949       WOutDev[i].caps.vDriverVersion = 0x0100;
950       WOutDev[i].caps.dwFormats = 0x00000000;
951       WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
952     
953       WOutDev[i].caps.wChannels = 2;
954       WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;
955
956 /* NOTE: we don't support any 8 bit modes so note that */
957 /*      WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
958       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
959       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
960       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
961 /*      WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
962       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
963       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
964       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
965 /*      WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
966       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
967       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
968       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
969     }
970
971     /* then do input device */
972     for (i = 0; i < MAX_WAVEINDRV; ++i)
973     {
974       /* TODO: we should initialize read stuff here */
975       memset(&WInDev[0].caps, 0, sizeof(WInDev[0].caps));
976
977     /* FIXME: some programs compare this string against the content of the registry
978      * for MM drivers. The names have to match in order for the program to work
979      * (e.g. MS win9x mplayer.exe)
980      */
981 #ifdef EMULATE_SB16
982         WInDev[i].caps.wMid = 0x0002;
983         WInDev[i].caps.wPid = 0x0104;
984         strcpy(WInDev[i].caps.szPname, "SB16 Wave In");
985 #else
986         WInDev[i].caps.wMid = 0x00FF;
987         WInDev[i].caps.wPid = 0x0001;
988         strcpy(WInDev[i].caps.szPname,"CS4236/37/38");
989 #endif
990         snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "winejack: %d", i);
991
992         WInDev[i].caps.vDriverVersion = 0x0100;
993
994         WInDev[i].caps.wChannels = 0x2;
995         /* NOTE: we don't support any 8 bit modes so note that */
996 /*      WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
997         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
998         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
999         WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
1000 /*      WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
1001         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
1002         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
1003         WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
1004 /*      WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
1005         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
1006         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
1007         WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
1008         WInDev[i].caps.wReserved1 = 0;
1009     }
1010     
1011     return 1;           /* return success */
1012
1013 /* error path for function pointer loading errors */
1014 sym_not_found:
1015     WINE_MESSAGE(
1016       "Wine cannot find certain functions that it needs inside the jack"
1017       "library.  To enable Wine to use the jack audio server please "
1018       "install libjack\n");
1019     wine_dlclose(jackhandle, NULL, 0);
1020     jackhandle = NULL;
1021     return FALSE;
1022 }
1023
1024 /*======================================================================*
1025  *                  Low level WAVE OUT implementation                   *
1026  *======================================================================*/
1027
1028 /**************************************************************************
1029  *                      wodNotifyClient                 [internal]
1030  */
1031 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1032 {
1033     TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
1034     
1035     switch (wMsg) {
1036     case WOM_OPEN:
1037     case WOM_CLOSE:
1038     case WOM_DONE:
1039       if (wwo->wFlags != DCB_NULL &&
1040         !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags,
1041           (HDRVR)wwo->waveDesc.hWave, wMsg, wwo->waveDesc.dwInstance,
1042           dwParam1, dwParam2))
1043       {
1044         WARN("can't notify client !\n");
1045         return MMSYSERR_ERROR;
1046       }
1047     break;
1048     default:
1049       FIXME("Unknown callback message %u\n", wMsg);
1050         return MMSYSERR_INVALPARAM;
1051     }
1052     return MMSYSERR_NOERROR;
1053 }
1054
1055 /**************************************************************************
1056  *                              wodHelper_BeginWaveHdr          [internal]
1057  *
1058  * Makes the specified lpWaveHdr the currently playing wave header.
1059  * If the specified wave header is a begin loop and we're not already in
1060  * a loop, setup the loop.
1061  */
1062 static void wodHelper_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
1063 {
1064     EnterCriticalSection(&wwo->access_crst);
1065
1066     wwo->lpPlayPtr = lpWaveHdr;
1067
1068     if (!lpWaveHdr)
1069     {
1070        LeaveCriticalSection(&wwo->access_crst);
1071        return;
1072     }
1073
1074     if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)
1075     {
1076       if (wwo->lpLoopPtr)
1077       {
1078         WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1079         TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1080       } else
1081       {
1082         TRACE("Starting loop (%ldx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
1083         wwo->lpLoopPtr = lpWaveHdr;
1084         /* Windows does not touch WAVEHDR.dwLoops,
1085          * so we need to make an internal copy */
1086         wwo->dwLoops = lpWaveHdr->dwLoops;
1087       }
1088     }
1089     wwo->dwPartialOffset = 0;
1090
1091     LeaveCriticalSection(&wwo->access_crst);
1092 }
1093
1094
1095 /**************************************************************************
1096  *                              wodHelper_PlayPtrNext           [internal]
1097  *
1098  * Advance the play pointer to the next waveheader, looping if required.
1099  */
1100 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
1101 {
1102   LPWAVEHDR lpWaveHdr;
1103
1104   EnterCriticalSection(&wwo->access_crst);
1105
1106   lpWaveHdr = wwo->lpPlayPtr;
1107
1108   wwo->dwPartialOffset = 0;
1109   if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr)
1110   {
1111     /* We're at the end of a loop, loop if required */
1112     if (--wwo->dwLoops > 0)
1113     {
1114       wwo->lpPlayPtr = wwo->lpLoopPtr;
1115     } else
1116     {
1117       /* Handle overlapping loops correctly */
1118       if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
1119         FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
1120         /* shall we consider the END flag for the closing loop or for
1121          * the opening one or for both ???
1122          * code assumes for closing loop only
1123          */
1124       } else
1125       {
1126         lpWaveHdr = lpWaveHdr->lpNext;
1127       }
1128       wwo->lpLoopPtr = NULL;
1129       wodHelper_BeginWaveHdr(wwo, lpWaveHdr);
1130     }
1131   } else
1132   {
1133      /* We're not in a loop.  Advance to the next wave header */
1134     TRACE("not inside of a loop, advancing to next wave header\n");
1135     wodHelper_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
1136   }
1137
1138   LeaveCriticalSection(&wwo->access_crst);
1139
1140   return lpWaveHdr;
1141 }
1142
1143 /* if force is TRUE then notify the client that all the headers were completed */
1144 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
1145 {
1146   LPWAVEHDR             lpWaveHdr;
1147   DWORD retval;
1148
1149   TRACE("called\n");
1150
1151   EnterCriticalSection(&wwo->access_crst);
1152
1153   /* Start from lpQueuePtr and keep notifying until:
1154    * - we hit an unwritten wavehdr
1155    * - we hit the beginning of a running loop
1156    * - we hit a wavehdr which hasn't finished playing
1157    */
1158   while ((lpWaveHdr = wwo->lpQueuePtr) &&
1159            (force || 
1160             (lpWaveHdr != wwo->lpPlayPtr &&
1161              lpWaveHdr != wwo->lpLoopPtr)))
1162   {
1163     wwo->lpQueuePtr = lpWaveHdr->lpNext;
1164
1165     lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1166     lpWaveHdr->dwFlags |= WHDR_DONE;
1167     TRACE("notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) dwFlags=(%ld)\n",
1168           lpWaveHdr, wwo->lpPlayPtr, lpWaveHdr->dwFlags);
1169
1170     wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
1171   }
1172   TRACE("Not notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) lpLoopPtr=(%p)\n",
1173         lpWaveHdr, wwo->lpPlayPtr, wwo->lpLoopPtr);
1174   retval = (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr != 
1175               wwo->lpLoopPtr) ? 0 : INFINITE;
1176
1177   LeaveCriticalSection(&wwo->access_crst);
1178
1179   return retval;
1180 }
1181
1182 /**************************************************************************
1183  *                              wodHelper_Reset                 [internal]
1184  *
1185  * Resets current output stream.
1186  */
1187 static  void  wodHelper_Reset(WINE_WAVEOUT* wwo, BOOL reset)
1188 {
1189     EnterCriticalSection(&wwo->access_crst);
1190  
1191     /* updates current notify list */
1192     wodHelper_NotifyCompletions(wwo, FALSE);
1193
1194     if (reset)
1195     {
1196         /* remove all wave headers and notify client that all headers were completed */
1197         wodHelper_NotifyCompletions(wwo, TRUE);
1198
1199         wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
1200         wwo->state = WINE_WS_STOPPED;
1201         wwo->dwPlayedTotal = wwo->dwWrittenTotal = wwo->bytesInJack = 0;
1202
1203         wwo->dwPartialOffset = 0;        /* Clear partial wavehdr */
1204     } else
1205     {
1206         if (wwo->lpLoopPtr)
1207         {
1208             /* complicated case, not handled yet (could imply modifying the loop counter) */
1209             FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
1210             wwo->lpPlayPtr = wwo->lpLoopPtr;
1211             wwo->dwPartialOffset = 0;
1212             wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
1213         } else
1214         {
1215             LPWAVEHDR   ptr;
1216             DWORD       sz = wwo->dwPartialOffset;
1217
1218             /* reset all the data as if we had written only up to lpPlayedTotal bytes */
1219             /* compute the max size playable from lpQueuePtr */
1220             for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext)
1221             {
1222                 sz += ptr->dwBufferLength;
1223             }
1224
1225             /* because the reset lpPlayPtr will be lpQueuePtr */
1226             if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("doh\n");
1227             wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal);
1228             wwo->dwWrittenTotal = wwo->dwPlayedTotal;
1229             wwo->lpPlayPtr = wwo->lpQueuePtr;
1230         }
1231
1232         wwo->state = WINE_WS_PAUSED;
1233     }
1234  
1235     LeaveCriticalSection(&wwo->access_crst);
1236 }
1237
1238 /**************************************************************************
1239  *                      wodGetDevCaps                           [internal]
1240  */
1241 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSA lpCaps, DWORD dwSize)
1242 {
1243     TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1244     
1245     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1246     
1247     if (wDevID >= MAX_WAVEOUTDRV)
1248     {
1249       TRACE("MAX_WAVOUTDRV reached !\n");
1250       return MMSYSERR_BADDEVICEID;
1251     }
1252
1253     TRACE("dwSupport=(0x%lx), dwFormats=(0x%lx)\n", WOutDev[wDevID].caps.dwSupport, WOutDev[wDevID].caps.dwFormats);
1254     memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1255     return MMSYSERR_NOERROR;
1256 }
1257
1258 /**************************************************************************
1259  *                              wodOpen                         [internal]
1260  *
1261  * NOTE: doesn't it seem like there is a race condition if you try to open 
1262  * the same device twice?
1263  */
1264 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1265 {
1266     WINE_WAVEOUT*       wwo;
1267     DWORD retval;
1268
1269     TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1270     if (lpDesc == NULL)
1271     {
1272       WARN("Invalid Parameter !\n");
1273       return MMSYSERR_INVALPARAM;
1274     }
1275     if (wDevID >= MAX_WAVEOUTDRV) {
1276       TRACE("MAX_WAVOUTDRV reached !\n");
1277       return MMSYSERR_BADDEVICEID;
1278     }
1279
1280 #if JACK_CLOSE_HACK
1281     if(WOutDev[wDevID].client && WOutDev[wDevID].in_use)
1282 #else
1283     if(WOutDev[wDevID].client)
1284 #endif
1285     {
1286       TRACE("device %d already allocated\n", wDevID);
1287       return MMSYSERR_ALLOCATED;
1288     }
1289
1290     /* Only the PCM format is supported so far...
1291      * Also we only support 16 bit mode.
1292      */
1293     if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1294       lpDesc->lpFormat->nChannels == 0 ||
1295       lpDesc->lpFormat->nSamplesPerSec == 0 ||
1296       lpDesc->lpFormat->wBitsPerSample != 16)
1297     {
1298       WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
1299        lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1300        lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
1301       return WAVERR_BADFORMAT;
1302     }
1303
1304     if (dwFlags & WAVE_FORMAT_QUERY)
1305     {
1306       TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1307        lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1308        lpDesc->lpFormat->nSamplesPerSec);
1309       return MMSYSERR_NOERROR;
1310     }
1311
1312     wwo = &WOutDev[wDevID];
1313     wwo->wDevID = wDevID;
1314
1315     /* Set things up before we call JACK_OpenWaveOutDevice because */
1316     /* we will start getting callbacks before JACK_OpenWaveOutDevice */
1317     /* even returns and we want to be initialized before then */
1318     wwo->state = WINE_WS_STOPPED; /* start in a stopped state */
1319     wwo->dwPlayedTotal = 0; /* zero out these totals */
1320     wwo->dwWrittenTotal = 0;
1321     wwo->bytesInJack = 0;
1322     wwo->tickCountMS = 0;
1323
1324     /* Initialize volume to full level */
1325     wwo->volume_left = 100;
1326     wwo->volume_right = 100;
1327
1328     InitializeCriticalSection(&wwo->access_crst); /* initialize the critical section */
1329     EnterCriticalSection(&wwo->access_crst);
1330
1331     dwFlags &= ~WAVE_DIRECTSOUND;  /* direct sound not supported, ignore the flag */
1332
1333     wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1334     
1335     memcpy(&wwo->waveDesc, lpDesc,           sizeof(WAVEOPENDESC));
1336     memcpy(&wwo->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1337
1338     /* open up jack ports for this device */
1339     if (!JACK_OpenWaveOutDevice(&WOutDev[wDevID]))
1340     {
1341       ERR("JACK_OpenWaveOutDevice(%d) failed\n", wDevID);
1342       LeaveCriticalSection(&wwo->access_crst);
1343       DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1344       return MMSYSERR_ERROR;            /* return unspecified error */
1345     }
1346
1347     LeaveCriticalSection(&wwo->access_crst);
1348
1349     /* display the current wave format */
1350     TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n", 
1351     wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
1352     wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1353     wwo->format.wf.nBlockAlign);
1354
1355     /* make sure that we have the same sample rate in our audio stream */
1356     /* as we do in the jack server */
1357     if(wwo->format.wf.nSamplesPerSec != wwo->sample_rate)
1358     {
1359       TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
1360          wwo->sample_rate, wwo->format.wf.nSamplesPerSec);
1361
1362 #if JACK_CLOSE_HACK
1363       JACK_CloseWaveOutDevice(wwo, FALSE); /* close this device, don't force the client to close */
1364 #else
1365       JACK_CloseWaveOutDevice(wwo); /* close this device */
1366 #endif
1367       DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1368       return WAVERR_BADFORMAT;
1369     }
1370
1371     /* check for an invalid number of bits per sample */
1372     if (wwo->format.wBitsPerSample == 0)
1373     {
1374       WARN("Resetting zeroed wBitsPerSample\n");
1375       wwo->format.wBitsPerSample = 8 *
1376       (wwo->format.wf.nAvgBytesPerSec /
1377        wwo->format.wf.nSamplesPerSec) /
1378        wwo->format.wf.nChannels;
1379     }
1380
1381     EnterCriticalSection(&wwo->access_crst);
1382     retval = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
1383     LeaveCriticalSection(&wwo->access_crst);
1384
1385     return retval;
1386 }
1387
1388 /**************************************************************************
1389  *                              wodClose                        [internal]
1390  */
1391 static DWORD wodClose(WORD wDevID)
1392 {
1393     DWORD               ret = MMSYSERR_NOERROR;
1394     WINE_WAVEOUT*       wwo;
1395
1396     TRACE("(%u);\n", wDevID);
1397
1398     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1399     {
1400       WARN("bad device ID !\n");
1401       return MMSYSERR_BADDEVICEID;
1402     }
1403     
1404     wwo = &WOutDev[wDevID];
1405     if (wwo->lpQueuePtr)
1406     {
1407       WARN("buffers still playing !\n");
1408       ret = WAVERR_STILLPLAYING;
1409     } else
1410     {
1411       /* sanity check: this should not happen since the device must have been reset before */
1412       if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
1413
1414       wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
1415
1416 #if JACK_CLOSE_HACK
1417       JACK_CloseWaveOutDevice(wwo, FALSE); /* close the jack device, DO NOT force the client to close */
1418 #else
1419       JACK_CloseWaveOutDevice(wwo); /* close the jack device */
1420 #endif
1421       DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1422
1423       ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
1424     }
1425
1426     return ret;
1427 }
1428
1429
1430 /**************************************************************************
1431  *                              wodWrite                        [internal]
1432  * 
1433  */
1434 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1435 {
1436     LPWAVEHDR*wh;
1437     WINE_WAVEOUT *wwo;
1438
1439     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1440     
1441     /* first, do the sanity checks... */
1442     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1443     {
1444       WARN("bad dev ID !\n");
1445       return MMSYSERR_BADDEVICEID;
1446     }
1447
1448     wwo = &WOutDev[wDevID];
1449
1450     if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1451     {
1452       TRACE("unprepared\n");
1453       return WAVERR_UNPREPARED;
1454     }
1455     
1456     if (lpWaveHdr->dwFlags & WHDR_INQUEUE) 
1457     {
1458       TRACE("still playing\n");
1459       return WAVERR_STILLPLAYING;
1460     }
1461
1462     lpWaveHdr->dwFlags &= ~WHDR_DONE;
1463     lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1464     lpWaveHdr->lpNext = 0;
1465
1466     EnterCriticalSection(&wwo->access_crst);
1467
1468     /* insert buffer at the end of queue */
1469     for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
1470     *wh = lpWaveHdr;
1471
1472     if (!wwo->lpPlayPtr)
1473       wodHelper_BeginWaveHdr(wwo,lpWaveHdr);
1474     if (wwo->state == WINE_WS_STOPPED)
1475       wwo->state = WINE_WS_PLAYING;
1476     LeaveCriticalSection(&wwo->access_crst);
1477
1478     return MMSYSERR_NOERROR;
1479 }
1480
1481 /**************************************************************************
1482  *                              wodPrepare                      [internal]
1483  */
1484 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1485 {
1486   TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1487     
1488   if (wDevID >= MAX_WAVEOUTDRV)
1489   {
1490     WARN("bad device ID !\n");
1491     return MMSYSERR_BADDEVICEID;
1492   }
1493     
1494   if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1495     return WAVERR_STILLPLAYING;
1496     
1497   lpWaveHdr->dwFlags |= WHDR_PREPARED;
1498   lpWaveHdr->dwFlags &= ~WHDR_DONE;
1499   return MMSYSERR_NOERROR;
1500 }
1501
1502 /**************************************************************************
1503  *                              wodUnprepare                    [internal]
1504  */
1505 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1506 {
1507   TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1508     
1509   if (wDevID >= MAX_WAVEOUTDRV)
1510   {
1511     WARN("bad device ID !\n");
1512     return MMSYSERR_BADDEVICEID;
1513   }
1514     
1515   if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1516     return WAVERR_STILLPLAYING;
1517     
1518   lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1519   lpWaveHdr->dwFlags |= WHDR_DONE;
1520     
1521   return MMSYSERR_NOERROR;
1522 }
1523
1524 /**************************************************************************
1525  *                      wodPause                                [internal]
1526  */
1527 static DWORD wodPause(WORD wDevID)
1528 {
1529   TRACE("(%u);!\n", wDevID);
1530     
1531   if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1532   {
1533     WARN("bad device ID !\n");
1534     return MMSYSERR_BADDEVICEID;
1535   }
1536     
1537   TRACE("[3-PAUSING]\n");
1538
1539   EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1540   wodHelper_Reset(&WOutDev[wDevID], FALSE);
1541   LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1542
1543   return MMSYSERR_NOERROR;
1544 }
1545
1546 /**************************************************************************
1547  *                      wodRestart                              [internal]
1548  */
1549 static DWORD wodRestart(WORD wDevID)
1550 {
1551     TRACE("(%u);\n", wDevID);
1552
1553     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1554     {
1555       WARN("bad device ID !\n");
1556       return MMSYSERR_BADDEVICEID;
1557     }
1558
1559     if (WOutDev[wDevID].state == WINE_WS_PAUSED)
1560     {
1561       EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1562       WOutDev[wDevID].state = WINE_WS_PLAYING;
1563       LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1564     }
1565     
1566     return MMSYSERR_NOERROR;
1567 }
1568
1569 /**************************************************************************
1570  *                      wodReset                                [internal]
1571  */
1572 static DWORD wodReset(WORD wDevID)
1573 {
1574     TRACE("(%u);\n", wDevID);
1575     
1576     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1577     {
1578       WARN("bad device ID !\n");
1579       return MMSYSERR_BADDEVICEID;
1580     }
1581
1582     EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1583     wodHelper_Reset(&WOutDev[wDevID], TRUE);
1584     LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1585
1586     return MMSYSERR_NOERROR;
1587 }
1588
1589 /**************************************************************************
1590  *                              wodGetPosition                  [internal]
1591  */
1592 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1593 {
1594     DWORD               val;
1595     WINE_WAVEOUT*       wwo;
1596     DWORD elapsedMS;
1597
1598     TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1599
1600     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1601     {
1602       WARN("bad device ID !\n");
1603       return MMSYSERR_BADDEVICEID;
1604     }
1605
1606     /* if null pointer to time structure return error */
1607     if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1608
1609     wwo = &WOutDev[wDevID];
1610
1611     EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1612     val = wwo->dwPlayedTotal;
1613     elapsedMS = GetTickCount() - wwo->tickCountMS;
1614     LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1615
1616     /* account for the bytes played since the last JACK_Callback() */
1617     val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
1618
1619     return bytes_to_mmtime(lpTime, val, &wwo->format);
1620 }
1621
1622 /**************************************************************************
1623  *                              wodBreakLoop                    [internal]
1624  */
1625 static DWORD wodBreakLoop(WORD wDevID)
1626 {
1627   TRACE("(%u);\n", wDevID);
1628
1629   if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1630   {
1631     WARN("bad device ID !\n");
1632     return MMSYSERR_BADDEVICEID;
1633   }
1634
1635   EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1636
1637   if (WOutDev[wDevID].state == WINE_WS_PLAYING && WOutDev[wDevID].lpLoopPtr != NULL)
1638   {
1639     /* ensure exit at end of current loop */
1640     WOutDev[wDevID].dwLoops = 1;
1641   }
1642
1643   LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1644
1645   return MMSYSERR_NOERROR;
1646 }
1647     
1648 /**************************************************************************
1649  *                              wodGetVolume                    [internal]
1650  */
1651 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1652 {
1653   DWORD left, right;
1654     
1655   left = WOutDev[wDevID].volume_left;
1656   right = WOutDev[wDevID].volume_right;
1657         
1658   TRACE("(%u, %p);\n", wDevID, lpdwVol);
1659  
1660   *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
1661               16);
1662     
1663   return MMSYSERR_NOERROR;
1664 }
1665
1666 /**************************************************************************
1667  *                              wodSetVolume                    [internal]
1668  */
1669 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1670 {
1671   DWORD left, right;
1672  
1673   left  = (LOWORD(dwParam) * 100) / 0xFFFFl;
1674   right = (HIWORD(dwParam) * 100) / 0xFFFFl;
1675  
1676   TRACE("(%u, %08lX);\n", wDevID, dwParam);
1677
1678   EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1679
1680   WOutDev[wDevID].volume_left = left;
1681   WOutDev[wDevID].volume_right = right;
1682
1683   LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1684
1685   return MMSYSERR_NOERROR;
1686 }
1687
1688 /**************************************************************************
1689  *                              wodGetNumDevs                   [internal]
1690  */
1691 static DWORD wodGetNumDevs(void)
1692 {
1693   return MAX_WAVEOUTDRV;
1694 }
1695
1696 /**************************************************************************
1697  *                              wodDevInterfaceSize             [internal]
1698  */
1699 static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
1700 {
1701     TRACE("(%u, %p)\n", wDevID, dwParam1);
1702                                                                                                        
1703     *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1704                                     NULL, 0 ) * sizeof(WCHAR);
1705     return MMSYSERR_NOERROR;
1706 }
1707
1708 /**************************************************************************
1709  *                              wodDevInterface                 [internal]
1710  */
1711 static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
1712 {
1713     if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1714                                         NULL, 0 ) * sizeof(WCHAR))
1715     {
1716         MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1717                             dwParam1, dwParam2 / sizeof(WCHAR));
1718         return MMSYSERR_NOERROR;
1719     }
1720     return MMSYSERR_INVALPARAM;
1721 }
1722
1723 /**************************************************************************
1724  *                              wodMessage (WINEJACK.7)
1725  */
1726 DWORD WINAPI JACK_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser, 
1727                             DWORD dwParam1, DWORD dwParam2)
1728 {
1729   TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
1730   wDevID, wMsg, dwUser, dwParam1, dwParam2);
1731     
1732   switch (wMsg) {
1733   case DRVM_INIT:
1734     TRACE("DRVM_INIT\n");
1735     return JACK_WaveInit();
1736   case DRVM_EXIT:
1737     TRACE("DRVM_EXIT\n");
1738     return JACK_WaveRelease();
1739   case DRVM_ENABLE:
1740   /* FIXME: Pretend this is supported */
1741     TRACE("DRVM_ENABLE\n");
1742     return 0;
1743   case DRVM_DISABLE:
1744   /* FIXME: Pretend this is supported */
1745     TRACE("DRVM_DISABLE\n");
1746     return 0;
1747   case WODM_OPEN:             return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1,  dwParam2);
1748   case WODM_CLOSE:            return wodClose(wDevID);
1749   case WODM_WRITE:            return wodWrite(wDevID, (LPWAVEHDR)dwParam1,              dwParam2);
1750   case WODM_PAUSE:            return wodPause(wDevID);
1751   case WODM_GETPOS:           return wodGetPosition(wDevID, (LPMMTIME)dwParam1,                 dwParam2);
1752   case WODM_BREAKLOOP:        return wodBreakLoop(wDevID);
1753   case WODM_PREPARE:          return wodPrepare(wDevID, (LPWAVEHDR)dwParam1,            dwParam2);
1754   case WODM_UNPREPARE:        return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1,          dwParam2);
1755   case WODM_GETDEVCAPS:       return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSA)dwParam1,    dwParam2);
1756   case WODM_GETNUMDEVS:       return wodGetNumDevs();
1757   case WODM_GETPITCH:         return MMSYSERR_NOTSUPPORTED;
1758   case WODM_SETPITCH:         return MMSYSERR_NOTSUPPORTED;
1759   case WODM_GETPLAYBACKRATE:    return MMSYSERR_NOTSUPPORTED;
1760   case WODM_SETPLAYBACKRATE:    return MMSYSERR_NOTSUPPORTED;
1761   case WODM_GETVOLUME:        return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1762   case WODM_SETVOLUME:        return wodSetVolume(wDevID, dwParam1);
1763   case WODM_RESTART:          return wodRestart(wDevID);
1764   case WODM_RESET:            return wodReset(wDevID);
1765
1766   case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize       (wDevID, (LPDWORD)dwParam1);
1767   case DRV_QUERYDEVICEINTERFACE:     return wodDevInterface           (wDevID, (PWCHAR)dwParam1, dwParam2);
1768   case DRV_QUERYDSOUNDIFACE:    return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1);
1769   case DRV_QUERYDSOUNDDESC:     return wodDsDesc(wDevID, (PDSDRIVERDESC)dwParam1);
1770   case DRV_QUERYDSOUNDGUID:     return wodDsGuid(wDevID, (LPGUID)dwParam1);
1771   default:
1772     FIXME("unknown message %d!\n", wMsg);
1773     }
1774     return MMSYSERR_NOTSUPPORTED;
1775 }
1776
1777 /*======================================================================*
1778  *                  Low level DSOUND implementation                     *
1779  *======================================================================*/
1780
1781 typedef struct IDsDriverImpl IDsDriverImpl;
1782 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;
1783
1784 struct IDsDriverImpl
1785 {
1786     /* IUnknown fields */
1787     ICOM_VFIELD(IDsDriver);
1788     DWORD               ref;
1789     /* IDsDriverImpl fields */
1790     UINT                wDevID;
1791     IDsDriverBufferImpl*primary;
1792 };
1793
1794 struct IDsDriverBufferImpl
1795 {
1796     /* IUnknown fields */
1797     ICOM_VFIELD(IDsDriverBuffer);
1798     DWORD ref;
1799     /* IDsDriverBufferImpl fields */
1800     IDsDriverImpl* drv;
1801     DWORD buflen;
1802 };
1803
1804 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
1805 {
1806     /* we can't perform memory mapping as we don't have a file stream 
1807       interface with jack like we do with oss */
1808     MESSAGE("This sound card's driver does not support direct access\n");
1809     MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
1810     return MMSYSERR_NOTSUPPORTED;
1811 }
1812
1813 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
1814 {
1815     memset(desc, 0, sizeof(*desc));
1816     strcpy(desc->szDesc, "Wine jack DirectSound Driver");
1817     strcpy(desc->szDrvName, "winejack.drv");
1818     return MMSYSERR_NOERROR;
1819 }
1820
1821 static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid)
1822 {
1823     memcpy(pGuid, &DSDEVID_DefaultPlayback, sizeof(GUID));
1824     return MMSYSERR_NOERROR;
1825 }
1826
1827 /*======================================================================*
1828  *                  Low level WAVE IN implementation                    *
1829  *======================================================================*/
1830
1831 /**************************************************************************
1832  *                      widNotifyClient                 [internal]
1833  */
1834 static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1835 {
1836     TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
1837     
1838     switch (wMsg) {
1839     case WIM_OPEN:
1840     case WIM_CLOSE:
1841     case WIM_DATA:
1842       if (wwi->wFlags != DCB_NULL &&
1843         !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
1844           (HDRVR)wwi->waveDesc.hWave, wMsg, wwi->waveDesc.dwInstance,
1845           dwParam1, dwParam2))
1846       {
1847         WARN("can't notify client !\n");
1848         return MMSYSERR_ERROR;
1849       }
1850     break;
1851     default:
1852       FIXME("Unknown callback message %u\n", wMsg);
1853         return MMSYSERR_INVALPARAM;
1854     }
1855     return MMSYSERR_NOERROR;
1856 }
1857
1858 /******************************************************************
1859  *    JACK_callback_wwi
1860  */
1861 /* everytime the jack server wants something from us it calls this 
1862    function */
1863 int JACK_callback_wwi (nframes_t nframes, void *arg)
1864 {
1865     sample_t* in_l;
1866     sample_t* in_r = 0;
1867     WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
1868
1869     TRACE("wDevID: %u, nframes %u\n", wwi->wDevID, nframes);
1870     
1871     if(!wwi->client)
1872         ERR("client is closed, this is weird...\n");
1873     
1874     in_l = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_l, nframes);
1875
1876     if (wwi->in_port_r)
1877       in_r = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_r, nframes);
1878     
1879     EnterCriticalSection(&wwi->access_crst);
1880     
1881     if((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
1882     {
1883         LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
1884         nframes_t jackFramesLeft = nframes;
1885
1886 #if JACK_CLOSE_HACK
1887         if(wwi->in_use == FALSE)
1888         {
1889           /* do nothing if nothing is being recorded */
1890             return 0;
1891         }
1892 #endif
1893         
1894         TRACE("wwi.state == WINE_WS_PLAYING\n");
1895         
1896         while (lpWaveHdr && jackFramesLeft)
1897         {
1898             DWORD waveHdrFramesLeft = (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded) / (sizeof(short) * wwi->format.wf.nChannels); 
1899             DWORD numFrames = min (jackFramesLeft, waveHdrFramesLeft);
1900             
1901             TRACE ("dwBufferLength=(%lu) dwBytesRecorded=(%ld)\n",   lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
1902             TRACE ("jackFramesLeft=(%u) waveHdrFramesLeft=(%lu)\n", jackFramesLeft, waveHdrFramesLeft);
1903
1904             if (!in_r) {
1905               /* mono */
1906               sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded), in_l+(nframes-jackFramesLeft), numFrames, 1);
1907             } else {
1908               /* stereo */
1909               sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded), 
1910                                   in_l+(nframes-jackFramesLeft), numFrames, 2);
1911               sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded + sizeof(short)), 
1912                                   in_r+(nframes-jackFramesLeft), numFrames, 2);
1913             }
1914             
1915             lpWaveHdr->dwBytesRecorded += (numFrames * sizeof(short) * wwi->format.wf.nChannels );
1916             jackFramesLeft -= numFrames;
1917
1918             if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
1919             {
1920                 /* must copy the value of next waveHdr, because we have no idea of what
1921                  * will be done with the content of lpWaveHdr in callback
1922                  */
1923                 LPWAVEHDR       lpNext = lpWaveHdr->lpNext;
1924                                 
1925                 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1926                 lpWaveHdr->dwFlags |=  WHDR_DONE;
1927
1928                 TRACE("WaveHdr full. dwBytesRecorded=(%lu) dwFlags=(0x%lx)\n",lpWaveHdr->dwBytesRecorded,lpWaveHdr->dwFlags);
1929
1930                 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1931
1932                 lpWaveHdr = wwi->lpQueuePtr = lpNext;
1933             }
1934         }
1935         TRACE ("jackFramesLeft=(%u) lpWaveHdr=(%p)\n", jackFramesLeft, lpWaveHdr);
1936         if (jackFramesLeft > 0) { WARN("Record buffer ran out of WaveHdrs\n"); }
1937     }
1938     
1939     LeaveCriticalSection(&wwi->access_crst);
1940
1941     return 0;
1942 }
1943
1944 /******************************************************************
1945  *              JACK_OpenWaveInDevice
1946  */
1947 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels)
1948 {
1949   const char** ports;
1950   int i;
1951   char client_name[64];
1952   jack_port_t* in_port_l;
1953   jack_port_t* in_port_r = 0;
1954   jack_client_t* client;
1955   int failed = 0;
1956
1957   TRACE("creating jack client and setting up callbacks\n");
1958
1959   if ((nChannels == 0) || (nChannels > 2)) {
1960     ERR ("nChannels = (%d), but we only support mono or stereo.\n", nChannels);
1961     return 0;
1962   }
1963
1964 #if JACK_CLOSE_HACK
1965   /* see if this device is already open */
1966         if(wwi->client)
1967         {
1968           /* if this device is already in use then it is bad for us to be in here */
1969           if(wwi->in_use)
1970             return 0;
1971
1972           TRACE("using existing client\n");
1973           wwi->in_use = TRUE;
1974           return 1;
1975         }
1976 #endif
1977
1978         /* zero out the buffer pointer and the size of the buffer */
1979         wwi->sound_buffer = 0;
1980         wwi->buffer_size = 0;
1981
1982         /* try to become a client of the JACK server */
1983         snprintf(client_name, sizeof(client_name), "wine_jack_in_%d", wwi->wDevID);
1984         TRACE("client name '%s'\n", client_name);
1985         if ((client = fp_jack_client_new (client_name)) == 0)
1986         {
1987                 /* jack has problems with shutting down clients, so lets */
1988                 /* wait a short while and try once more before we give up */
1989                 Sleep(250);
1990                 if ((client = fp_jack_client_new (client_name)) == 0)
1991                 {
1992                   ERR("jack server not running?\n");
1993                   return 0;
1994                 }
1995         }
1996         wwi->client = client;
1997                 
1998         /* tell the JACK server to call `JACK_wwi_callback()' whenever
1999            there is work to be done. */
2000         fp_jack_set_process_callback (client, JACK_callback_wwi, wwi);
2001         
2002         /* tell the JACK server to call `JACK_bufsize_wwi()' whenever   
2003            the maximum number of frames that will be passed
2004            to `JACK_Callback()' changes */
2005         fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwi, wwi);
2006           
2007         /* tell the JACK server to call `srate()' whenever
2008            the sample rate of the system changes. */
2009         fp_jack_set_sample_rate_callback (client, JACK_srate, wwi);
2010
2011         /* tell the JACK server to call `jack_shutdown()' if
2012            it ever shuts down, either entirely, or if it
2013            just decides to stop calling us. */
2014         fp_jack_on_shutdown (client, JACK_shutdown_wwi, wwi);
2015         
2016         /* display the current sample rate. once the client is activated
2017            (see below), you should rely on your own sample rate
2018            callback (see above) for this value. */
2019         wwi->sample_rate = fp_jack_get_sample_rate(client);
2020         TRACE("engine sample rate: %lu\n", wwi->sample_rate);
2021           
2022         /* create the left and right channel output ports */
2023         /* jack's ports are all mono so for stereo you need two */
2024         in_port_l = fp_jack_port_register (client, "in_l",
2025                          JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
2026         wwi->in_port_l = in_port_l;
2027         TRACE("Created port. (%p)\n", in_port_l);
2028
2029         if (nChannels == 2)
2030         {
2031           in_port_r = fp_jack_port_register (client, "in_r",
2032                            JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); 
2033           TRACE("Created port. (%p)\n", in_port_r);
2034         } 
2035         wwi->in_port_r = in_port_r;
2036
2037 #if JACK_CLOSE_HACK
2038         wwi->in_use = TRUE; /* mark this device as in use since it now is ;-) */
2039 #endif
2040
2041         TRACE("activating client.\n");
2042         /* tell the JACK server that we are ready to roll */
2043         if (fp_jack_activate (client))
2044         {
2045           ERR( "cannot activate client\n");
2046           return 0;
2047         }
2048         TRACE("activated client.\n");
2049         /* figure out what the ports that we want to output on are */
2050         /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
2051         /*   this way works if names are changed */
2052         ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
2053
2054         /* display a trace of the output ports we found */
2055         for(i = 0; ports[i]; i++)
2056         {
2057           TRACE("ports[%d] = '%s'\n", i, ports[i]);
2058         }
2059
2060         if(!ports)
2061         {
2062           ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsOutput'\n");
2063         }
2064
2065         /* connect the ports. Note: you can't do this before
2066            the client is activated (this may change in the future).
2067         */ 
2068         /* we want to connect to two ports so we have stereo input ;-) */
2069
2070         if(fp_jack_connect(client, ports[0], fp_jack_port_name(in_port_l)))
2071         {
2072           ERR ("cannot connect to input port %d('%s')\n", 0, ports[0]);
2073           failed = 1;
2074         }
2075         TRACE("Connected (%s)<->(%s)\n",ports[0],fp_jack_port_name(in_port_l));
2076
2077         if ((nChannels == 2) && in_port_r) {
2078           if(fp_jack_connect(client, ports[1], fp_jack_port_name(in_port_r)))
2079           {
2080             ERR ("cannot connect to input port %d('%s')\n", 1, ports[1]);
2081             failed = 1;
2082           }
2083           TRACE("Connected (%s)<->(%s)\n",ports[1],fp_jack_port_name(in_port_r));
2084         }
2085         free(ports); /* free the returned array of ports */
2086
2087         /* if something failed we need to shut the client down and return 0 */
2088         if(failed)
2089         {
2090 #if JACK_CLOSE_HACK
2091           JACK_CloseWaveInDevice(wwi, TRUE);
2092 #else
2093           JACK_CloseWaveInDevice(wwi);
2094 #endif
2095           return 0;
2096         }
2097
2098         TRACE("return success.\n");
2099         return 1; /* return success */
2100 }
2101
2102 /**************************************************************************
2103  *                      widGetDevCaps                           [internal]
2104  */
2105 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSA lpCaps, DWORD dwSize)
2106 {
2107     TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
2108
2109     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
2110
2111     if (wDevID >= MAX_WAVEINDRV) {
2112         TRACE("MAX_WAVEINDRV reached !\n");
2113         return MMSYSERR_BADDEVICEID;
2114     }
2115
2116     memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
2117     return MMSYSERR_NOERROR;
2118 }
2119
2120 /**************************************************************************
2121  *                              widOpen                         [internal]
2122  */
2123 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
2124 {
2125     WINE_WAVEIN*        wwi;
2126     DWORD retval;
2127
2128     TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
2129     if (lpDesc == NULL)
2130     {
2131         WARN("Invalid Parameter !\n");
2132         return MMSYSERR_INVALPARAM;
2133     }
2134     if (wDevID >= MAX_WAVEINDRV) {
2135         TRACE ("MAX_WAVEINDRV reached !\n");
2136         return MMSYSERR_BADDEVICEID;
2137     }
2138
2139 #if JACK_CLOSE_HACK
2140     if(WInDev[wDevID].client && WOutDev[wDevID].in_use)
2141 #else
2142     if(WInDev[wDevID].client)
2143 #endif
2144     {
2145       TRACE("device %d already allocated\n", wDevID);
2146       return MMSYSERR_ALLOCATED;
2147     }
2148
2149     /* Only the PCM format is supported so far...
2150      * Also we only support 16 bit mode.
2151      */
2152     if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
2153       lpDesc->lpFormat->nChannels == 0 ||
2154       lpDesc->lpFormat->nSamplesPerSec == 0 ||
2155       lpDesc->lpFormat->wBitsPerSample!=16)
2156     {
2157       WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
2158        lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2159        lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
2160       return WAVERR_BADFORMAT;
2161     }
2162
2163     if (dwFlags & WAVE_FORMAT_QUERY)
2164     {
2165       TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
2166        lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2167        lpDesc->lpFormat->nSamplesPerSec);
2168       return MMSYSERR_NOERROR;
2169     }
2170
2171     wwi = &WInDev[wDevID];
2172     wwi->wDevID = wDevID;
2173
2174     /* Set things up before we call JACK_OpenWaveOutDevice because */
2175     /* we will start getting callbacks before JACK_OpenWaveOutDevice */
2176     /* even returns and we want to be initialized before then */
2177     wwi->state = WINE_WS_STOPPED; /* start in a stopped state */
2178
2179     InitializeCriticalSection(&wwi->access_crst); /* initialize the critical section */
2180     EnterCriticalSection(&wwi->access_crst);
2181
2182     /* open up jack ports for this device */
2183     if (!JACK_OpenWaveInDevice(&WInDev[wDevID], lpDesc->lpFormat->nChannels))
2184     {
2185       ERR("JACK_OpenWaveInDevice(%d) failed\n", wDevID);
2186       LeaveCriticalSection(&wwi->access_crst);
2187       DeleteCriticalSection(&wwi->access_crst);
2188       return MMSYSERR_ERROR;            /* return unspecified error */
2189     }
2190
2191     dwFlags &= ~WAVE_DIRECTSOUND;  /* direct sound not supported, ignore the flag */
2192
2193     wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
2194     
2195     memcpy(&wwi->waveDesc, lpDesc,           sizeof(WAVEOPENDESC));
2196     memcpy(&wwi->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
2197
2198     LeaveCriticalSection(&wwi->access_crst);
2199
2200     /* display the current wave format */
2201     TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n", 
2202     wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
2203     wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
2204     wwi->format.wf.nBlockAlign);
2205
2206     /* make sure that we have the same sample rate in our audio stream */
2207     /* as we do in the jack server */
2208     if(wwi->format.wf.nSamplesPerSec != wwi->sample_rate)
2209     {
2210       TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
2211          wwi->sample_rate, wwi->format.wf.nSamplesPerSec);
2212
2213 #if JACK_CLOSE_HACK
2214       JACK_CloseWaveInDevice(wwi, FALSE); /* close this device, don't force the client to close */
2215 #else
2216       JACK_CloseWaveInDevice(wwi); /* close this device */
2217 #endif
2218       DeleteCriticalSection(&wwi->access_crst);
2219       return WAVERR_BADFORMAT;
2220     }
2221
2222     /* check for an invalid number of bits per sample */
2223     if (wwi->format.wBitsPerSample == 0)
2224     {
2225       WARN("Resetting zeroed wBitsPerSample\n");
2226       wwi->format.wBitsPerSample = 8 *
2227       (wwi->format.wf.nAvgBytesPerSec /
2228        wwi->format.wf.nSamplesPerSec) /
2229        wwi->format.wf.nChannels;
2230     }
2231
2232     TRACE("notify client.\n");
2233     EnterCriticalSection(&wwi->access_crst);
2234     retval = widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
2235     LeaveCriticalSection(&wwi->access_crst);
2236
2237     return retval;
2238 }
2239 /**************************************************************************
2240  *                              widClose                        [internal]
2241  */
2242 static DWORD widClose(WORD wDevID)
2243 {
2244     DWORD               ret = MMSYSERR_NOERROR;
2245     WINE_WAVEIN*        wwi;
2246
2247     TRACE("(%u);\n", wDevID);
2248
2249     if (wDevID >= MAX_WAVEINDRV || !WInDev[wDevID].client)
2250     {
2251       WARN("bad device ID !\n");
2252       return MMSYSERR_BADDEVICEID;
2253     }
2254     
2255     wwi = &WInDev[wDevID];
2256     if (wwi->lpQueuePtr)
2257     {
2258       WARN("buffers still playing !\n");
2259       ret = WAVERR_STILLPLAYING;
2260     } else
2261     {
2262         /* sanity check: this should not happen since the device must have been reset before */
2263         if (wwi->lpQueuePtr) ERR("out of sync\n");
2264         
2265         wwi->state = WINE_WS_CLOSED; /* mark the device as closed */
2266         
2267 #if JACK_CLOSE_HACK
2268         JACK_CloseWaveInDevice(wwi, FALSE); /* close the jack device, DO NOT force the client to close */
2269 #else
2270         JACK_CloseWaveInDevice(wwi); /* close the jack device */
2271 #endif
2272         DeleteCriticalSection(&wwi->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
2273         
2274         ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
2275     }
2276
2277     return ret;
2278 }
2279
2280 /**************************************************************************
2281  *                              widAddBuffer            [internal]
2282  */
2283 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2284 {
2285     WINE_WAVEIN* wwi = &WInDev[wDevID];
2286
2287     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2288
2289     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2290                                 WARN("can't do it !\n");
2291                                 return MMSYSERR_INVALHANDLE;
2292     }
2293     if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
2294                                 TRACE("never been prepared !\n");
2295                                 return WAVERR_UNPREPARED;
2296     }
2297     if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2298                                 TRACE("header already in use !\n");
2299                                 return WAVERR_STILLPLAYING;
2300     }
2301
2302     lpWaveHdr->dwFlags |= WHDR_INQUEUE;
2303     lpWaveHdr->dwFlags &= ~WHDR_DONE;
2304     lpWaveHdr->dwBytesRecorded = 0;
2305     lpWaveHdr->lpNext = NULL;
2306
2307     EnterCriticalSection(&wwi->access_crst);
2308     /* insert buffer at end of queue */
2309     {
2310         LPWAVEHDR* wh;
2311         for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
2312         *wh=lpWaveHdr;
2313     }
2314     LeaveCriticalSection(&wwi->access_crst);
2315
2316     return MMSYSERR_NOERROR;
2317 }
2318
2319 /**************************************************************************
2320  *                              widPrepare                      [internal]
2321  */
2322 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2323 {
2324     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2325                 
2326     if (wDevID >= MAX_WAVEINDRV) return MMSYSERR_INVALHANDLE;
2327                 
2328     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
2329                                 return WAVERR_STILLPLAYING;
2330
2331     lpWaveHdr->dwFlags |= WHDR_PREPARED;
2332     lpWaveHdr->dwFlags &= ~WHDR_DONE;
2333     lpWaveHdr->dwBytesRecorded = 0;
2334     lpWaveHdr->lpNext = NULL;
2335
2336     return MMSYSERR_NOERROR;
2337 }
2338
2339 /**************************************************************************
2340  *                              widUnprepare                    [internal]
2341  */
2342 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2343 {
2344     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2345     if (wDevID >= MAX_WAVEINDRV) {
2346                                 WARN("bad device ID !\n");
2347                                 return MMSYSERR_INVALHANDLE;
2348     }
2349
2350     if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2351                                 TRACE("Still playing...\n");
2352                                 return WAVERR_STILLPLAYING;
2353     }
2354
2355     lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
2356     lpWaveHdr->dwFlags |= WHDR_DONE;
2357
2358     return MMSYSERR_NOERROR;
2359 }
2360
2361 /**************************************************************************
2362  *                      widStart                                [internal]
2363  */
2364 static DWORD widStart(WORD wDevID)
2365 {
2366     TRACE("(%u);\n", wDevID);
2367     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2368         WARN("can't start recording !\n");
2369         return MMSYSERR_INVALHANDLE;
2370     }
2371
2372     WInDev[wDevID].state = WINE_WS_PLAYING;
2373     return MMSYSERR_NOERROR;
2374 }
2375
2376 /**************************************************************************
2377  *                      widStop                                 [internal]
2378  */
2379 static DWORD widStop(WORD wDevID)
2380 {
2381     WINE_WAVEIN* wwi = &WInDev[wDevID];
2382
2383     TRACE("(%u);\n", wDevID);
2384     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2385         WARN("can't stop !\n");
2386         return MMSYSERR_INVALHANDLE;
2387     }
2388     
2389     if (wwi->state != WINE_WS_STOPPED)
2390     {
2391         WAVEHDR*                lpWaveHdr;
2392         /* do something here to stop recording ??? */
2393         
2394         /* return current buffer to app */
2395         lpWaveHdr = wwi->lpQueuePtr;
2396         if (lpWaveHdr)
2397         {
2398             LPWAVEHDR   lpNext = lpWaveHdr->lpNext;
2399             TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2400             lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2401             lpWaveHdr->dwFlags |= WHDR_DONE;
2402             widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2403             wwi->lpQueuePtr = lpNext;
2404         }
2405     }
2406     wwi->state = WINE_WS_STOPPED;
2407
2408     return MMSYSERR_NOERROR;
2409 }
2410
2411 /**************************************************************************
2412  *                      widReset                                [internal]
2413  */
2414 static DWORD widReset(WORD wDevID)
2415 {
2416     WINE_WAVEIN* wwi = &WInDev[wDevID];
2417     WAVEHDR*            lpWaveHdr;
2418
2419     TRACE("(%u);\n", wDevID);
2420     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2421         WARN("can't reset !\n");
2422         return MMSYSERR_INVALHANDLE;
2423     }
2424
2425     wwi->state = WINE_WS_STOPPED;
2426
2427     /* return all buffers to the app */
2428     for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
2429         TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2430         lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2431         lpWaveHdr->dwFlags |= WHDR_DONE;
2432         
2433         widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2434     }
2435     wwi->lpQueuePtr = NULL;
2436
2437     return MMSYSERR_NOERROR;
2438 }
2439
2440 /**************************************************************************
2441  *                              widGetNumDevs                   [internal]
2442  */
2443 static DWORD widGetNumDevs(void)
2444 {
2445   return MAX_WAVEINDRV;
2446 }
2447
2448 /**************************************************************************
2449  *                              widDevInterfaceSize             [internal]
2450  */
2451 static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
2452 {
2453     TRACE("(%u, %p)\n", wDevID, dwParam1);
2454                                                                                                        
2455                                                                                                        
2456     *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2457                                     NULL, 0 ) * sizeof(WCHAR);
2458     return MMSYSERR_NOERROR;
2459 }
2460
2461 /**************************************************************************
2462  *                              widDevInterface                 [internal]
2463  */
2464 static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
2465 {
2466     if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2467                                         NULL, 0 ) * sizeof(WCHAR))
2468     {
2469         MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2470                             dwParam1, dwParam2 / sizeof(WCHAR));
2471         return MMSYSERR_NOERROR;
2472     }
2473     return MMSYSERR_INVALPARAM;
2474 }
2475
2476 /**************************************************************************
2477  *                              widMessage (WINEJACK.6)
2478  */
2479 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
2480                             DWORD dwParam1, DWORD dwParam2)
2481 {
2482   TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
2483   wDevID, wMsg, dwUser, dwParam1, dwParam2);
2484
2485     switch (wMsg) {
2486     case DRVM_INIT:
2487     case DRVM_EXIT:
2488     case DRVM_ENABLE:
2489     case DRVM_DISABLE:
2490         /* FIXME: Pretend this is supported */
2491         return 0;
2492     case WIDM_OPEN:             return widOpen          (wDevID, (LPWAVEOPENDESC)dwParam1,      dwParam2);
2493     case WIDM_CLOSE:            return widClose         (wDevID);
2494     case WIDM_ADDBUFFER:        return widAddBuffer     (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2495     case WIDM_PREPARE:          return widPrepare       (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2496     case WIDM_UNPREPARE:        return widUnprepare     (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2497     case WIDM_GETDEVCAPS:       return widGetDevCaps    (wDevID, (LPWAVEINCAPSA)dwParam1,       dwParam2);
2498     case WIDM_GETNUMDEVS:       return widGetNumDevs();
2499     case WIDM_RESET:            return widReset         (wDevID);
2500     case WIDM_START:            return widStart         (wDevID);
2501     case WIDM_STOP:             return widStop          (wDevID);
2502     case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize       (wDevID, (LPDWORD)dwParam1);
2503     case DRV_QUERYDEVICEINTERFACE:     return widDevInterface           (wDevID, (PWCHAR)dwParam1, dwParam2);
2504     default:
2505         FIXME("unknown message %d!\n", wMsg);
2506     }
2507
2508   return MMSYSERR_NOTSUPPORTED;
2509 }
2510
2511 #else /* !HAVE_JACK_JACK_H */
2512
2513 /**************************************************************************
2514  *                              widMessage (WINEJACK.6)
2515  */
2516 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
2517                             DWORD dwParam1, DWORD dwParam2)
2518 {
2519   FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2520   return MMSYSERR_NOTENABLED;
2521 }
2522
2523 /**************************************************************************
2524  *                              wodMessage (WINEJACK.7)
2525  */
2526 DWORD WINAPI JACK_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
2527                             DWORD dwParam1, DWORD dwParam2)
2528 {
2529   FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2530   return MMSYSERR_NOTENABLED;
2531 }
2532
2533 #endif /* HAVE_JACK_JACK_H */