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