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