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