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