Fixed some issues found by winapi_check.
[wine] / dlls / winmm / winejack / audio.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
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  *  implement wave-in support with jack
33  *
34  * FIXME:
35  *  pause in waveOut during loop is not handled correctly
36  */
37
38 #include "config.h"
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46 #include <errno.h>
47 #include <fcntl.h>
48 #include "windef.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 #undef MAKE_FUNCPTR
86
87 /* define the below to work around a bug in jack where closing a port */
88 /* takes a very long time, so to get around this we actually don't */
89 /* close the port when the device is closed but instead mark the */
90 /* corresponding device as unused */
91 #define JACK_CLOSE_HACK    1
92
93 typedef jack_default_audio_sample_t sample_t;
94 typedef jack_nframes_t nframes_t;
95
96 /* only allow 10 output devices through this driver, this ought to be adequate */
97 #define MAX_WAVEOUTDRV  (10)
98 #define MAX_WAVEINDRV   (1)
99
100 /* state diagram for waveOut writing:
101  *
102  * +---------+-------------+---------------+---------------------------------+
103  * |  state  |  function   |     event     |            new state            |
104  * +---------+-------------+---------------+---------------------------------+
105  * |         | open()      |               | STOPPED                         |
106  * | PAUSED  | write()     |               | PAUSED                          |
107  * | STOPPED | write()     | <thrd create> | PLAYING                         |
108  * | PLAYING | write()     | HEADER        | PLAYING                         |
109  * | (other) | write()     | <error>       |                                 |
110  * | (any)   | pause()     | PAUSING       | PAUSED                          |
111  * | PAUSED  | restart()   | RESTARTING    | PLAYING (if no thrd => STOPPED) |
112  * | (any)   | reset()     | RESETTING     | STOPPED                         |
113  * | (any)   | close()     | CLOSING       | CLOSED                          |
114  * +---------+-------------+---------------+---------------------------------+
115  */
116
117 /* states of the playing device */
118 #define WINE_WS_PLAYING   0
119 #define WINE_WS_PAUSED    1
120 #define WINE_WS_STOPPED   2
121 #define WINE_WS_CLOSED    3
122
123 typedef struct {
124     volatile int      state;      /* one of the WINE_WS_ manifest constants */
125     WAVEOPENDESC      waveDesc;
126     WORD              wFlags;
127     PCMWAVEFORMAT     format;
128     WAVEOUTCAPSA      caps;
129     WORD              wDevID;
130
131     jack_port_t*      out_port_l;   /* ports for left and right channels */
132     jack_port_t*      out_port_r;
133     jack_client_t*    client;
134     long              sample_rate;        /* jack server sample rate */
135
136 #if JACK_CLOSE_HACK
137     BOOL              in_use; /* TRUE if this device is in use */
138 #endif
139
140     char*             sound_buffer;
141     unsigned long     buffer_size;
142
143     DWORD             volume_left;
144     DWORD             volume_right;
145
146     LPWAVEHDR         lpQueuePtr;   /* start of queued WAVEHDRs (waiting to be notified) */
147     LPWAVEHDR         lpPlayPtr;    /* start of not yet fully played buffers */
148     DWORD             dwPartialOffset;  /* Offset of not yet written bytes in lpPlayPtr */
149
150     LPWAVEHDR         lpLoopPtr;    /* pointer of first buffer in loop, if any */
151     DWORD             dwLoops;      /* private copy of loop counter */
152     
153     DWORD             dwPlayedTotal;    /* number of bytes actually played since opening */
154     DWORD             dwWrittenTotal;   /* number of bytes written to jack since opening */
155
156     DWORD             bytesInJack; /* bytes that we wrote during the previous JACK_Callback() */
157     DWORD             tickCountMS; /* time in MS of last JACK_Callback() */
158
159     /* synchronization stuff */
160     CRITICAL_SECTION    access_crst;
161 } WINE_WAVEOUT;
162
163 typedef struct {
164     volatile int    state;
165     WAVEOPENDESC    waveDesc;
166     WORD            wFlags;
167     PCMWAVEFORMAT   format;
168     LPWAVEHDR       lpQueuePtr;
169     DWORD           dwTotalRecorded;
170     WAVEINCAPSA     caps;
171     BOOL            bTriggerSupport;
172
173     /* synchronization stuff */
174     CRITICAL_SECTION    access_crst;
175 } WINE_WAVEIN;
176
177 static WINE_WAVEOUT WOutDev   [MAX_WAVEOUTDRV];
178 static WINE_WAVEIN  WInDev    [MAX_WAVEINDRV ];
179
180 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
181 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo);
182 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force);
183  
184 static int JACK_OpenDevice(WINE_WAVEOUT* wwo);
185
186 #if JACK_CLOSE_HACK
187 static void     JACK_CloseDevice(WINE_WAVEOUT* wwo, BOOL close_client);
188 #else
189 static void     JACK_CloseDevice(WINE_WAVEOUT* wwo);
190 #endif
191
192
193 /*======================================================================*
194  *                  Low level WAVE implementation                       *
195  *======================================================================*/
196
197 #define SAMPLE_MAX_16BIT  32767.0f
198
199 /* Alsaplayer function that applies volume changes to a buffer */
200 /* (C) Andy Lo A Foe */
201 /* Length is in terms of 32 bit samples */
202 void volume_effect32(void *buffer, int length, int left, int right)
203 {
204         short *data = (short *)buffer;
205         int i, v;
206     
207         if (right == -1) right = left;
208  
209         for(i = 0; i < length; i++) {
210                 v = (int) ((*(data) * left) / 100);
211                 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
212                 v = (int) ((*(data) * right) / 100);
213                 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
214         }
215 }
216
217 /* move 16 bit mono/stereo to 16 bit stereo */
218 void sample_move_d16_d16(short *dst, short *src,
219                   unsigned long nsamples, int nChannels)
220 {
221   while(nsamples--)
222   {
223     *dst = *src;
224     dst++;
225
226     if(nChannels == 2) src++;
227
228     *dst = *src;
229     dst++;
230
231     src++;
232   }
233 }
234
235 /* convert from 16 bit to floating point */
236 /* allow for copying of stereo data with alternating left/right */
237 /* channels to a buffer that will hold a single channel stream */
238 /* nsamples is in terms of 16bit samples */
239 /* src_skip is in terms of 16bit samples */
240 void sample_move_d16_s16 (sample_t *dst, short *src,
241                         unsigned long nsamples, unsigned long src_skip)
242 {
243   /* ALERT: signed sign-extension portability !!! */
244   while (nsamples--)
245   {
246     *dst = (*src) / SAMPLE_MAX_16BIT;
247     dst++;
248     src += src_skip;
249   }
250 }       
251
252 /* fill dst buffer with nsamples worth of silence */
253 void sample_silence_dS (sample_t *dst, unsigned long nsamples)
254 {
255   /* ALERT: signed sign-extension portability !!! */
256   while (nsamples--)
257   {
258     *dst = 0;
259     dst++;
260   }
261 }       
262
263 /******************************************************************
264  *    JACK_callback
265  */
266 /* everytime the jack server wants something from us it calls this 
267 function, so we either deliver it some sound to play or deliver it nothing 
268 to play */
269 int JACK_callback (nframes_t nframes, void *arg)
270 {
271   sample_t* out_l;
272   sample_t* out_r;
273   WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
274
275   TRACE("wDevID: %d, nframes %ld\n", wwo->wDevID, nframes);
276
277   if(!wwo->client)
278     ERR("client is closed, this is weird...\n");
279     
280   out_l = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_l, 
281       nframes);
282   out_r = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_r, 
283       nframes);
284
285   EnterCriticalSection(&wwo->access_crst);
286
287   if(wwo->state == WINE_WS_PLAYING)
288   {
289     DWORD jackBytesAvailableThisCallback = sizeof(sample_t) * nframes;
290     DWORD jackBytesLeft = sizeof(sample_t) * nframes;
291
292     DWORD inputBytesAvailable; /* number of bytes we have from the app, after conversion to 16bit stereo */
293     DWORD jackBytesToWrite; /* number of bytes we are going to write out, after conversion */
294
295     DWORD bytesInput; /* the number of bytes from the app */
296     DWORD appBytesToWrite; /* number of bytes from the app we are going to write */
297
298     long written = 0;
299     char* buffer;
300
301 #if JACK_CLOSE_HACK
302     if(wwo->in_use == FALSE)
303     {
304       /* output silence if nothing is being outputted */
305       sample_silence_dS(out_l, nframes);
306       sample_silence_dS(out_r, nframes);
307
308       return 0;
309     }
310 #endif
311
312     TRACE("wwo.state == WINE_WS_PLAYING\n");
313
314     /* see if our buffer is large enough for the data we are writing */
315     /* ie. Buffer_size < (bytes we already wrote + bytes we are going to write in this loop) */
316     if(wwo->buffer_size < jackBytesAvailableThisCallback)
317     {
318       ERR("for some reason JACK_BufSize() didn't allocate enough memory\n");
319       ERR("allocated %ld bytes, need %ld bytes\n", wwo->buffer_size, 
320       jackBytesAvailableThisCallback);
321       LeaveCriticalSection(&wwo->access_crst);
322       return 0;
323     }
324
325     /* while we have jackBytesLeft and a wave header to be played */
326     while(jackBytesLeft && wwo->lpPlayPtr)
327     {
328       /* find the amount of audio to be played at this time */
329       bytesInput = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;
330       inputBytesAvailable = bytesInput;
331
332       /* calculate inputBytesAvailable based on audio format conversion */
333       if(wwo->format.wf.nChannels == 1)
334         inputBytesAvailable<<=1; /* multiply by two for mono->stereo conversion */
335
336       /* find the minimum of the inputBytesAvailable and the space available */
337       jackBytesToWrite = min(jackBytesLeft, inputBytesAvailable);
338
339       /* calculate appBytesToWrite based on audio format conversion */
340       appBytesToWrite = jackBytesToWrite;
341       if(wwo->format.wf.nChannels == 1)
342         appBytesToWrite>>=1; /* divide by two for stereo->mono conversion */
343
344       TRACE("jackBytesToWrite == %ld, appBytesToWrite == %ld\n", jackBytesToWrite, appBytesToWrite);
345
346       buffer = wwo->lpPlayPtr->lpData + wwo->dwPartialOffset;
347
348       /* convert from mono to stereo if necessary */
349       /* otherwise just memcpy to the output buffer */
350       if(wwo->format.wf.nChannels == 1)
351       {
352         sample_move_d16_d16((short*)wwo->sound_buffer +((jackBytesAvailableThisCallback - jackBytesLeft) / sizeof(short)),
353                  (short*)buffer, jackBytesToWrite, wwo->format.wf.nChannels);
354       } else /* just copy the memory over */
355       {
356         memcpy(wwo->sound_buffer + (jackBytesAvailableThisCallback - jackBytesLeft),
357                   buffer, jackBytesToWrite);
358       }
359
360       /* advance to the next wave header if possible, or advance pointer */
361       /* inside of the current header if we haven't completed it */
362       if(appBytesToWrite == bytesInput)
363       {
364         wodHelper_PlayPtrNext(wwo);            /* we wrote the whole waveheader, skip to the next one*/
365       }
366       else
367       {
368         wwo->dwPartialOffset+=appBytesToWrite; /* else advance by the bytes we took in to write */
369       }
370
371       written+=appBytesToWrite; /* add on what we wrote */
372       jackBytesLeft-=jackBytesToWrite; /* take away what was written in terms of output bytes */
373     }
374
375     wwo->tickCountMS = GetTickCount();    /* record the current time */
376     wwo->dwWrittenTotal+=written; /* update states on wave device */
377     wwo->dwPlayedTotal+=wwo->bytesInJack; /* we must have finished with the last bytes or we wouldn't be back inside of this callback again... */
378     wwo->bytesInJack = written; /* record the bytes inside of jack */
379
380     /* Now that we have finished filling the buffer either until it is full or until */
381     /* we have run out of application sound data to process, apply volume and output */
382     /* the audio to the jack server */
383
384     /* apply volume to the buffer */
385     /* NOTE: buffer_size >> 2 to convert from bytes to 16 bit stereo(32bit) samples */
386     volume_effect32(wwo->sound_buffer, (jackBytesAvailableThisCallback - jackBytesLeft)>>2, wwo->volume_left,
387         wwo->volume_right);
388
389     /* convert from stereo 16 bit to single channel 32 bit float */
390     /* for each jack server channel */
391     /* NOTE: we skip over two sample since we want to only get either the left or right channel */
392     sample_move_d16_s16(out_l, (short*)wwo->sound_buffer, (jackBytesAvailableThisCallback - jackBytesLeft)>>2, 2);
393     sample_move_d16_s16(out_r, (short*)wwo->sound_buffer + 1,
394         (jackBytesAvailableThisCallback - jackBytesLeft)>>2, 2);
395
396     /* see if we still have jackBytesLeft here, if we do that means that we
397     ran out of wave data to play and had a buffer underrun, fill in
398     the rest of the space with zero bytes */
399     if(jackBytesLeft)
400     {
401       ERR("buffer underrun of %ld bytes\n", jackBytesLeft);
402       sample_silence_dS(out_l + ((jackBytesAvailableThisCallback - jackBytesLeft) / sizeof(sample_t)), jackBytesLeft / sizeof(sample_t));
403       sample_silence_dS(out_r + ((jackBytesAvailableThisCallback - jackBytesLeft) / sizeof(sample_t)), jackBytesLeft / sizeof(sample_t));
404     }
405   }
406   else if(wwo->state == WINE_WS_PAUSED || 
407     wwo->state == WINE_WS_STOPPED ||
408     wwo->state == WINE_WS_CLOSED)
409   {
410       /* output silence if nothing is being outputted */
411       sample_silence_dS(out_l, nframes);
412       sample_silence_dS(out_r, nframes);
413   }
414
415   /* notify the client of completed wave headers */
416   wodHelper_NotifyCompletions(wwo, FALSE);
417
418   LeaveCriticalSection(&wwo->access_crst);
419
420   TRACE("ending\n");
421
422   return 0;
423 }
424
425 /******************************************************************
426  *              JACK_bufsize
427  *
428  *              Called whenever the jack server changes the the max number 
429  *              of frames passed to JACK_callback
430  */
431 int JACK_bufsize (nframes_t nframes, void *arg)
432 {
433   WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
434   DWORD buffer_required;
435   TRACE("the maximum buffer size is now %lu frames\n", nframes);
436
437   /* make sure the callback routine has adequate memory */
438     /* see if our buffer is large enough for the data we are writing */
439     /* ie. Buffer_size < (bytes we already wrote + bytes we are going to write in this loop) */
440   EnterCriticalSection(&wwo->access_crst);
441
442   buffer_required = sizeof(sample_t) * nframes;
443   if(wwo->buffer_size < buffer_required)
444   {
445     TRACE("expanding buffer from wwo->buffer_size == %ld, to %ld\n", 
446       wwo->buffer_size, buffer_required);
447     TRACE("GetProcessHeap() == %p\n", GetProcessHeap());
448     wwo->buffer_size = buffer_required;
449     wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, wwo->buffer_size);
450
451     /* if we don't have a buffer then error out */
452     if(!wwo->sound_buffer)
453     {
454         ERR("error allocating sound_buffer memory\n");
455         LeaveCriticalSection(&wwo->access_crst);
456         return 0;
457     }
458   }
459
460   LeaveCriticalSection(&wwo->access_crst);
461
462   TRACE("called\n");
463
464   return 0;
465 }
466
467 /******************************************************************
468  *              JACK_srate
469  */
470 int JACK_srate (nframes_t nframes, void *arg)
471 {
472   TRACE("the sample rate is now %lu/sec\n", nframes);
473   return 0;
474 }
475
476
477 /******************************************************************
478  *              JACK_shutdown
479  */
480 /* if this is called then jack shut down... handle this appropriately */
481 void JACK_shutdown(void* arg)
482 {
483   WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
484
485   wwo->client = 0; /* reset client */
486
487   TRACE("trying to reconnect after sleeping for a short while...\n");
488   
489   /* lets see if we can't reestablish the connection */
490   Sleep(750); /* pause for a short period of time */
491   if(!JACK_OpenDevice(wwo))
492   {
493     ERR("unable to reconnect with jack...\n");
494   }
495 }
496
497
498 /******************************************************************
499  *              JACK_OpenDevice
500  */
501 static int JACK_OpenDevice(WINE_WAVEOUT* wwo)
502 {
503   const char** ports;
504   int i;
505   char client_name[64];
506   jack_port_t* out_port_l;
507   jack_port_t* out_port_r;
508   jack_client_t* client;
509   int failed = 0;
510
511   TRACE("creating jack client and setting up callbacks\n");
512
513 #if JACK_CLOSE_HACK
514   /* see if this device is already open */
515         if(wwo->client)
516         {
517           /* if this device is already in use then it is bad for us to be in here */
518           if(wwo->in_use)
519             return 0;
520
521           TRACE("using existing client\n");
522           wwo->in_use = TRUE;
523           return 1;
524         }
525 #endif
526
527         /* zero out the buffer pointer and the size of the buffer */
528         wwo->sound_buffer = 0;
529         wwo->buffer_size = 0;
530
531         /* try to become a client of the JACK server */
532         snprintf(client_name, sizeof(client_name), "wine_jack_client %d", wwo->wDevID);
533         TRACE("client name '%s'\n", client_name);
534         if ((client = fp_jack_client_new (client_name)) == 0)
535         {
536                 /* jack has problems with shutting down clients, so lets */
537                 /* wait a short while and try once more before we give up */
538                 Sleep(250);
539                 if ((client = fp_jack_client_new (client_name)) == 0)
540                 {
541                   ERR("jack server not running?\n");
542                   return 0;
543                 }
544         }
545                 
546         /* tell the JACK server to call `JACK_callback()' whenever
547            there is work to be done. */
548         fp_jack_set_process_callback (client, JACK_callback, wwo);
549         
550         /* tell the JACK server to call `JACK_bufsize()' whenever   
551            the maximum number of frames that will be passed
552            to `JACK_Callback()' changes */
553         fp_jack_set_buffer_size_callback (client, JACK_bufsize, wwo);
554           
555         /* tell the JACK server to call `srate()' whenever
556            the sample rate of the system changes. */
557         fp_jack_set_sample_rate_callback (client, JACK_srate, wwo);
558
559         /* tell the JACK server to call `jack_shutdown()' if
560            it ever shuts down, either entirely, or if it
561            just decides to stop calling us. */
562         fp_jack_on_shutdown (client, JACK_shutdown, wwo);
563         
564         /* display the current sample rate. once the client is activated
565            (see below), you should rely on your own sample rate
566            callback (see above) for this value. */
567         wwo->sample_rate = fp_jack_get_sample_rate(client);
568         TRACE("engine sample rate: %lu\n", wwo->sample_rate);
569           
570         /* create the left and right channel output ports */
571         /* jack's ports are all mono so for stereo you need two */
572         out_port_l = fp_jack_port_register (client, "out_l",
573                          JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
574
575         out_port_r = fp_jack_port_register (client, "out_r",
576                          JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
577
578         /* save away important values to the WINE_WAVEOUT struct */
579         wwo->client = client;
580         wwo->out_port_l = out_port_l;
581         wwo->out_port_r = out_port_r;
582
583 #if JACK_CLOSE_HACK
584         wwo->in_use = TRUE; /* mark this device as in use since it now is ;-) */
585 #endif
586
587         /* tell the JACK server that we are ready to roll */
588         if (fp_jack_activate (client))
589         {
590           ERR( "cannot activate client\n");
591           return 0;
592         }
593
594         /* figure out what the ports that we want to output on are */
595         /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
596         /*   this way works if names are changed */
597         ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
598
599         /* display a trace of the output ports we found */
600         for(i = 0; ports[i]; i++)
601         {
602           TRACE("ports[%d] = '%s'\n", i, ports[i]);
603         }
604
605         if(!ports)
606         {
607           ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsInput'\n");
608         }
609
610         /* connect the ports. Note: you can't do this before
611            the client is activated (this may change in the future).
612         */ 
613         /* we want to connect to two ports so we have stereo output ;-) */
614
615         if(fp_jack_connect(client, fp_jack_port_name(out_port_l), ports[0]))
616         {
617           ERR ("cannot connect to output port %d('%s')\n", 0, ports[0]);
618           failed = 1;
619         }
620
621         if(fp_jack_connect(client, fp_jack_port_name(out_port_r), ports[1]))
622         {
623           ERR ("cannot connect to output port %d('%s')\n", 1, ports[1]);
624           failed = 1;
625         }
626
627         free(ports); /* free the returned array of ports */
628
629         /* if something failed we need to shut the client down and return 0 */
630         if(failed)
631         {
632           JACK_CloseDevice(wwo, TRUE);
633           return 0;
634         }
635
636         return 1; /* return success */
637 }
638
639 /******************************************************************
640  *              JACK_CloseDevice
641  *
642  *      Close the connection to the server cleanly.
643  *  If close_client is TRUE we close the client for this device instead of
644  *    just marking the device as in_use(JACK_CLOSE_HACK only)
645  */
646 #if JACK_CLOSE_HACK
647 static void     JACK_CloseDevice(WINE_WAVEOUT* wwo, BOOL close_client)
648 #else
649 static void     JACK_CloseDevice(WINE_WAVEOUT* wwo)
650 #endif
651 {
652 #if JACK_CLOSE_HACK
653   TRACE("wDevID: %d, close_client: %d\n", wwo->wDevID, close_client);
654 #else
655   TRACE("wDevID: %d\n", wwo->wDevID);
656 #endif
657
658 #if JACK_CLOSE_HACK
659   if(close_client)
660   {
661 #endif
662     fp_jack_deactivate(wwo->client); /* supposed to help the jack_client_close() to succeed */
663     fp_jack_client_close (wwo->client);
664
665     EnterCriticalSection(&wwo->access_crst);
666     wwo->client = 0; /* reset client */
667     HeapFree(GetProcessHeap(), 0, wwo->sound_buffer); /* free buffer memory */
668     wwo->sound_buffer = 0;
669     wwo->buffer_size = 0; /* zero out size of the buffer */
670     LeaveCriticalSection(&wwo->access_crst);
671 #if JACK_CLOSE_HACK
672   } else
673   {
674     EnterCriticalSection(&wwo->access_crst);
675     TRACE("setting in_use to FALSE\n");
676     wwo->in_use = FALSE;
677     LeaveCriticalSection(&wwo->access_crst);
678   }
679 #endif
680 }
681
682 /******************************************************************
683  *              JACK_WaveRelease
684  *
685  *
686  */
687 LONG    JACK_WaveRelease(void)
688
689   int iDevice;
690
691   TRACE("closing all open devices\n");
692
693   /* close all open devices */
694   for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
695   {
696     TRACE("iDevice == %d\n", iDevice);
697     if(WOutDev[iDevice].client)
698     {
699 #if JACK_CLOSE_HACK
700       JACK_CloseDevice(&WOutDev[iDevice], TRUE); /* close the device, FORCE the client to close */
701 #else
702       JACK_CloseDevice(&WOutDev[iDevice]); /* close the device, FORCE the client to close */
703 #endif
704       DeleteCriticalSection(&(WOutDev[iDevice].access_crst)); /* delete the critical section */
705     }
706   }
707
708   TRACE("returning 1\n");
709
710   return 1;
711 }
712
713 /******************************************************************
714  *              JACK_WaveInit
715  *
716  * Initialize internal structures from JACK server info
717  */
718 LONG JACK_WaveInit(void)
719 {
720     int i;
721
722     TRACE("called\n");
723
724     /* setup function pointers */
725 #define LOAD_FUNCPTR(f) if((fp_##f = wine_dlsym(jackhandle, #f, NULL, 0)) == NULL) goto sym_not_found;    
726     LOAD_FUNCPTR(jack_activate);
727     LOAD_FUNCPTR(jack_connect);
728     LOAD_FUNCPTR(jack_client_new);
729     LOAD_FUNCPTR(jack_client_close);
730     LOAD_FUNCPTR(jack_deactivate);
731     LOAD_FUNCPTR(jack_set_process_callback);
732     LOAD_FUNCPTR(jack_set_buffer_size_callback);
733     LOAD_FUNCPTR(jack_set_sample_rate_callback);
734     LOAD_FUNCPTR(jack_on_shutdown);
735     LOAD_FUNCPTR(jack_get_sample_rate);
736     LOAD_FUNCPTR(jack_port_register);
737     LOAD_FUNCPTR(jack_port_get_buffer);
738     LOAD_FUNCPTR(jack_get_ports);
739     LOAD_FUNCPTR(jack_port_name);
740 #undef LOAD_FUNCPTR
741
742     /* start with output device */
743
744     for (i = 0; i < MAX_WAVEOUTDRV; ++i)
745     {
746       WOutDev[i].client = 0; /* initialize the client to 0 */
747
748 #if JACK_CLOSE_HACK
749       WOutDev[i].in_use = FALSE;
750 #endif
751
752       memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps));
753
754       /* FIXME: some programs compare this string against the content of the registry
755        * for MM drivers. The names have to match in order for the program to work 
756        * (e.g. MS win9x mplayer.exe)
757        */
758 #ifdef EMULATE_SB16
759       WOutDev[i].caps.wMid = 0x0002;
760       WOutDev[i].caps.wPid = 0x0104;
761       strcpy(WOutDev[i].caps.szPname, "SB16 Wave Out");
762 #else
763       WOutDev[i].caps.wMid = 0x00FF;    /* Manufac ID */
764       WOutDev[i].caps.wPid = 0x0001;    /* Product ID */
765       /*    strcpy(WOutDev[i].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/
766       strcpy(WOutDev[i].caps.szPname, "CS4236/37/38");
767 #endif
768       WOutDev[i].caps.vDriverVersion = 0x0100;
769       WOutDev[i].caps.dwFormats = 0x00000000;
770       WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
771     
772       WOutDev[i].caps.wChannels = 2;
773       WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;
774
775 /* NOTE: we don't support any 8 bit modes so note that */
776 /*      WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
777       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
778       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
779       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
780 /*      WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
781       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
782       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
783       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
784 /*      WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
785       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
786       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
787       WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
788     }
789
790     /* then do input device */
791     for (i = 0; i < MAX_WAVEINDRV; ++i)
792     {
793       /* TODO: we should initialize read stuff here */
794       memset(&WInDev[0].caps, 0, sizeof(WInDev[0].caps));
795     }
796     
797     return 1;           /* return success */
798
799 /* error path for function pointer loading errors */
800 sym_not_found:
801     WINE_MESSAGE(
802       "Wine cannot find certain functions that it needs inside the jack"
803       "library.  To enable Wine to use the jack audio server please "
804       "install libjack\n");
805     wine_dlclose(jackhandle, NULL, 0);
806     jackhandle = NULL;
807     return FALSE;
808 }
809
810 /*======================================================================*
811  *                  Low level WAVE OUT implementation                   *
812  *======================================================================*/
813
814 /**************************************************************************
815  *                      wodNotifyClient                 [internal]
816  */
817 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
818 {
819     TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
820     
821     switch (wMsg) {
822     case WOM_OPEN:
823     case WOM_CLOSE:
824     case WOM_DONE:
825       if (wwo->wFlags != DCB_NULL &&
826         !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags,
827           (HDRVR)wwo->waveDesc.hWave, wMsg, wwo->waveDesc.dwInstance,
828           dwParam1, dwParam2))
829       {
830         WARN("can't notify client !\n");
831         return MMSYSERR_ERROR;
832       }
833     break;
834     default:
835       FIXME("Unknown callback message %u\n", wMsg);
836         return MMSYSERR_INVALPARAM;
837     }
838     return MMSYSERR_NOERROR;
839 }
840
841 /**************************************************************************
842  *                              wodHelper_BeginWaveHdr          [internal]
843  *
844  * Makes the specified lpWaveHdr the currently playing wave header.
845  * If the specified wave header is a begin loop and we're not already in
846  * a loop, setup the loop.
847  */
848 static void wodHelper_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
849 {
850     EnterCriticalSection(&wwo->access_crst);
851
852     wwo->lpPlayPtr = lpWaveHdr;
853
854     if (!lpWaveHdr)
855     {
856        LeaveCriticalSection(&wwo->access_crst);
857        return;
858     }
859
860     if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)
861     {
862       if (wwo->lpLoopPtr)
863       {
864         WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
865         TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
866       } else
867       {
868         TRACE("Starting loop (%ldx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
869         wwo->lpLoopPtr = lpWaveHdr;
870         /* Windows does not touch WAVEHDR.dwLoops,
871          * so we need to make an internal copy */
872         wwo->dwLoops = lpWaveHdr->dwLoops;
873       }
874     }
875     wwo->dwPartialOffset = 0;
876
877     LeaveCriticalSection(&wwo->access_crst);
878 }
879
880
881 /**************************************************************************
882  *                              wodHelper_PlayPtrNext           [internal]
883  *
884  * Advance the play pointer to the next waveheader, looping if required.
885  */
886 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
887 {
888   LPWAVEHDR lpWaveHdr;
889
890   EnterCriticalSection(&wwo->access_crst);
891
892   lpWaveHdr = wwo->lpPlayPtr;
893
894   wwo->dwPartialOffset = 0;
895   if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr)
896   {
897     /* We're at the end of a loop, loop if required */
898     if (--wwo->dwLoops > 0)
899     {
900       wwo->lpPlayPtr = wwo->lpLoopPtr;
901     } else
902     {
903       /* Handle overlapping loops correctly */
904       if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
905         FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
906         /* shall we consider the END flag for the closing loop or for
907          * the opening one or for both ???
908          * code assumes for closing loop only
909          */
910       } else
911       {
912         lpWaveHdr = lpWaveHdr->lpNext;
913       }
914       wwo->lpLoopPtr = NULL;
915       wodHelper_BeginWaveHdr(wwo, lpWaveHdr);
916     }
917   } else
918   {
919      /* We're not in a loop.  Advance to the next wave header */
920     TRACE("not inside of a loop, advancing to next wave header\n");
921     wodHelper_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
922   }
923
924   LeaveCriticalSection(&wwo->access_crst);
925
926   return lpWaveHdr;
927 }
928
929 /* if force is TRUE then notify the client that all the headers were completed */
930 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
931 {
932   LPWAVEHDR             lpWaveHdr;
933   DWORD retval;
934
935   TRACE("called\n");
936
937   EnterCriticalSection(&wwo->access_crst);
938
939   /* Start from lpQueuePtr and keep notifying until:
940    * - we hit an unwritten wavehdr
941    * - we hit the beginning of a running loop
942    * - we hit a wavehdr which hasn't finished playing
943    */
944   while ((lpWaveHdr = wwo->lpQueuePtr) &&
945            (force || 
946             (lpWaveHdr != wwo->lpPlayPtr &&
947              lpWaveHdr != wwo->lpLoopPtr)))
948   {
949     wwo->lpQueuePtr = lpWaveHdr->lpNext;
950
951     lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
952     lpWaveHdr->dwFlags |= WHDR_DONE;
953     TRACE("calling notify client\n");
954
955     wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
956   }
957
958   retval = (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr != 
959               wwo->lpLoopPtr) ? 0 : INFINITE;
960
961   LeaveCriticalSection(&wwo->access_crst);
962
963   return retval;
964 }
965
966 /**************************************************************************
967  *                              wodHelper_Reset                 [internal]
968  *
969  * Resets current output stream.
970  */
971 static  void  wodHelper_Reset(WINE_WAVEOUT* wwo, BOOL reset)
972 {
973     EnterCriticalSection(&wwo->access_crst);
974  
975     /* updates current notify list */
976     wodHelper_NotifyCompletions(wwo, FALSE);
977
978     if (reset)
979     {
980         /* remove all wave headers and notify client that all headers were completed */
981         wodHelper_NotifyCompletions(wwo, TRUE);
982
983         wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
984         wwo->state = WINE_WS_STOPPED;
985         wwo->dwPlayedTotal = wwo->dwWrittenTotal = wwo->bytesInJack = 0;
986
987         wwo->dwPartialOffset = 0;        /* Clear partial wavehdr */
988     } else
989     {
990         if (wwo->lpLoopPtr)
991         {
992             /* complicated case, not handled yet (could imply modifying the loop counter) */
993             FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
994             wwo->lpPlayPtr = wwo->lpLoopPtr;
995             wwo->dwPartialOffset = 0;
996             wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
997         } else
998         {
999             LPWAVEHDR   ptr;
1000             DWORD       sz = wwo->dwPartialOffset;
1001
1002             /* reset all the data as if we had written only up to lpPlayedTotal bytes */
1003             /* compute the max size playable from lpQueuePtr */
1004             for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext)
1005             {
1006                 sz += ptr->dwBufferLength;
1007             }
1008
1009             /* because the reset lpPlayPtr will be lpQueuePtr */
1010             if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("doh\n");
1011             wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal);
1012             wwo->dwWrittenTotal = wwo->dwPlayedTotal;
1013             wwo->lpPlayPtr = wwo->lpQueuePtr;
1014         }
1015
1016         wwo->state = WINE_WS_PAUSED;
1017     }
1018  
1019     LeaveCriticalSection(&wwo->access_crst);
1020 }
1021
1022 /**************************************************************************
1023  *                      wodGetDevCaps                           [internal]
1024  */
1025 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSA lpCaps, DWORD dwSize)
1026 {
1027     TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1028     
1029     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1030     
1031     if (wDevID >= MAX_WAVEOUTDRV)
1032     {
1033       TRACE("MAX_WAVOUTDRV reached !\n");
1034       return MMSYSERR_BADDEVICEID;
1035     }
1036
1037     memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1038     return MMSYSERR_NOERROR;
1039 }
1040
1041 /**************************************************************************
1042  *                              wodOpen                         [internal]
1043  */
1044 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1045 {
1046     WINE_WAVEOUT*       wwo;
1047     DWORD retval;
1048
1049     TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1050     if (lpDesc == NULL)
1051     {
1052       WARN("Invalid Parameter !\n");
1053       return MMSYSERR_INVALPARAM;
1054     }
1055     if (wDevID >= MAX_WAVEOUTDRV) {
1056       TRACE("MAX_WAVOUTDRV reached !\n");
1057       return MMSYSERR_BADDEVICEID;
1058     }
1059
1060 #if JACK_CLOSE_HACK
1061     if(WOutDev[wDevID].client && WOutDev[wDevID].in_use)
1062 #else
1063     if(WOutDev[wDevID].client)
1064 #endif
1065     {
1066       TRACE("device %d already allocated\n", wDevID);
1067       return MMSYSERR_ALLOCATED;
1068     }
1069
1070     /* make sure we aren't being opened in 8 bit mode */
1071     if(lpDesc->lpFormat->wBitsPerSample == 8)
1072     {
1073       TRACE("8bits per sample unsupported, returning WAVERR_BADFORMAT\n");
1074       return WAVERR_BADFORMAT;
1075     }
1076
1077     wwo = &WOutDev[wDevID];
1078     wwo->wDevID = wDevID;
1079
1080     /* Set things up before we call JACK_OpenDevice because */
1081     /* we will start getting callbacks before JACK_OpenDevice */
1082     /* even returns and we want to be initialized before then */
1083     wwo->state = WINE_WS_STOPPED; /* start in a stopped state */
1084     wwo->dwPlayedTotal = 0; /* zero out these totals */
1085     wwo->dwWrittenTotal = 0;
1086     wwo->bytesInJack = 0;
1087     wwo->tickCountMS = 0;
1088
1089     InitializeCriticalSection(&wwo->access_crst); /* initialize the critical section */
1090
1091     /* open up jack ports for this device */
1092     if (!JACK_OpenDevice(&WOutDev[wDevID]))
1093     {
1094       ERR("JACK_OpenDevice(%d) failed\n", wDevID);
1095       return MMSYSERR_ERROR;            /* return unspecified error */
1096     }
1097
1098     /* only PCM format is supported so far... */
1099     if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1100       lpDesc->lpFormat->nChannels == 0 ||
1101       lpDesc->lpFormat->nSamplesPerSec == 0)
1102     {
1103       WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1104        lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1105        lpDesc->lpFormat->nSamplesPerSec);
1106       return WAVERR_BADFORMAT;
1107     }
1108
1109     if (dwFlags & WAVE_FORMAT_QUERY)
1110     {
1111       TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1112        lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1113        lpDesc->lpFormat->nSamplesPerSec);
1114       return MMSYSERR_NOERROR;
1115     }
1116
1117     dwFlags &= ~WAVE_DIRECTSOUND;  /* direct sound not supported, ignore the flag */
1118
1119     EnterCriticalSection(&wwo->access_crst);
1120
1121     wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1122     
1123     memcpy(&wwo->waveDesc, lpDesc,           sizeof(WAVEOPENDESC));
1124     memcpy(&wwo->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1125
1126     LeaveCriticalSection(&wwo->access_crst);
1127
1128     /* display the current wave format */
1129     TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n", 
1130     wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
1131     wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1132     wwo->format.wf.nBlockAlign);
1133
1134     /* make sure that we have the same sample rate in our audio stream */
1135     /* as we do in the jack server */
1136     if(wwo->format.wf.nSamplesPerSec != wwo->sample_rate)
1137     {
1138       TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
1139          wwo->sample_rate, wwo->format.wf.nSamplesPerSec);
1140
1141 #if JACK_CLOSE_HACK
1142       JACK_CloseDevice(wwo, FALSE); /* close this device, don't force the client to close */
1143 #else
1144       JACK_CloseDevice(wwo); /* close this device */
1145 #endif
1146       return WAVERR_BADFORMAT;
1147     }
1148
1149     /* check for an invalid number of bits per sample */
1150     if (wwo->format.wBitsPerSample == 0)
1151     {
1152       WARN("Resetting zeroed wBitsPerSample to 16\n");
1153       wwo->format.wBitsPerSample = 16 *
1154       (wwo->format.wf.nAvgBytesPerSec /
1155        wwo->format.wf.nSamplesPerSec) /
1156        wwo->format.wf.nChannels;
1157     }
1158
1159     EnterCriticalSection(&wwo->access_crst);
1160     retval = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
1161     LeaveCriticalSection(&wwo->access_crst);
1162
1163     return retval;
1164 }
1165
1166 /**************************************************************************
1167  *                              wodClose                        [internal]
1168  */
1169 static DWORD wodClose(WORD wDevID)
1170 {
1171     DWORD               ret = MMSYSERR_NOERROR;
1172     WINE_WAVEOUT*       wwo;
1173
1174     TRACE("(%u);\n", wDevID);
1175
1176     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1177     {
1178       WARN("bad device ID !\n");
1179       return MMSYSERR_BADDEVICEID;
1180     }
1181     
1182     wwo = &WOutDev[wDevID];
1183     if (wwo->lpQueuePtr)
1184     {
1185       WARN("buffers still playing !\n");
1186       ret = WAVERR_STILLPLAYING;
1187     } else
1188     {
1189       /* sanity check: this should not happen since the device must have been reset before */
1190       if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
1191
1192       wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
1193
1194 #if JACK_CLOSE_HACK
1195       JACK_CloseDevice(wwo, FALSE); /* close the jack device, DO NOT force the client to close */
1196 #else
1197       JACK_CloseDevice(wwo); /* close the jack device */
1198       DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1199 #endif
1200
1201       ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
1202     }
1203
1204     return ret;
1205 }
1206
1207 /**************************************************************************
1208  *                              wodWrite                        [internal]
1209  * 
1210  */
1211 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1212 {
1213     LPWAVEHDR*wh;
1214     WINE_WAVEOUT *wwo;
1215
1216     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1217     
1218     /* first, do the sanity checks... */
1219     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1220     {
1221       WARN("bad dev ID !\n");
1222       return MMSYSERR_BADDEVICEID;
1223     }
1224
1225     wwo = &WOutDev[wDevID];
1226
1227     if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1228     {
1229       TRACE("unprepared\n");
1230       return WAVERR_UNPREPARED;
1231     }
1232     
1233     if (lpWaveHdr->dwFlags & WHDR_INQUEUE) 
1234     {
1235       TRACE("still playing\n");
1236       return WAVERR_STILLPLAYING;
1237     }
1238
1239     lpWaveHdr->dwFlags &= ~WHDR_DONE;
1240     lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1241     lpWaveHdr->lpNext = 0;
1242
1243     EnterCriticalSection(&wwo->access_crst);
1244
1245     /* insert buffer at the end of queue */
1246     for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
1247     *wh = lpWaveHdr;
1248
1249     LeaveCriticalSection(&wwo->access_crst);
1250
1251     EnterCriticalSection(&wwo->access_crst);
1252     if (!wwo->lpPlayPtr)
1253       wodHelper_BeginWaveHdr(wwo,lpWaveHdr);
1254     if (wwo->state == WINE_WS_STOPPED)
1255       wwo->state = WINE_WS_PLAYING;
1256     LeaveCriticalSection(&wwo->access_crst);
1257
1258     return MMSYSERR_NOERROR;
1259 }
1260
1261 /**************************************************************************
1262  *                              wodPrepare                      [internal]
1263  */
1264 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1265 {
1266   TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1267     
1268   if (wDevID >= MAX_WAVEOUTDRV)
1269   {
1270     WARN("bad device ID !\n");
1271     return MMSYSERR_BADDEVICEID;
1272   }
1273     
1274   if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1275     return WAVERR_STILLPLAYING;
1276     
1277   lpWaveHdr->dwFlags |= WHDR_PREPARED;
1278   lpWaveHdr->dwFlags &= ~WHDR_DONE;
1279   return MMSYSERR_NOERROR;
1280 }
1281
1282 /**************************************************************************
1283  *                              wodUnprepare                    [internal]
1284  */
1285 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1286 {
1287   TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1288     
1289   if (wDevID >= MAX_WAVEOUTDRV)
1290   {
1291     WARN("bad device ID !\n");
1292     return MMSYSERR_BADDEVICEID;
1293   }
1294     
1295   if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1296     return WAVERR_STILLPLAYING;
1297     
1298   lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1299   lpWaveHdr->dwFlags |= WHDR_DONE;
1300     
1301   return MMSYSERR_NOERROR;
1302 }
1303
1304 /**************************************************************************
1305  *                      wodPause                                [internal]
1306  */
1307 static DWORD wodPause(WORD wDevID)
1308 {
1309   TRACE("(%u);!\n", wDevID);
1310     
1311   if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1312   {
1313     WARN("bad device ID !\n");
1314     return MMSYSERR_BADDEVICEID;
1315   }
1316     
1317   TRACE("[3-PAUSING]\n");
1318
1319   EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1320   wodHelper_Reset(&WOutDev[wDevID], FALSE);
1321   LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1322
1323   return MMSYSERR_NOERROR;
1324 }
1325
1326 /**************************************************************************
1327  *                      wodRestart                              [internal]
1328  */
1329 static DWORD wodRestart(WORD wDevID)
1330 {
1331     TRACE("(%u);\n", wDevID);
1332
1333     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1334     {
1335       WARN("bad device ID !\n");
1336       return MMSYSERR_BADDEVICEID;
1337     }
1338
1339     if (WOutDev[wDevID].state == WINE_WS_PAUSED)
1340     {
1341       EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1342       WOutDev[wDevID].state = WINE_WS_PLAYING;
1343       LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1344     }
1345     
1346     return MMSYSERR_NOERROR;
1347 }
1348
1349 /**************************************************************************
1350  *                      wodReset                                [internal]
1351  */
1352 static DWORD wodReset(WORD wDevID)
1353 {
1354     TRACE("(%u);\n", wDevID);
1355     
1356     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1357     {
1358       WARN("bad device ID !\n");
1359       return MMSYSERR_BADDEVICEID;
1360     }
1361
1362     EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1363     wodHelper_Reset(&WOutDev[wDevID], TRUE);
1364     LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1365
1366     return MMSYSERR_NOERROR;
1367 }
1368
1369 /**************************************************************************
1370  *                              wodGetPosition                  [internal]
1371  */
1372 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1373 {
1374     int                 time;
1375     DWORD               val;
1376     WINE_WAVEOUT*       wwo;
1377     DWORD elapsedMS;
1378
1379     TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1380     
1381     if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1382     {
1383       WARN("bad device ID !\n");
1384       return MMSYSERR_BADDEVICEID;
1385     }
1386     
1387     /* if null pointer to time structure return error */
1388     if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1389
1390     wwo = &WOutDev[wDevID];
1391
1392     EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1393     val = wwo->dwPlayedTotal;
1394     elapsedMS = GetTickCount() - wwo->tickCountMS;
1395     LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1396
1397     /* account for the bytes played since the last JACK_Callback() */
1398     val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
1399
1400     TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n", 
1401       lpTime->wType, wwo->format.wBitsPerSample,
1402       wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1403       wwo->format.wf.nAvgBytesPerSec);
1404     TRACE("dwPlayedTotal=%lu\n", val);
1405     
1406     switch (lpTime->wType) {
1407     case TIME_BYTES:
1408       lpTime->u.cb = val;
1409       TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
1410       break;
1411     case TIME_SAMPLES:
1412       lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
1413       TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
1414       break;
1415     case TIME_SMPTE:
1416       time = val / (wwo->format.wf.nAvgBytesPerSec / 1000);
1417       lpTime->u.smpte.hour = time / 108000;
1418       time -= lpTime->u.smpte.hour * 108000;
1419       lpTime->u.smpte.min = time / 1800;
1420       time -= lpTime->u.smpte.min * 1800;
1421       lpTime->u.smpte.sec = time / 30;
1422       time -= lpTime->u.smpte.sec * 30;
1423       lpTime->u.smpte.frame = time;
1424       lpTime->u.smpte.fps = 30;
1425       TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1426         lpTime->u.smpte.hour, lpTime->u.smpte.min,
1427         lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1428       break;
1429     default:
1430       FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
1431       lpTime->wType = TIME_MS;
1432     case TIME_MS:
1433       lpTime->u.ms = val / (wwo->format.wf.nAvgBytesPerSec / 1000);
1434       TRACE("TIME_MS=%lu\n", lpTime->u.ms);
1435       break;
1436     }
1437     return MMSYSERR_NOERROR;
1438 }
1439
1440 /**************************************************************************
1441  *                              wodBreakLoop                    [internal]
1442  */
1443 static DWORD wodBreakLoop(WORD wDevID)
1444 {
1445   TRACE("(%u);\n", wDevID);
1446
1447   if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1448   {
1449     WARN("bad device ID !\n");
1450     return MMSYSERR_BADDEVICEID;
1451   }
1452
1453   EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1454
1455   if (WOutDev[wDevID].state == WINE_WS_PLAYING && WOutDev[wDevID].lpLoopPtr != NULL)
1456   {
1457     /* ensure exit at end of current loop */
1458     WOutDev[wDevID].dwLoops = 1;
1459   }
1460
1461   LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1462
1463   return MMSYSERR_NOERROR;
1464 }
1465     
1466 /**************************************************************************
1467  *                              wodGetVolume                    [internal]
1468  */
1469 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1470 {
1471   DWORD left, right;
1472     
1473   left = WOutDev[wDevID].volume_left;
1474   right = WOutDev[wDevID].volume_right;
1475         
1476   TRACE("(%u, %p);\n", wDevID, lpdwVol);
1477  
1478   *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
1479               16);
1480     
1481   return MMSYSERR_NOERROR;
1482 }
1483
1484 /**************************************************************************
1485  *                              wodSetVolume                    [internal]
1486  */
1487 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1488 {
1489   DWORD left, right;
1490  
1491   left  = (LOWORD(dwParam) * 100) / 0xFFFFl;
1492   right = (HIWORD(dwParam) * 100) / 0xFFFFl;
1493  
1494   TRACE("(%u, %08lX);\n", wDevID, dwParam);
1495
1496   EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1497
1498   WOutDev[wDevID].volume_left = left;
1499   WOutDev[wDevID].volume_right = right;
1500
1501   LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1502
1503   return MMSYSERR_NOERROR;
1504 }
1505
1506 /**************************************************************************
1507  *                              wodGetNumDevs                   [internal]
1508  */
1509 static DWORD wodGetNumDevs(void)
1510 {
1511   return MAX_WAVEOUTDRV;
1512 }
1513
1514 /**************************************************************************
1515  *                              wodMessage (WINEJACK.7)
1516  */
1517 DWORD WINAPI JACK_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser, 
1518                             DWORD dwParam1, DWORD dwParam2)
1519 {
1520   TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
1521   wDevID, wMsg, dwUser, dwParam1, dwParam2);
1522     
1523   switch (wMsg) {
1524   case DRVM_INIT:
1525     TRACE("DRVM_INIT\n");
1526     return JACK_WaveInit();
1527   case DRVM_EXIT:
1528     TRACE("DRVM_EXIT\n");
1529     return JACK_WaveRelease();
1530   case DRVM_ENABLE:
1531   /* FIXME: Pretend this is supported */
1532     TRACE("DRVM_ENABLE\n");
1533     return 0;
1534   case DRVM_DISABLE:
1535   /* FIXME: Pretend this is supported */
1536     TRACE("DRVM_DISABLE\n");
1537     return 0;
1538   case WODM_OPEN:             return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1,  dwParam2);
1539   case WODM_CLOSE:            return wodClose(wDevID);
1540   case WODM_WRITE:            return wodWrite(wDevID, (LPWAVEHDR)dwParam1,              dwParam2);
1541   case WODM_PAUSE:            return wodPause(wDevID);
1542   case WODM_GETPOS:           return wodGetPosition(wDevID, (LPMMTIME)dwParam1,                 dwParam2);
1543   case WODM_BREAKLOOP:        return wodBreakLoop(wDevID);
1544   case WODM_PREPARE:          return wodPrepare(wDevID, (LPWAVEHDR)dwParam1,            dwParam2);
1545   case WODM_UNPREPARE:        return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1,          dwParam2);
1546   case WODM_GETDEVCAPS:       return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSA)dwParam1,    dwParam2);
1547   case WODM_GETNUMDEVS:       return wodGetNumDevs();
1548   case WODM_GETPITCH:         return MMSYSERR_NOTSUPPORTED;
1549   case WODM_SETPITCH:         return MMSYSERR_NOTSUPPORTED;
1550   case WODM_GETPLAYBACKRATE:    return MMSYSERR_NOTSUPPORTED;
1551   case WODM_SETPLAYBACKRATE:    return MMSYSERR_NOTSUPPORTED;
1552   case WODM_GETVOLUME:        return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1553   case WODM_SETVOLUME:        return wodSetVolume(wDevID, dwParam1);
1554   case WODM_RESTART:          return wodRestart(wDevID);
1555   case WODM_RESET:            return wodReset(wDevID);
1556
1557   case DRV_QUERYDSOUNDIFACE:    return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1);
1558   default:
1559     FIXME("unknown message %d!\n", wMsg);
1560     }
1561     return MMSYSERR_NOTSUPPORTED;
1562 }
1563
1564 /*======================================================================*
1565  *                  Low level DSOUND implementation                     *
1566  *======================================================================*/
1567
1568 typedef struct IDsDriverImpl IDsDriverImpl;
1569 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;
1570
1571 struct IDsDriverImpl
1572 {
1573     /* IUnknown fields */
1574     ICOM_VFIELD(IDsDriver);
1575     DWORD               ref;
1576     /* IDsDriverImpl fields */
1577     UINT                wDevID;
1578     IDsDriverBufferImpl*primary;
1579 };
1580
1581 struct IDsDriverBufferImpl
1582 {
1583     /* IUnknown fields */
1584     ICOM_VFIELD(IDsDriverBuffer);
1585     DWORD ref;
1586     /* IDsDriverBufferImpl fields */
1587     IDsDriverImpl* drv;
1588     DWORD buflen;
1589 };
1590
1591 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
1592 {
1593     /* we can't perform memory mapping as we don't have a file stream 
1594       interface with jack like we do with oss */
1595     MESSAGE("This sound card's driver does not support direct access\n");
1596     MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
1597     return MMSYSERR_NOTSUPPORTED;
1598 }
1599
1600 /*======================================================================*
1601  *                  Low level WAVE IN implementation                    *
1602  *======================================================================*/
1603
1604 /**************************************************************************
1605  *                              widMessage (WINEJACK.6)
1606  */
1607 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
1608                             DWORD dwParam1, DWORD dwParam2)
1609 {
1610   TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
1611   wDevID, wMsg, dwUser, dwParam1, dwParam2);
1612
1613   return MMSYSERR_NOTSUPPORTED;
1614 }
1615
1616 #else /* !HAVE_JACK_JACK_H */
1617
1618 /**************************************************************************
1619  *                              wodMessage (WINEJACK.7)
1620  */
1621 DWORD WINAPI JACK_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
1622                             DWORD dwParam1, DWORD dwParam2)
1623 {
1624   FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
1625   return MMSYSERR_NOTENABLED;
1626 }
1627
1628 #endif /* HAVE_JACK_JACK_H */