d3dx9: Implement ID3DXBaseEffect::GetAnnotation().
[wine/multimedia.git] / dlls / winejack.drv / audio.c
blob5d339eeac820f7e333f4ffb55eba1b803a027904
1 /*
2 * Wine Driver for jack Sound Server
3 * http://jackit.sourceforge.net
5 * Copyright 1994 Martin Ayotte
6 * Copyright 1999 Eric Pouech (async playing in waveOut/waveIn)
7 * Copyright 2000 Eric Pouech (loops in waveOut)
8 * Copyright 2002 Chris Morgan (jack version of this file)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * TODO:
27 * implement audio stream resampling for any arbitrary frequenty
28 * right now we use the winmm layer to do resampling although it would
29 * be nice to have a full set of algorithms to choose from based on cpu
30 * time
32 * FIXME:
33 * pause in waveOut during loop is not handled correctly
36 #include "config.h"
37 #include "wine/port.h"
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <string.h>
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46 #include <fcntl.h>
47 #include "windef.h"
48 #include "winbase.h"
49 #include "winnls.h"
50 #include "wingdi.h"
51 #include "winuser.h"
52 #include "winerror.h"
53 #include "mmddk.h"
54 #include "dsound.h"
55 #include "dsdriver.h"
56 #include "wine/unicode.h"
57 #include "wine/library.h"
58 #include "wine/debug.h"
60 #ifdef HAVE_JACK_JACK_H
61 #include <jack/jack.h>
62 #endif
65 WINE_DEFAULT_DEBUG_CHANNEL(wave);
67 #define MAKE_FUNCPTR(f) static typeof(f) * fp_##f = NULL;
69 /* Function pointers for dynamic loading of libjack */
70 /* these are prefixed with "fp_", ie. "fp_jack_client_open" */
71 MAKE_FUNCPTR(jack_activate);
72 MAKE_FUNCPTR(jack_connect);
73 MAKE_FUNCPTR(jack_client_open);
74 MAKE_FUNCPTR(jack_client_close);
75 MAKE_FUNCPTR(jack_deactivate);
76 MAKE_FUNCPTR(jack_set_process_callback);
77 MAKE_FUNCPTR(jack_set_buffer_size_callback);
78 MAKE_FUNCPTR(jack_set_sample_rate_callback);
79 MAKE_FUNCPTR(jack_on_shutdown);
80 MAKE_FUNCPTR(jack_get_sample_rate);
81 MAKE_FUNCPTR(jack_port_register);
82 MAKE_FUNCPTR(jack_port_get_buffer);
83 MAKE_FUNCPTR(jack_get_ports);
84 MAKE_FUNCPTR(jack_port_name);
85 MAKE_FUNCPTR(jack_get_buffer_size);
86 #undef MAKE_FUNCPTR
88 static void *jackhandle;
90 /* define the below to work around a bug in jack where closing a port */
91 /* takes a very long time, so to get around this we actually don't */
92 /* close the port when the device is closed but instead mark the */
93 /* corresponding device as unused */
94 #define JACK_CLOSE_HACK 1
96 typedef jack_default_audio_sample_t sample_t;
97 typedef jack_nframes_t nframes_t;
99 /* only allow 10 output devices through this driver, this ought to be adequate */
100 #define MAX_WAVEOUTDRV (10)
101 #define MAX_WAVEINDRV (10)
103 /* state diagram for waveOut writing:
105 * +---------+-------------+---------------+---------------------------------+
106 * | state | function | event | new state |
107 * +---------+-------------+---------------+---------------------------------+
108 * | | open() | | STOPPED |
109 * | PAUSED | write() | | PAUSED |
110 * | STOPPED | write() | <thrd create> | PLAYING |
111 * | PLAYING | write() | HEADER | PLAYING |
112 * | (other) | write() | <error> | |
113 * | (any) | pause() | PAUSING | PAUSED |
114 * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
115 * | (any) | reset() | RESETTING | STOPPED |
116 * | (any) | close() | CLOSING | CLOSED |
117 * +---------+-------------+---------------+---------------------------------+
120 /* states of the playing device */
121 #define WINE_WS_PLAYING 0
122 #define WINE_WS_PAUSED 1
123 #define WINE_WS_STOPPED 2
124 #define WINE_WS_CLOSED 3
126 typedef struct {
127 volatile int state; /* one of the WINE_WS_ manifest constants */
128 WAVEOPENDESC waveDesc;
129 WORD wFlags;
130 PCMWAVEFORMAT format;
131 WAVEOUTCAPSW caps;
132 WORD wDevID;
133 char interface_name[32];
135 jack_port_t* out_port_l; /* ports for left and right channels */
136 jack_port_t* out_port_r;
137 jack_client_t* client;
138 long sample_rate; /* jack server sample rate */
140 #if JACK_CLOSE_HACK
141 BOOL in_use; /* TRUE if this device is in use */
142 #endif
144 char* sound_buffer;
145 unsigned long buffer_size;
147 DWORD volume_left;
148 DWORD volume_right;
150 LPWAVEHDR lpQueuePtr; /* start of queued WAVEHDRs (waiting to be notified) */
151 LPWAVEHDR lpPlayPtr; /* start of not yet fully played buffers */
152 DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
154 LPWAVEHDR lpLoopPtr; /* pointer of first buffer in loop, if any */
155 DWORD dwLoops; /* private copy of loop counter */
157 DWORD dwPlayedTotal; /* number of bytes actually played since opening */
158 DWORD dwWrittenTotal; /* number of bytes written to jack since opening */
160 DWORD bytesInJack; /* bytes that we wrote during the previous JACK_Callback() */
161 DWORD tickCountMS; /* time in MS of last JACK_Callback() */
163 /* synchronization stuff */
164 CRITICAL_SECTION access_crst;
165 } WINE_WAVEOUT;
167 typedef struct {
168 volatile int state;
169 WAVEOPENDESC waveDesc;
170 WORD wFlags;
171 PCMWAVEFORMAT format;
172 LPWAVEHDR lpQueuePtr;
173 DWORD dwTotalRecorded;
174 WAVEINCAPSW caps;
175 BOOL bTriggerSupport;
176 WORD wDevID;
177 char interface_name[32];
179 jack_port_t* in_port_l; /* ports for left and right channels */
180 jack_port_t* in_port_r;
181 jack_client_t* client;
182 long sample_rate; /* jack server sample rate */
184 #if JACK_CLOSE_HACK
185 BOOL in_use; /* TRUE if this device is in use */
186 #endif
188 char* sound_buffer;
189 unsigned long buffer_size;
191 /* synchronization stuff */
192 CRITICAL_SECTION access_crst;
193 } WINE_WAVEIN;
195 static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV];
196 static WINE_WAVEIN WInDev [MAX_WAVEINDRV ];
198 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
199 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
201 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo);
202 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force);
204 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo);
205 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels);
207 #if JACK_CLOSE_HACK
208 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client);
209 #else
210 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo);
211 #endif
213 #if JACK_CLOSE_HACK
214 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client);
215 #else
216 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi);
217 #endif
219 static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
220 PCMWAVEFORMAT* format)
222 TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%u nChannels=%u nAvgBytesPerSec=%u\n",
223 lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
224 format->wf.nChannels, format->wf.nAvgBytesPerSec);
225 TRACE("Position in bytes=%u\n", position);
227 switch (lpTime->wType) {
228 case TIME_SAMPLES:
229 lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
230 TRACE("TIME_SAMPLES=%u\n", lpTime->u.sample);
231 break;
232 case TIME_MS:
233 lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
234 TRACE("TIME_MS=%u\n", lpTime->u.ms);
235 break;
236 case TIME_SMPTE:
237 lpTime->u.smpte.fps = 30;
238 position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
239 position += (format->wf.nSamplesPerSec / lpTime->u.smpte.fps) - 1; /* round up */
240 lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
241 position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
242 lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
243 lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
244 lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
245 lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
246 lpTime->u.smpte.fps = 30;
247 lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
248 TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
249 lpTime->u.smpte.hour, lpTime->u.smpte.min,
250 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
251 break;
252 default:
253 WARN("Format %d not supported, using TIME_BYTES !\n", lpTime->wType);
254 lpTime->wType = TIME_BYTES;
255 /* fall through */
256 case TIME_BYTES:
257 lpTime->u.cb = position;
258 TRACE("TIME_BYTES=%u\n", lpTime->u.cb);
259 break;
261 return MMSYSERR_NOERROR;
265 /*======================================================================*
266 * Low level WAVE implementation *
267 *======================================================================*/
269 #define SAMPLE_MAX_16BIT 32767.0f
271 /* Alsaplayer function that applies volume changes to a buffer */
272 /* (C) Andy Lo A Foe */
273 /* Length is in terms of 32 bit samples */
274 static void volume_effect32(void *buffer, int length, int left, int right)
276 short *data = buffer;
277 int i, v;
279 if (right == -1) right = left;
281 for(i = 0; i < length; i++) {
282 v = (int) ((*(data) * left) / 100);
283 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
284 v = (int) ((*(data) * right) / 100);
285 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
289 /* move 16 bit mono/stereo to 16 bit stereo */
290 static void sample_move_d16_d16(short *dst, short *src,
291 unsigned long nsamples, int nChannels)
293 while(nsamples--)
295 *dst = *src;
296 dst++;
298 if(nChannels == 2) src++;
300 *dst = *src;
301 dst++;
303 src++;
307 /* convert from 16 bit to floating point */
308 /* allow for copying of stereo data with alternating left/right */
309 /* channels to a buffer that will hold a single channel stream */
310 /* nsamples is in terms of 16bit samples */
311 /* src_skip is in terms of 16bit samples */
312 static void sample_move_d16_s16 (sample_t *dst, short *src,
313 unsigned long nsamples, unsigned long src_skip)
315 /* ALERT: signed sign-extension portability !!! */
316 while (nsamples--)
318 *dst = (*src) / SAMPLE_MAX_16BIT;
319 dst++;
320 src += src_skip;
324 /* convert from floating point to 16 bit */
325 /* allow for copying of a buffer that will hold a single channel stream */
326 /* to stereo data with alternating left/right channels */
327 /* nsamples is in terms of float samples */
328 /* dst_skip is in terms of 16bit samples */
329 static void sample_move_s16_d16 (short *dst, sample_t *src,
330 unsigned long nsamples, unsigned long dst_skip)
332 /* ALERT: signed sign-extension portability !!! */
333 while (nsamples--)
335 *dst = (*src) * SAMPLE_MAX_16BIT;
336 /* TRACE("src=(%.8f,%p) dst=(%d,%p)\n",*src,src,*dst,dst); */
337 dst += dst_skip;
338 src++;
343 /* fill dst buffer with nsamples worth of silence */
344 static void sample_silence_dS (sample_t *dst, unsigned long nsamples)
346 /* ALERT: signed sign-extension portability !!! */
347 while (nsamples--)
349 *dst = 0;
350 dst++;
354 /******************************************************************
355 * JACK_callback_wwo
357 /* everytime the jack server wants something from us it calls this
358 function, so we either deliver it some sound to play or deliver it nothing
359 to play */
360 static int JACK_callback_wwo (nframes_t nframes, void *arg)
362 sample_t* out_l;
363 sample_t* out_r;
364 WINE_WAVEOUT* wwo = arg;
366 TRACE("wDevID: %u, nframes %u state=%u\n", wwo->wDevID, nframes,wwo->state);
368 if(!wwo->client)
369 ERR("client is closed, this is weird...\n");
371 out_l = fp_jack_port_get_buffer(wwo->out_port_l, nframes);
372 out_r = fp_jack_port_get_buffer(wwo->out_port_r, nframes);
374 if(wwo->state == WINE_WS_PLAYING)
376 DWORD jackFramesAvailable = nframes;
377 DWORD outputFramesAvailable;
378 DWORD numFramesToWrite;
380 long written = 0;
381 char* buffer;
383 #if JACK_CLOSE_HACK
384 if(wwo->in_use == FALSE)
386 /* output silence if nothing is being outputted */
387 sample_silence_dS(out_l, nframes);
388 sample_silence_dS(out_r, nframes);
390 return 0;
392 #endif
394 TRACE("wwo.state == WINE_WS_PLAYING\n");
396 /* see if our sound_buffer is large enough to hold the number of frames jack requested */
397 /* Note: sound_buffer is always filled with 16-bit stereo data, even for mono mode */
398 if(wwo->buffer_size < (nframes * sizeof(short) * 2))
400 ERR("for some reason JACK_BufSize() didn't allocate enough memory\n");
401 ERR("allocated %ld bytes, need %d bytes\n", wwo->buffer_size, (nframes * (unsigned)sizeof(short) * 2));
402 return 0;
405 /* while we have jackFramesAvailable and a wave header to be played */
406 while(jackFramesAvailable && wwo->lpPlayPtr)
408 /* find the amount of audio to be played at this time */
409 outputFramesAvailable = (wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset) / wwo->format.wf.nBlockAlign;
411 numFramesToWrite = min(jackFramesAvailable, outputFramesAvailable);
412 TRACE("dwBufferLength=(%d) dwPartialOffset=(%d)\n",wwo->lpPlayPtr->dwBufferLength,wwo->dwPartialOffset);
413 TRACE("outputFramesAvailable == %d, jackFramesAvailable == %d\n", outputFramesAvailable, jackFramesAvailable);
415 buffer = wwo->lpPlayPtr->lpData + wwo->dwPartialOffset;
417 /* convert from mono to stereo if necessary */
418 /* otherwise just memcpy to the output buffer */
420 if(wwo->format.wf.nChannels == 1)
422 sample_move_d16_d16((short*)wwo->sound_buffer + ((nframes - jackFramesAvailable) * sizeof(short)),
423 (short*)buffer, numFramesToWrite, wwo->format.wf.nChannels);
424 } else /* just copy the memory over */
426 memcpy(wwo->sound_buffer + ((nframes - jackFramesAvailable) * wwo->format.wf.nBlockAlign),
427 buffer, numFramesToWrite * wwo->format.wf.nBlockAlign);
430 /* advance to the next wave header if possible, or advance pointer */
431 /* inside of the current header if we haven't completed it */
432 if(numFramesToWrite == outputFramesAvailable)
434 wodHelper_PlayPtrNext(wwo); /* we wrote the whole waveheader, skip to the next one*/
436 else
438 wwo->dwPartialOffset+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* else advance by the bytes we took in to write */
441 written+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* add on what we wrote */
442 jackFramesAvailable-=numFramesToWrite; /* take away what was written in terms of output bytes */
445 wwo->tickCountMS = GetTickCount(); /* record the current time */
446 wwo->dwWrittenTotal+=written; /* update states on wave device */
447 wwo->dwPlayedTotal+=wwo->bytesInJack; /* we must have finished with the last bytes or we wouldn't be back inside of this callback again... */
448 wwo->bytesInJack = written; /* record the bytes inside of jack */
450 /* Now that we have finished filling the buffer either until it is full or until */
451 /* we have run out of application sound data to process, apply volume and output */
452 /* the audio to the jack server */
454 /* apply volume to the buffer */
455 volume_effect32(wwo->sound_buffer, (nframes - jackFramesAvailable), wwo->volume_left, wwo->volume_right);
457 /* convert from stereo 16 bit to single channel 32 bit float */
458 /* for each jack server channel */
459 /* NOTE: we skip over two sample since we want to only get either the left or right channel */
460 sample_move_d16_s16(out_l, (short*)wwo->sound_buffer, (nframes - jackFramesAvailable), 2);
461 sample_move_d16_s16(out_r, (short*)wwo->sound_buffer + 1, (nframes - jackFramesAvailable), 2);
463 /* see if we still have jackBytesLeft here, if we do that means that we
464 ran out of wave data to play and had a buffer underrun, fill in
465 the rest of the space with zero bytes */
466 if(jackFramesAvailable)
468 ERR("buffer underrun of %d frames\n", jackFramesAvailable);
469 sample_silence_dS(out_l + (nframes - jackFramesAvailable), jackFramesAvailable);
470 sample_silence_dS(out_r + (nframes - jackFramesAvailable), jackFramesAvailable);
473 else if(wwo->state == WINE_WS_PAUSED ||
474 wwo->state == WINE_WS_STOPPED ||
475 wwo->state == WINE_WS_CLOSED)
477 /* output silence if nothing is being outputted */
478 sample_silence_dS(out_l, nframes);
479 sample_silence_dS(out_r, nframes);
482 /* notify the client of completed wave headers */
483 EnterCriticalSection(&wwo->access_crst);
484 wodHelper_NotifyCompletions(wwo, FALSE);
485 LeaveCriticalSection(&wwo->access_crst);
487 return 0;
490 /******************************************************************
491 * JACK_bufsize_wwo
493 * Called whenever the jack server changes the max number
494 * of frames passed to JACK_callback
496 static int JACK_bufsize_wwo (nframes_t nframes, void *arg)
498 WINE_WAVEOUT* wwo = arg;
499 DWORD buffer_required;
500 TRACE("wDevID=%d\n",wwo->wDevID);
501 TRACE("the maximum buffer size is now %u frames\n", nframes);
503 /* make sure the callback routine has adequate memory */
504 /* see if our buffer is large enough for the data we are writing */
505 /* ie. Buffer_size < (bytes we already wrote + bytes we are going to write in this loop) */
506 EnterCriticalSection(&wwo->access_crst);
508 /* wwo->sound_buffer is always filled with 16-bit stereo data, even for mono streams */
509 buffer_required = nframes * sizeof(short) * 2;
510 TRACE("wwo->buffer_size (%ld) buffer_required (%d).\n", wwo->buffer_size,buffer_required);
511 if(wwo->buffer_size < buffer_required)
513 TRACE("expanding buffer from wwo->buffer_size == %ld, to %d\n",
514 wwo->buffer_size, buffer_required);
515 TRACE("GetProcessHeap() == %p\n", GetProcessHeap());
516 wwo->buffer_size = buffer_required;
518 if (wwo->sound_buffer)
519 wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, wwo->buffer_size);
520 else
521 wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, wwo->buffer_size);
523 /* if we don't have a buffer then error out */
524 if(!wwo->sound_buffer)
526 ERR("error allocating sound_buffer memory\n");
527 LeaveCriticalSection(&wwo->access_crst);
528 return 0;
532 LeaveCriticalSection(&wwo->access_crst);
534 TRACE("ending\n");
536 return 0;
538 /******************************************************************
539 * JACK_bufsize_wwi
541 * Called whenever the jack server changes the max number
542 * of frames passed to JACK_callback
544 static int JACK_bufsize_wwi (nframes_t nframes, void *arg)
546 TRACE("the maximum buffer size is now %u frames\n", nframes);
547 return 0;
550 /******************************************************************
551 * JACK_srate
553 static int JACK_srate (nframes_t nframes, void *arg)
555 TRACE("the sample rate is now %u/sec\n", nframes);
556 return 0;
560 /******************************************************************
561 * JACK_shutdown_wwo
563 /* if this is called then jack shut down... handle this appropriately */
564 static void JACK_shutdown_wwo(void* arg)
566 WINE_WAVEOUT* wwo = arg;
568 wwo->client = 0; /* reset client */
570 TRACE("trying to reconnect after sleeping for a short while...\n");
572 /* lets see if we can't reestablish the connection */
573 Sleep(750); /* pause for a short period of time */
574 if(!JACK_OpenWaveOutDevice(wwo))
576 ERR("unable to reconnect with jack...\n");
580 /******************************************************************
581 * JACK_shutdown_wwi
583 /* if this is called then jack shut down... handle this appropriately */
584 static void JACK_shutdown_wwi(void* arg)
586 WINE_WAVEIN* wwi = arg;
588 wwi->client = 0; /* reset client */
590 TRACE("trying to reconnect after sleeping for a short while...\n");
592 /* lets see if we can't reestablish the connection */
593 Sleep(750); /* pause for a short period of time */
594 if(!JACK_OpenWaveInDevice(wwi,wwi->format.wf.nChannels))
596 ERR("unable to reconnect with jack...\n");
601 /******************************************************************
602 * JACK_OpenWaveOutDevice
604 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo)
606 const char** ports;
607 int i;
608 char client_name[64];
609 jack_port_t* out_port_l;
610 jack_port_t* out_port_r;
611 jack_client_t* client;
612 int failed = 0;
614 TRACE("creating jack client and setting up callbacks\n");
616 #if JACK_CLOSE_HACK
617 /* see if this device is already open */
618 if(wwo->client)
620 /* if this device is already in use then it is bad for us to be in here */
621 if(wwo->in_use)
622 return 0;
624 TRACE("using existing client\n");
625 wwo->in_use = TRUE;
626 return 1;
628 #endif
630 /* zero out the buffer pointer and the size of the buffer */
631 wwo->sound_buffer = 0;
632 wwo->buffer_size = 0;
634 /* try to become a client of the JACK server */
635 snprintf(client_name, sizeof(client_name), "wine_jack_out_%d", wwo->wDevID);
636 TRACE("client name '%s'\n", client_name);
637 if ((client = fp_jack_client_open (client_name, JackUseExactName, NULL)) == 0)
639 /* jack has problems with shutting down clients, so lets */
640 /* wait a short while and try once more before we give up */
641 Sleep(250);
642 if ((client = fp_jack_client_open (client_name, JackUseExactName, NULL)) == 0)
644 ERR("jack server not running?\n");
645 return 0;
649 /* tell the JACK server to call `JACK_callback_wwo()' whenever
650 there is work to be done. */
651 fp_jack_set_process_callback (client, JACK_callback_wwo, wwo);
653 /* tell the JACK server to call `JACK_bufsize_wwo()' whenever
654 the maximum number of frames that will be passed
655 to `JACK_Callback()' changes */
656 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwo, wwo);
658 /* tell the JACK server to call `srate()' whenever
659 the sample rate of the system changes. */
660 fp_jack_set_sample_rate_callback (client, JACK_srate, wwo);
662 /* tell the JACK server to call `jack_shutdown()' if
663 it ever shuts down, either entirely, or if it
664 just decides to stop calling us. */
665 fp_jack_on_shutdown (client, JACK_shutdown_wwo, wwo);
667 /* display the current sample rate. once the client is activated
668 (see below), you should rely on your own sample rate
669 callback (see above) for this value. */
670 wwo->sample_rate = fp_jack_get_sample_rate(client);
671 TRACE("engine sample rate: %lu\n", wwo->sample_rate);
673 /* create the left and right channel output ports */
674 /* jack's ports are all mono so for stereo you need two */
675 out_port_l = fp_jack_port_register (client, "out_l",
676 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
678 out_port_r = fp_jack_port_register (client, "out_r",
679 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
681 TRACE("Created ports. (%p) (%p)\n",out_port_l, out_port_r);
683 /* save away important values to the WINE_WAVEOUT struct */
684 wwo->client = client;
685 wwo->out_port_l = out_port_l;
686 wwo->out_port_r = out_port_r;
688 #if JACK_CLOSE_HACK
689 wwo->in_use = TRUE; /* mark this device as in use since it now is ;-) */
690 #endif
692 /* set initial buffer size */
693 JACK_bufsize_wwo (fp_jack_get_buffer_size(client),wwo);
695 /* tell the JACK server that we are ready to roll */
696 if (fp_jack_activate (client))
698 ERR( "cannot activate client\n");
699 return 0;
702 TRACE("jack activate.\n");
703 /* figure out what the ports that we want to output on are */
704 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
705 /* this way works if names are changed */
706 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
708 /* display a trace of the output ports we found */
709 for(i = 0; ports[i]; i++)
711 TRACE("ports[%d] = '%s'\n", i, ports[i]);
714 if(!ports)
716 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsInput'\n");
719 /* connect the ports. Note: you can't do this before
720 the client is activated (this may change in the future).
722 /* we want to connect to two ports so we have stereo output ;-) */
724 if(fp_jack_connect(client, fp_jack_port_name(out_port_l), ports[0]))
726 ERR ("cannot connect to output port %d('%s')\n", 0, ports[0]);
727 failed = 1;
730 if(fp_jack_connect(client, fp_jack_port_name(out_port_r), ports[1]))
732 ERR ("cannot connect to output port %d('%s')\n", 1, ports[1]);
733 failed = 1;
736 free(ports); /* free the returned array of ports */
738 /* if something failed we need to shut the client down and return 0 */
739 if(failed)
741 #if JACK_CLOSE_HACK
742 JACK_CloseWaveOutDevice(wwo, TRUE);
743 #else
744 JACK_CloseWaveOutDevice(wwo);
745 #endif
746 return 0;
749 return 1; /* return success */
752 /******************************************************************
753 * JACK_CloseWaveOutDevice
755 * Close the connection to the server cleanly.
756 * If close_client is TRUE we close the client for this device instead of
757 * just marking the device as in_use(JACK_CLOSE_HACK only)
759 #if JACK_CLOSE_HACK
760 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client)
761 #else
762 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
763 #endif
765 #if JACK_CLOSE_HACK
766 TRACE("wDevID: %d, close_client (wwo): %d\n", wwo->wDevID, close_client);
767 #else
768 TRACE("wDevID: %d\n", wwo->wDevID);
769 #endif
771 #if JACK_CLOSE_HACK
772 if(close_client)
774 #endif
775 fp_jack_deactivate(wwo->client); /* supposed to help the jack_client_close() to succeed */
776 fp_jack_client_close (wwo->client);
778 EnterCriticalSection(&wwo->access_crst);
779 wwo->client = 0; /* reset client */
780 HeapFree(GetProcessHeap(), 0, wwo->sound_buffer); /* free buffer memory */
781 wwo->sound_buffer = 0;
782 wwo->buffer_size = 0; /* zero out size of the buffer */
783 LeaveCriticalSection(&wwo->access_crst);
784 #if JACK_CLOSE_HACK
785 } else
787 EnterCriticalSection(&wwo->access_crst);
788 TRACE("setting in_use to FALSE\n");
789 wwo->in_use = FALSE;
790 LeaveCriticalSection(&wwo->access_crst);
792 #endif
795 /******************************************************************
796 * JACK_CloseWaveInDevice
798 * Close the connection to the server cleanly.
799 * If close_client is TRUE we close the client for this device instead of
800 * just marking the device as in_use(JACK_CLOSE_HACK only)
802 #if JACK_CLOSE_HACK
803 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client)
804 #else
805 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi)
806 #endif
808 #if JACK_CLOSE_HACK
809 TRACE("wDevID: %d, close_client (wwi): %d\n", wwi->wDevID, close_client);
810 #else
811 TRACE("wDevID: %d\n", wwi->wDevID);
812 #endif
814 #if JACK_CLOSE_HACK
815 if(close_client)
817 #endif
818 fp_jack_deactivate(wwi->client); /* supposed to help the jack_client_close() to succeed */
819 fp_jack_client_close (wwi->client);
821 EnterCriticalSection(&wwi->access_crst);
822 wwi->client = 0; /* reset client */
823 HeapFree(GetProcessHeap(), 0, wwi->sound_buffer); /* free buffer memory */
824 wwi->sound_buffer = 0;
825 wwi->buffer_size = 0; /* zero out size of the buffer */
826 LeaveCriticalSection(&wwi->access_crst);
827 #if JACK_CLOSE_HACK
828 } else
830 EnterCriticalSection(&wwi->access_crst);
831 TRACE("setting in_use to FALSE\n");
832 wwi->in_use = FALSE;
833 LeaveCriticalSection(&wwi->access_crst);
835 #endif
838 static int WAVE_loadcount;
840 /******************************************************************
841 * JACK_WaveRelease
845 static LONG JACK_WaveRelease(void)
847 int iDevice;
849 if (--WAVE_loadcount)
850 return 1;
851 TRACE("closing all open waveout devices\n");
853 /* close all open output devices */
854 for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
856 TRACE("iDevice == %d\n", iDevice);
857 if(WOutDev[iDevice].client)
859 #if JACK_CLOSE_HACK
860 JACK_CloseWaveOutDevice(&WOutDev[iDevice], TRUE); /* close the device, FORCE the client to close */
861 #else
862 JACK_CloseWaveOutDevice(&WOutDev[iDevice]); /* close the device, FORCE the client to close */
863 #endif
864 DeleteCriticalSection(&(WOutDev[iDevice].access_crst)); /* delete the critical section */
868 TRACE("closing all open wavein devices\n");
870 /* close all open input devices */
871 for(iDevice = 0; iDevice < MAX_WAVEINDRV; iDevice++)
873 TRACE("iDevice == %d\n", iDevice);
874 if(WInDev[iDevice].client)
876 #if JACK_CLOSE_HACK
877 JACK_CloseWaveInDevice(&WInDev[iDevice], TRUE); /* close the device, FORCE the client to close */
878 #else
879 JACK_CloseWaveInDevice(&WInDev[iDevice]); /* close the device, FORCE the client to close */
880 #endif
881 DeleteCriticalSection(&(WInDev[iDevice].access_crst)); /* delete the critical section */
885 TRACE("returning 1\n");
887 return 1;
890 /******************************************************************
891 * JACK_WaveInit
893 * Initialize internal structures from JACK server info
895 static LONG JACK_WaveInit(void)
897 int i;
898 CHAR szPname[MAXPNAMELEN];
900 TRACE("called\n");
901 if (WAVE_loadcount++)
902 return 1;
904 /* setup function pointers */
905 #define LOAD_FUNCPTR(f) if((fp_##f = wine_dlsym(jackhandle, #f, NULL, 0)) == NULL) goto sym_not_found;
906 LOAD_FUNCPTR(jack_activate);
907 LOAD_FUNCPTR(jack_connect);
908 LOAD_FUNCPTR(jack_client_open);
909 LOAD_FUNCPTR(jack_client_close);
910 LOAD_FUNCPTR(jack_deactivate);
911 LOAD_FUNCPTR(jack_set_process_callback);
912 LOAD_FUNCPTR(jack_set_buffer_size_callback);
913 LOAD_FUNCPTR(jack_set_sample_rate_callback);
914 LOAD_FUNCPTR(jack_on_shutdown);
915 LOAD_FUNCPTR(jack_get_sample_rate);
916 LOAD_FUNCPTR(jack_port_register);
917 LOAD_FUNCPTR(jack_port_get_buffer);
918 LOAD_FUNCPTR(jack_get_ports);
919 LOAD_FUNCPTR(jack_port_name);
920 LOAD_FUNCPTR(jack_get_buffer_size);
921 #undef LOAD_FUNCPTR
923 /* start with output device */
925 for (i = 0; i < MAX_WAVEOUTDRV; ++i)
927 WOutDev[i].client = 0; /* initialize the client to 0 */
929 #if JACK_CLOSE_HACK
930 WOutDev[i].in_use = FALSE;
931 WInDev[i].in_use = FALSE;
932 #endif
934 memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps));
936 WOutDev[i].caps.wMid = 0x00FF; /* Manufac ID */
937 WOutDev[i].caps.wPid = 0x0001; /* Product ID */
938 snprintf(szPname, sizeof(szPname), "JACK WaveOut %d", i);
939 MultiByteToWideChar(CP_ACP, 0, szPname, -1, WOutDev[i].caps.szPname, sizeof(WOutDev[i].caps.szPname)/sizeof(WCHAR));
940 snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "winejack: %d", i);
942 WOutDev[i].caps.vDriverVersion = 0x0100;
943 WOutDev[i].caps.dwFormats = 0x00000000;
944 WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
946 WOutDev[i].caps.wChannels = 2;
947 WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;
949 /* NOTE: we don't support any 8 bit modes so note that */
950 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
951 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
952 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
953 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
954 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
955 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
956 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
957 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
958 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
959 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
960 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
961 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
964 /* then do input device */
965 for (i = 0; i < MAX_WAVEINDRV; ++i)
967 /* TODO: we should initialize read stuff here */
968 memset(&WInDev[i].caps, 0, sizeof(WInDev[i].caps));
970 WInDev[i].caps.wMid = 0x00FF;
971 WInDev[i].caps.wPid = 0x0001;
972 snprintf(szPname, sizeof(szPname), "JACK WaveIn %d", i);
973 MultiByteToWideChar(CP_ACP, 0, szPname, -1, WInDev[i].caps.szPname, sizeof(WInDev[i].caps.szPname)/sizeof(WCHAR));
974 snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "winejack: %d", i);
976 WInDev[i].caps.vDriverVersion = 0x0100;
978 WInDev[i].caps.wChannels = 0x2;
979 /* NOTE: we don't support any 8 bit modes so note that */
980 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
981 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
982 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
983 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
984 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
985 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
986 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
987 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
988 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
989 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
990 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
991 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
992 WInDev[i].caps.wReserved1 = 0;
995 return 1; /* return success */
997 /* error path for function pointer loading errors */
998 sym_not_found:
999 WINE_MESSAGE(
1000 "Wine cannot find certain functions that it needs inside the jack"
1001 "library. To enable Wine to use the jack audio server please "
1002 "install libjack\n");
1003 wine_dlclose(jackhandle, NULL, 0);
1004 jackhandle = NULL;
1005 return FALSE;
1008 /*======================================================================*
1009 * Low level WAVE OUT implementation *
1010 *======================================================================*/
1012 /**************************************************************************
1013 * wodNotifyClient [internal]
1015 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD_PTR dwParam1,
1016 DWORD_PTR dwParam2)
1018 TRACE("wMsg = %04X dwParm1 = %08lX dwParam2 = %08lX\n", wMsg, dwParam1, dwParam2);
1020 switch (wMsg) {
1021 case WOM_OPEN:
1022 case WOM_CLOSE:
1023 case WOM_DONE:
1024 if (wwo->wFlags != DCB_NULL &&
1025 !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags,
1026 (HDRVR)wwo->waveDesc.hWave, wMsg, wwo->waveDesc.dwInstance,
1027 dwParam1, dwParam2))
1029 WARN("can't notify client !\n");
1030 return MMSYSERR_ERROR;
1032 break;
1033 default:
1034 FIXME("Unknown callback message %u\n", wMsg);
1035 return MMSYSERR_INVALPARAM;
1037 return MMSYSERR_NOERROR;
1040 /**************************************************************************
1041 * wodHelper_BeginWaveHdr [internal]
1043 * Makes the specified lpWaveHdr the currently playing wave header.
1044 * If the specified wave header is a begin loop and we're not already in
1045 * a loop, setup the loop.
1047 static void wodHelper_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
1049 EnterCriticalSection(&wwo->access_crst);
1051 wwo->lpPlayPtr = lpWaveHdr;
1053 if (!lpWaveHdr)
1055 LeaveCriticalSection(&wwo->access_crst);
1056 return;
1059 if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)
1061 if (wwo->lpLoopPtr)
1063 WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1064 TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1065 } else
1067 TRACE("Starting loop (%dx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
1068 wwo->lpLoopPtr = lpWaveHdr;
1069 /* Windows does not touch WAVEHDR.dwLoops,
1070 * so we need to make an internal copy */
1071 wwo->dwLoops = lpWaveHdr->dwLoops;
1074 wwo->dwPartialOffset = 0;
1076 LeaveCriticalSection(&wwo->access_crst);
1080 /**************************************************************************
1081 * wodHelper_PlayPtrNext [internal]
1083 * Advance the play pointer to the next waveheader, looping if required.
1085 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
1087 LPWAVEHDR lpWaveHdr;
1089 EnterCriticalSection(&wwo->access_crst);
1091 lpWaveHdr = wwo->lpPlayPtr;
1093 wwo->dwPartialOffset = 0;
1094 if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr)
1096 /* We're at the end of a loop, loop if required */
1097 if (--wwo->dwLoops > 0)
1099 wwo->lpPlayPtr = wwo->lpLoopPtr;
1100 } else
1102 /* Handle overlapping loops correctly */
1103 if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
1104 FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
1105 /* shall we consider the END flag for the closing loop or for
1106 * the opening one or for both ???
1107 * code assumes for closing loop only
1109 } else
1111 lpWaveHdr = lpWaveHdr->lpNext;
1113 wwo->lpLoopPtr = NULL;
1114 wodHelper_BeginWaveHdr(wwo, lpWaveHdr);
1116 } else
1118 /* We're not in a loop. Advance to the next wave header */
1119 TRACE("not inside of a loop, advancing to next wave header\n");
1120 wodHelper_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
1123 LeaveCriticalSection(&wwo->access_crst);
1125 return lpWaveHdr;
1128 /* if force is TRUE then notify the client that all the headers were completed */
1129 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
1131 LPWAVEHDR lpWaveHdr;
1132 DWORD retval;
1134 TRACE("called\n");
1136 EnterCriticalSection(&wwo->access_crst);
1138 /* Start from lpQueuePtr and keep notifying until:
1139 * - we hit an unwritten wavehdr
1140 * - we hit the beginning of a running loop
1141 * - we hit a wavehdr which hasn't finished playing
1143 while ((lpWaveHdr = wwo->lpQueuePtr) &&
1144 (force ||
1145 (lpWaveHdr != wwo->lpPlayPtr &&
1146 lpWaveHdr != wwo->lpLoopPtr)))
1148 wwo->lpQueuePtr = lpWaveHdr->lpNext;
1150 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1151 lpWaveHdr->dwFlags |= WHDR_DONE;
1152 TRACE("notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) dwFlags=(%d)\n",
1153 lpWaveHdr, wwo->lpPlayPtr, lpWaveHdr->dwFlags);
1155 wodNotifyClient(wwo, WOM_DONE, (DWORD_PTR)lpWaveHdr, 0);
1157 TRACE("Not notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) lpLoopPtr=(%p)\n",
1158 lpWaveHdr, wwo->lpPlayPtr, wwo->lpLoopPtr);
1159 retval = (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr !=
1160 wwo->lpLoopPtr) ? 0 : INFINITE;
1162 LeaveCriticalSection(&wwo->access_crst);
1164 return retval;
1167 /**************************************************************************
1168 * wodHelper_Reset [internal]
1170 * Resets current output stream.
1172 static void wodHelper_Reset(WINE_WAVEOUT* wwo, BOOL reset)
1174 EnterCriticalSection(&wwo->access_crst);
1176 /* updates current notify list */
1177 wodHelper_NotifyCompletions(wwo, FALSE);
1179 if (reset)
1181 /* remove all wave headers and notify client that all headers were completed */
1182 wodHelper_NotifyCompletions(wwo, TRUE);
1184 wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
1185 wwo->state = WINE_WS_STOPPED;
1186 wwo->dwPlayedTotal = wwo->dwWrittenTotal = wwo->bytesInJack = 0;
1188 wwo->dwPartialOffset = 0; /* Clear partial wavehdr */
1189 } else
1191 if (wwo->lpLoopPtr)
1193 /* complicated case, not handled yet (could imply modifying the loop counter) */
1194 FIXME("Pausing while in loop isn't correctly handled yet, expect strange results\n");
1195 wwo->lpPlayPtr = wwo->lpLoopPtr;
1196 wwo->dwPartialOffset = 0;
1197 wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
1198 } else
1200 LPWAVEHDR ptr;
1201 DWORD sz = wwo->dwPartialOffset;
1203 /* reset all the data as if we had written only up to lpPlayedTotal bytes */
1204 /* compute the max size playable from lpQueuePtr */
1205 for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext)
1207 sz += ptr->dwBufferLength;
1210 /* because the reset lpPlayPtr will be lpQueuePtr */
1211 if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("doh\n");
1212 wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal);
1213 wwo->dwWrittenTotal = wwo->dwPlayedTotal;
1214 wwo->lpPlayPtr = wwo->lpQueuePtr;
1217 wwo->state = WINE_WS_PAUSED;
1220 LeaveCriticalSection(&wwo->access_crst);
1223 /**************************************************************************
1224 * wodGetDevCaps [internal]
1226 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSW lpCaps, DWORD dwSize)
1228 TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
1230 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1232 if (wDevID >= MAX_WAVEOUTDRV)
1234 TRACE("MAX_WAVOUTDRV reached !\n");
1235 return MMSYSERR_BADDEVICEID;
1238 TRACE("dwSupport=(0x%x), dwFormats=(0x%x)\n", WOutDev[wDevID].caps.dwSupport, WOutDev[wDevID].caps.dwFormats);
1239 memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1240 return MMSYSERR_NOERROR;
1243 /**************************************************************************
1244 * wodOpen [internal]
1246 * NOTE: doesn't it seem like there is a race condition if you try to open
1247 * the same device twice?
1249 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1251 WINE_WAVEOUT* wwo;
1252 DWORD retval;
1254 TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
1255 if (lpDesc == NULL)
1257 WARN("Invalid Parameter !\n");
1258 return MMSYSERR_INVALPARAM;
1260 if (wDevID >= MAX_WAVEOUTDRV) {
1261 TRACE("MAX_WAVOUTDRV reached !\n");
1262 return MMSYSERR_BADDEVICEID;
1265 #if JACK_CLOSE_HACK
1266 if(WOutDev[wDevID].client && WOutDev[wDevID].in_use)
1267 #else
1268 if(WOutDev[wDevID].client)
1269 #endif
1271 TRACE("device %d already allocated\n", wDevID);
1272 return MMSYSERR_ALLOCATED;
1275 /* Only the PCM format is supported so far...
1276 * Also we only support 16 bit mode.
1278 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1279 lpDesc->lpFormat->nChannels == 0 ||
1280 lpDesc->lpFormat->nSamplesPerSec == 0 ||
1281 lpDesc->lpFormat->wBitsPerSample != 16)
1283 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
1284 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1285 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
1286 return WAVERR_BADFORMAT;
1289 if (dwFlags & WAVE_FORMAT_QUERY)
1291 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
1292 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1293 lpDesc->lpFormat->nSamplesPerSec);
1294 return MMSYSERR_NOERROR;
1297 wwo = &WOutDev[wDevID];
1298 wwo->wDevID = wDevID;
1300 /* Set things up before we call JACK_OpenWaveOutDevice because */
1301 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
1302 /* even returns and we want to be initialized before then */
1303 wwo->state = WINE_WS_STOPPED; /* start in a stopped state */
1304 wwo->dwPlayedTotal = 0; /* zero out these totals */
1305 wwo->dwWrittenTotal = 0;
1306 wwo->bytesInJack = 0;
1307 wwo->tickCountMS = 0;
1309 /* Initialize volume to full level */
1310 wwo->volume_left = 100;
1311 wwo->volume_right = 100;
1313 InitializeCriticalSection(&wwo->access_crst); /* initialize the critical section */
1314 EnterCriticalSection(&wwo->access_crst);
1316 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
1318 wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1320 wwo->waveDesc = *lpDesc;
1321 memcpy(&wwo->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1323 /* open up jack ports for this device */
1324 if (!JACK_OpenWaveOutDevice(&WOutDev[wDevID]))
1326 ERR("JACK_OpenWaveOutDevice(%d) failed\n", wDevID);
1327 LeaveCriticalSection(&wwo->access_crst);
1328 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1329 return MMSYSERR_ERROR; /* return unspecified error */
1332 LeaveCriticalSection(&wwo->access_crst);
1334 /* display the current wave format */
1335 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%u, nSamplesPerSec=%u, nChannels=%u nBlockAlign=%u!\n",
1336 wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
1337 wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1338 wwo->format.wf.nBlockAlign);
1340 /* make sure that we have the same sample rate in our audio stream */
1341 /* as we do in the jack server */
1342 if(wwo->format.wf.nSamplesPerSec != wwo->sample_rate)
1344 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%d'\n",
1345 wwo->sample_rate, wwo->format.wf.nSamplesPerSec);
1347 #if JACK_CLOSE_HACK
1348 JACK_CloseWaveOutDevice(wwo, FALSE); /* close this device, don't force the client to close */
1349 #else
1350 JACK_CloseWaveOutDevice(wwo); /* close this device */
1351 #endif
1352 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1353 return WAVERR_BADFORMAT;
1356 /* check for an invalid number of bits per sample */
1357 if (wwo->format.wBitsPerSample == 0)
1359 WARN("Resetting zeroed wBitsPerSample\n");
1360 wwo->format.wBitsPerSample = 8 *
1361 (wwo->format.wf.nAvgBytesPerSec /
1362 wwo->format.wf.nSamplesPerSec) /
1363 wwo->format.wf.nChannels;
1366 EnterCriticalSection(&wwo->access_crst);
1367 retval = wodNotifyClient(wwo, WOM_OPEN, 0, 0);
1368 LeaveCriticalSection(&wwo->access_crst);
1370 return retval;
1373 /**************************************************************************
1374 * wodClose [internal]
1376 static DWORD wodClose(WORD wDevID)
1378 DWORD ret = MMSYSERR_NOERROR;
1379 WINE_WAVEOUT* wwo;
1381 TRACE("(%u);\n", wDevID);
1383 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1385 WARN("bad device ID !\n");
1386 return MMSYSERR_BADDEVICEID;
1389 wwo = &WOutDev[wDevID];
1390 if (wwo->lpQueuePtr)
1392 WARN("buffers still playing !\n");
1393 ret = WAVERR_STILLPLAYING;
1394 } else
1396 /* sanity check: this should not happen since the device must have been reset before */
1397 if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
1399 wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
1401 #if JACK_CLOSE_HACK
1402 JACK_CloseWaveOutDevice(wwo, FALSE); /* close the jack device, DO NOT force the client to close */
1403 #else
1404 JACK_CloseWaveOutDevice(wwo); /* close the jack device */
1405 #endif
1406 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1408 ret = wodNotifyClient(wwo, WOM_CLOSE, 0, 0);
1411 return ret;
1415 /**************************************************************************
1416 * wodWrite [internal]
1419 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1421 LPWAVEHDR*wh;
1422 WINE_WAVEOUT *wwo;
1424 TRACE("(%u, %p, %08X);\n", wDevID, lpWaveHdr, dwSize);
1426 /* first, do the sanity checks... */
1427 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1429 WARN("bad dev ID !\n");
1430 return MMSYSERR_BADDEVICEID;
1433 wwo = &WOutDev[wDevID];
1435 if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1437 TRACE("unprepared\n");
1438 return WAVERR_UNPREPARED;
1441 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1443 TRACE("still playing\n");
1444 return WAVERR_STILLPLAYING;
1447 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1448 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1449 lpWaveHdr->lpNext = 0;
1451 EnterCriticalSection(&wwo->access_crst);
1453 /* insert buffer at the end of queue */
1454 for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
1455 *wh = lpWaveHdr;
1457 if (!wwo->lpPlayPtr)
1458 wodHelper_BeginWaveHdr(wwo,lpWaveHdr);
1459 if (wwo->state == WINE_WS_STOPPED)
1460 wwo->state = WINE_WS_PLAYING;
1461 LeaveCriticalSection(&wwo->access_crst);
1463 return MMSYSERR_NOERROR;
1466 /**************************************************************************
1467 * wodPause [internal]
1469 static DWORD wodPause(WORD wDevID)
1471 TRACE("(%u);!\n", wDevID);
1473 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1475 WARN("bad device ID !\n");
1476 return MMSYSERR_BADDEVICEID;
1479 TRACE("[3-PAUSING]\n");
1481 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1482 wodHelper_Reset(&WOutDev[wDevID], FALSE);
1483 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1485 return MMSYSERR_NOERROR;
1488 /**************************************************************************
1489 * wodRestart [internal]
1491 static DWORD wodRestart(WORD wDevID)
1493 TRACE("(%u);\n", wDevID);
1495 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1497 WARN("bad device ID !\n");
1498 return MMSYSERR_BADDEVICEID;
1501 if (WOutDev[wDevID].state == WINE_WS_PAUSED)
1503 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1504 WOutDev[wDevID].state = WINE_WS_PLAYING;
1505 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1508 return MMSYSERR_NOERROR;
1511 /**************************************************************************
1512 * wodReset [internal]
1514 static DWORD wodReset(WORD wDevID)
1516 TRACE("(%u);\n", wDevID);
1518 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1520 WARN("bad device ID !\n");
1521 return MMSYSERR_BADDEVICEID;
1524 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1525 wodHelper_Reset(&WOutDev[wDevID], TRUE);
1526 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1528 return MMSYSERR_NOERROR;
1531 /**************************************************************************
1532 * wodGetPosition [internal]
1534 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1536 DWORD val;
1537 WINE_WAVEOUT* wwo;
1538 DWORD elapsedMS;
1540 TRACE("(%u, %p, %u);\n", wDevID, lpTime, uSize);
1542 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1544 WARN("bad device ID !\n");
1545 return MMSYSERR_BADDEVICEID;
1548 /* if null pointer to time structure return error */
1549 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1551 wwo = &WOutDev[wDevID];
1553 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1554 val = wwo->dwPlayedTotal;
1555 elapsedMS = GetTickCount() - wwo->tickCountMS;
1556 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1558 /* account for the bytes played since the last JACK_Callback() */
1559 val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
1561 return bytes_to_mmtime(lpTime, val, &wwo->format);
1564 /**************************************************************************
1565 * wodBreakLoop [internal]
1567 static DWORD wodBreakLoop(WORD wDevID)
1569 TRACE("(%u);\n", wDevID);
1571 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1573 WARN("bad device ID !\n");
1574 return MMSYSERR_BADDEVICEID;
1577 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1579 if (WOutDev[wDevID].state == WINE_WS_PLAYING && WOutDev[wDevID].lpLoopPtr != NULL)
1581 /* ensure exit at end of current loop */
1582 WOutDev[wDevID].dwLoops = 1;
1585 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1587 return MMSYSERR_NOERROR;
1590 /**************************************************************************
1591 * wodGetVolume [internal]
1593 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1595 DWORD left, right;
1597 left = WOutDev[wDevID].volume_left;
1598 right = WOutDev[wDevID].volume_right;
1600 TRACE("(%u, %p);\n", wDevID, lpdwVol);
1602 *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
1603 16);
1605 return MMSYSERR_NOERROR;
1608 /**************************************************************************
1609 * wodSetVolume [internal]
1611 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1613 DWORD left, right;
1615 left = (LOWORD(dwParam) * 100) / 0xFFFFl;
1616 right = (HIWORD(dwParam) * 100) / 0xFFFFl;
1618 TRACE("(%u, %08X);\n", wDevID, dwParam);
1620 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1622 WOutDev[wDevID].volume_left = left;
1623 WOutDev[wDevID].volume_right = right;
1625 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1627 return MMSYSERR_NOERROR;
1630 /**************************************************************************
1631 * wodGetNumDevs [internal]
1633 static DWORD wodGetNumDevs(void)
1635 return MAX_WAVEOUTDRV;
1638 /**************************************************************************
1639 * wodDevInterfaceSize [internal]
1641 static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
1643 TRACE("(%u, %p)\n", wDevID, dwParam1);
1645 *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1646 NULL, 0 ) * sizeof(WCHAR);
1647 return MMSYSERR_NOERROR;
1650 /**************************************************************************
1651 * wodDevInterface [internal]
1653 static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
1655 if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1656 NULL, 0 ) * sizeof(WCHAR))
1658 MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1659 dwParam1, dwParam2 / sizeof(WCHAR));
1660 return MMSYSERR_NOERROR;
1662 return MMSYSERR_INVALPARAM;
1665 /**************************************************************************
1666 * wodMessage (WINEJACK.7)
1668 DWORD WINAPI JACK_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
1669 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
1671 TRACE("(%u, %04X, %08X, %08lX, %08lX);\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
1673 switch (wMsg) {
1674 case DRVM_INIT:
1675 return JACK_WaveInit();
1676 case DRVM_EXIT:
1677 return JACK_WaveRelease();
1678 case DRVM_ENABLE:
1679 case DRVM_DISABLE:
1680 /* FIXME: Pretend this is supported */
1681 return 0;
1682 case WODM_OPEN: return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1683 case WODM_CLOSE: return wodClose(wDevID);
1684 case WODM_WRITE: return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1685 case WODM_PAUSE: return wodPause(wDevID);
1686 case WODM_GETPOS: return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1687 case WODM_BREAKLOOP: return wodBreakLoop(wDevID);
1688 case WODM_PREPARE: return MMSYSERR_NOTSUPPORTED;
1689 case WODM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
1690 case WODM_GETDEVCAPS: return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSW)dwParam1, dwParam2);
1691 case WODM_GETNUMDEVS: return wodGetNumDevs();
1692 case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED;
1693 case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED;
1694 case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1695 case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1696 case WODM_GETVOLUME: return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1697 case WODM_SETVOLUME: return wodSetVolume(wDevID, dwParam1);
1698 case WODM_RESTART: return wodRestart(wDevID);
1699 case WODM_RESET: return wodReset(wDevID);
1701 case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
1702 case DRV_QUERYDEVICEINTERFACE: return wodDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
1703 case DRV_QUERYDSOUNDIFACE: return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1);
1704 case DRV_QUERYDSOUNDDESC: return wodDsDesc(wDevID, (PDSDRIVERDESC)dwParam1);
1705 default:
1706 FIXME("unknown message %d!\n", wMsg);
1708 return MMSYSERR_NOTSUPPORTED;
1711 /*======================================================================*
1712 * Low level DSOUND implementation *
1713 *======================================================================*/
1715 typedef struct IDsDriverImpl IDsDriverImpl;
1716 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;
1718 struct IDsDriverImpl
1720 /* IUnknown fields */
1721 const IDsDriverVtbl *lpVtbl;
1722 DWORD ref;
1723 /* IDsDriverImpl fields */
1724 UINT wDevID;
1725 IDsDriverBufferImpl*primary;
1728 struct IDsDriverBufferImpl
1730 /* IUnknown fields */
1731 const IDsDriverBufferVtbl *lpVtbl;
1732 DWORD ref;
1733 /* IDsDriverBufferImpl fields */
1734 IDsDriverImpl* drv;
1735 DWORD buflen;
1738 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
1740 /* we can't perform memory mapping as we don't have a file stream
1741 interface with jack like we do with oss */
1742 MESSAGE("This sound card's driver does not support direct access\n");
1743 MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
1744 return MMSYSERR_NOTSUPPORTED;
1747 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
1749 memset(desc, 0, sizeof(*desc));
1750 strcpy(desc->szDesc, "Wine jack DirectSound Driver");
1751 strcpy(desc->szDrvname, "winejack.drv");
1752 return MMSYSERR_NOERROR;
1755 /*======================================================================*
1756 * Low level WAVE IN implementation *
1757 *======================================================================*/
1759 /**************************************************************************
1760 * widNotifyClient [internal]
1762 static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD_PTR dwParam1,
1763 DWORD_PTR dwParam2)
1765 TRACE("wMsg = %04X dwParm1 = %08lX dwParam2 = %08lX\n", wMsg, dwParam1, dwParam2);
1767 switch (wMsg) {
1768 case WIM_OPEN:
1769 case WIM_CLOSE:
1770 case WIM_DATA:
1771 if (wwi->wFlags != DCB_NULL &&
1772 !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
1773 (HDRVR)wwi->waveDesc.hWave, wMsg, wwi->waveDesc.dwInstance,
1774 dwParam1, dwParam2))
1776 WARN("can't notify client !\n");
1777 return MMSYSERR_ERROR;
1779 break;
1780 default:
1781 FIXME("Unknown callback message %u\n", wMsg);
1782 return MMSYSERR_INVALPARAM;
1784 return MMSYSERR_NOERROR;
1787 /******************************************************************
1788 * JACK_callback_wwi
1790 /* everytime the jack server wants something from us it calls this
1791 function */
1792 static int JACK_callback_wwi (nframes_t nframes, void *arg)
1794 sample_t* in_l;
1795 sample_t* in_r = 0;
1796 WINE_WAVEIN* wwi = arg;
1798 TRACE("wDevID: %u, nframes %u\n", wwi->wDevID, nframes);
1800 if(!wwi->client)
1801 ERR("client is closed, this is weird...\n");
1803 in_l = fp_jack_port_get_buffer(wwi->in_port_l, nframes);
1805 if (wwi->in_port_r)
1806 in_r = fp_jack_port_get_buffer(wwi->in_port_r, nframes);
1808 EnterCriticalSection(&wwi->access_crst);
1810 if((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
1812 LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
1813 nframes_t jackFramesLeft = nframes;
1815 #if JACK_CLOSE_HACK
1816 if(wwi->in_use == FALSE)
1818 /* do nothing if nothing is being recorded */
1819 LeaveCriticalSection(&wwi->access_crst);
1820 return 0;
1822 #endif
1824 TRACE("wwi.state == WINE_WS_PLAYING\n");
1826 while (lpWaveHdr && jackFramesLeft)
1828 DWORD waveHdrFramesLeft = (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded) / (sizeof(short) * wwi->format.wf.nChannels);
1829 DWORD numFrames = min (jackFramesLeft, waveHdrFramesLeft);
1831 TRACE ("dwBufferLength=(%u) dwBytesRecorded=(%d)\n", lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
1832 TRACE ("jackFramesLeft=(%u) waveHdrFramesLeft=(%u)\n", jackFramesLeft, waveHdrFramesLeft);
1834 if (!in_r) {
1835 /* mono */
1836 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded), in_l+(nframes-jackFramesLeft), numFrames, 1);
1837 } else {
1838 /* stereo */
1839 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded),
1840 in_l+(nframes-jackFramesLeft), numFrames, 2);
1841 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded + sizeof(short)),
1842 in_r+(nframes-jackFramesLeft), numFrames, 2);
1845 lpWaveHdr->dwBytesRecorded += (numFrames * sizeof(short) * wwi->format.wf.nChannels );
1846 jackFramesLeft -= numFrames;
1848 if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
1850 /* must copy the value of next waveHdr, because we have no idea of what
1851 * will be done with the content of lpWaveHdr in callback
1853 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
1855 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1856 lpWaveHdr->dwFlags |= WHDR_DONE;
1858 TRACE("WaveHdr full. dwBytesRecorded=(%u) dwFlags=(0x%x)\n",lpWaveHdr->dwBytesRecorded,lpWaveHdr->dwFlags);
1860 widNotifyClient(wwi, WIM_DATA, (DWORD_PTR)lpWaveHdr, 0);
1862 lpWaveHdr = wwi->lpQueuePtr = lpNext;
1865 TRACE ("jackFramesLeft=(%u) lpWaveHdr=(%p)\n", jackFramesLeft, lpWaveHdr);
1866 if (jackFramesLeft > 0) { WARN("Record buffer ran out of WaveHdrs\n"); }
1869 LeaveCriticalSection(&wwi->access_crst);
1871 return 0;
1874 /******************************************************************
1875 * JACK_OpenWaveInDevice
1877 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels)
1879 const char** ports;
1880 int i;
1881 char client_name[64];
1882 jack_port_t* in_port_l;
1883 jack_port_t* in_port_r = 0;
1884 jack_client_t* client;
1885 int failed = 0;
1887 TRACE("creating jack client and setting up callbacks\n");
1889 if ((nChannels == 0) || (nChannels > 2)) {
1890 ERR ("nChannels = (%d), but we only support mono or stereo.\n", nChannels);
1891 return 0;
1894 #if JACK_CLOSE_HACK
1895 /* see if this device is already open */
1896 if(wwi->client)
1898 /* if this device is already in use then it is bad for us to be in here */
1899 if(wwi->in_use)
1900 return 0;
1902 TRACE("using existing client\n");
1903 wwi->in_use = TRUE;
1904 return 1;
1906 #endif
1908 /* zero out the buffer pointer and the size of the buffer */
1909 wwi->sound_buffer = 0;
1910 wwi->buffer_size = 0;
1912 /* try to become a client of the JACK server */
1913 snprintf(client_name, sizeof(client_name), "wine_jack_in_%d", wwi->wDevID);
1914 TRACE("client name '%s'\n", client_name);
1915 if ((client = fp_jack_client_open (client_name, JackUseExactName, NULL)) == 0)
1917 /* jack has problems with shutting down clients, so lets */
1918 /* wait a short while and try once more before we give up */
1919 Sleep(250);
1920 if ((client = fp_jack_client_open (client_name, JackUseExactName, NULL)) == 0)
1922 ERR("jack server not running?\n");
1923 return 0;
1926 wwi->client = client;
1928 /* tell the JACK server to call `JACK_wwi_callback()' whenever
1929 there is work to be done. */
1930 fp_jack_set_process_callback (client, JACK_callback_wwi, wwi);
1932 /* tell the JACK server to call `JACK_bufsize_wwi()' whenever
1933 the maximum number of frames that will be passed
1934 to `JACK_Callback()' changes */
1935 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwi, wwi);
1937 /* tell the JACK server to call `srate()' whenever
1938 the sample rate of the system changes. */
1939 fp_jack_set_sample_rate_callback (client, JACK_srate, wwi);
1941 /* tell the JACK server to call `jack_shutdown()' if
1942 it ever shuts down, either entirely, or if it
1943 just decides to stop calling us. */
1944 fp_jack_on_shutdown (client, JACK_shutdown_wwi, wwi);
1946 /* display the current sample rate. once the client is activated
1947 (see below), you should rely on your own sample rate
1948 callback (see above) for this value. */
1949 wwi->sample_rate = fp_jack_get_sample_rate(client);
1950 TRACE("engine sample rate: %lu\n", wwi->sample_rate);
1952 /* create the left and right channel output ports */
1953 /* jack's ports are all mono so for stereo you need two */
1954 in_port_l = fp_jack_port_register (client, "in_l",
1955 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
1956 wwi->in_port_l = in_port_l;
1957 TRACE("Created port. (%p)\n", in_port_l);
1959 if (nChannels == 2)
1961 in_port_r = fp_jack_port_register (client, "in_r",
1962 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
1963 TRACE("Created port. (%p)\n", in_port_r);
1965 wwi->in_port_r = in_port_r;
1967 #if JACK_CLOSE_HACK
1968 wwi->in_use = TRUE; /* mark this device as in use since it now is ;-) */
1969 #endif
1971 TRACE("activating client.\n");
1972 /* tell the JACK server that we are ready to roll */
1973 if (fp_jack_activate (client))
1975 ERR( "cannot activate client\n");
1976 return 0;
1978 TRACE("activated client.\n");
1979 /* figure out what the ports that we want to output on are */
1980 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
1981 /* this way works if names are changed */
1982 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
1984 /* display a trace of the output ports we found */
1985 for(i = 0; ports[i]; i++)
1987 TRACE("ports[%d] = '%s'\n", i, ports[i]);
1990 if(!ports)
1992 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsOutput'\n");
1995 /* connect the ports. Note: you can't do this before
1996 the client is activated (this may change in the future).
1998 /* we want to connect to two ports so we have stereo input ;-) */
2000 if(fp_jack_connect(client, ports[0], fp_jack_port_name(in_port_l)))
2002 ERR ("cannot connect to input port %d('%s')\n", 0, ports[0]);
2003 failed = 1;
2005 TRACE("Connected (%s)<->(%s)\n",ports[0],fp_jack_port_name(in_port_l));
2007 if ((nChannels == 2) && in_port_r) {
2008 if(fp_jack_connect(client, ports[1], fp_jack_port_name(in_port_r)))
2010 ERR ("cannot connect to input port %d('%s')\n", 1, ports[1]);
2011 failed = 1;
2013 TRACE("Connected (%s)<->(%s)\n",ports[1],fp_jack_port_name(in_port_r));
2015 free(ports); /* free the returned array of ports */
2017 /* if something failed we need to shut the client down and return 0 */
2018 if(failed)
2020 #if JACK_CLOSE_HACK
2021 JACK_CloseWaveInDevice(wwi, TRUE);
2022 #else
2023 JACK_CloseWaveInDevice(wwi);
2024 #endif
2025 return 0;
2028 TRACE("return success.\n");
2029 return 1; /* return success */
2032 /**************************************************************************
2033 * widGetDevCaps [internal]
2035 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSW lpCaps, DWORD dwSize)
2037 TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
2039 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
2041 if (wDevID >= MAX_WAVEINDRV) {
2042 TRACE("MAX_WAVEINDRV reached !\n");
2043 return MMSYSERR_BADDEVICEID;
2046 memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
2047 return MMSYSERR_NOERROR;
2050 /**************************************************************************
2051 * widOpen [internal]
2053 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
2055 WINE_WAVEIN* wwi;
2056 DWORD retval;
2058 TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
2059 if (lpDesc == NULL)
2061 WARN("Invalid Parameter !\n");
2062 return MMSYSERR_INVALPARAM;
2064 if (wDevID >= MAX_WAVEINDRV) {
2065 TRACE ("MAX_WAVEINDRV reached !\n");
2066 return MMSYSERR_BADDEVICEID;
2069 #if JACK_CLOSE_HACK
2070 if(WInDev[wDevID].client && WOutDev[wDevID].in_use)
2071 #else
2072 if(WInDev[wDevID].client)
2073 #endif
2075 TRACE("device %d already allocated\n", wDevID);
2076 return MMSYSERR_ALLOCATED;
2079 /* Only the PCM format is supported so far...
2080 * Also we only support 16 bit mode.
2082 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
2083 lpDesc->lpFormat->nChannels == 0 ||
2084 lpDesc->lpFormat->nSamplesPerSec == 0 ||
2085 lpDesc->lpFormat->wBitsPerSample!=16)
2087 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
2088 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2089 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
2090 return WAVERR_BADFORMAT;
2093 if (dwFlags & WAVE_FORMAT_QUERY)
2095 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
2096 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2097 lpDesc->lpFormat->nSamplesPerSec);
2098 return MMSYSERR_NOERROR;
2101 wwi = &WInDev[wDevID];
2102 wwi->wDevID = wDevID;
2104 /* Set things up before we call JACK_OpenWaveOutDevice because */
2105 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
2106 /* even returns and we want to be initialized before then */
2107 wwi->state = WINE_WS_STOPPED; /* start in a stopped state */
2109 InitializeCriticalSection(&wwi->access_crst); /* initialize the critical section */
2110 EnterCriticalSection(&wwi->access_crst);
2112 /* open up jack ports for this device */
2113 if (!JACK_OpenWaveInDevice(&WInDev[wDevID], lpDesc->lpFormat->nChannels))
2115 ERR("JACK_OpenWaveInDevice(%d) failed\n", wDevID);
2116 LeaveCriticalSection(&wwi->access_crst);
2117 DeleteCriticalSection(&wwi->access_crst);
2118 return MMSYSERR_ERROR; /* return unspecified error */
2121 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
2123 wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
2125 wwi->waveDesc = *lpDesc;
2126 memcpy(&wwi->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
2128 LeaveCriticalSection(&wwi->access_crst);
2130 /* display the current wave format */
2131 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%u, nSamplesPerSec=%u, nChannels=%u nBlockAlign=%u!\n",
2132 wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
2133 wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
2134 wwi->format.wf.nBlockAlign);
2136 /* make sure that we have the same sample rate in our audio stream */
2137 /* as we do in the jack server */
2138 if(wwi->format.wf.nSamplesPerSec != wwi->sample_rate)
2140 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%d'\n",
2141 wwi->sample_rate, wwi->format.wf.nSamplesPerSec);
2143 #if JACK_CLOSE_HACK
2144 JACK_CloseWaveInDevice(wwi, FALSE); /* close this device, don't force the client to close */
2145 #else
2146 JACK_CloseWaveInDevice(wwi); /* close this device */
2147 #endif
2148 DeleteCriticalSection(&wwi->access_crst);
2149 return WAVERR_BADFORMAT;
2152 /* check for an invalid number of bits per sample */
2153 if (wwi->format.wBitsPerSample == 0)
2155 WARN("Resetting zeroed wBitsPerSample\n");
2156 wwi->format.wBitsPerSample = 8 *
2157 (wwi->format.wf.nAvgBytesPerSec /
2158 wwi->format.wf.nSamplesPerSec) /
2159 wwi->format.wf.nChannels;
2162 TRACE("notify client.\n");
2163 EnterCriticalSection(&wwi->access_crst);
2164 retval = widNotifyClient(wwi, WIM_OPEN, 0, 0);
2165 LeaveCriticalSection(&wwi->access_crst);
2167 return retval;
2169 /**************************************************************************
2170 * widClose [internal]
2172 static DWORD widClose(WORD wDevID)
2174 DWORD ret = MMSYSERR_NOERROR;
2175 WINE_WAVEIN* wwi;
2177 TRACE("(%u);\n", wDevID);
2179 if (wDevID >= MAX_WAVEINDRV || !WInDev[wDevID].client)
2181 WARN("bad device ID !\n");
2182 return MMSYSERR_BADDEVICEID;
2185 wwi = &WInDev[wDevID];
2186 if (wwi->lpQueuePtr)
2188 WARN("buffers still playing !\n");
2189 ret = WAVERR_STILLPLAYING;
2190 } else
2192 /* sanity check: this should not happen since the device must have been reset before */
2193 if (wwi->lpQueuePtr) ERR("out of sync\n");
2195 wwi->state = WINE_WS_CLOSED; /* mark the device as closed */
2197 #if JACK_CLOSE_HACK
2198 JACK_CloseWaveInDevice(wwi, FALSE); /* close the jack device, DO NOT force the client to close */
2199 #else
2200 JACK_CloseWaveInDevice(wwi); /* close the jack device */
2201 #endif
2202 DeleteCriticalSection(&wwi->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
2204 ret = widNotifyClient(wwi, WIM_CLOSE, 0, 0);
2207 return ret;
2210 /**************************************************************************
2211 * widAddBuffer [internal]
2213 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2215 WINE_WAVEIN* wwi = &WInDev[wDevID];
2217 TRACE("(%u, %p, %08X);\n", wDevID, lpWaveHdr, dwSize);
2219 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2220 WARN("can't do it !\n");
2221 return MMSYSERR_INVALHANDLE;
2223 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
2224 TRACE("never been prepared !\n");
2225 return WAVERR_UNPREPARED;
2227 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2228 TRACE("header already in use !\n");
2229 return WAVERR_STILLPLAYING;
2232 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
2233 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2234 lpWaveHdr->dwBytesRecorded = 0;
2235 lpWaveHdr->lpNext = NULL;
2237 EnterCriticalSection(&wwi->access_crst);
2238 /* insert buffer at end of queue */
2240 LPWAVEHDR* wh;
2241 for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
2242 *wh=lpWaveHdr;
2244 LeaveCriticalSection(&wwi->access_crst);
2246 return MMSYSERR_NOERROR;
2249 /**************************************************************************
2250 * widStart [internal]
2252 static DWORD widStart(WORD wDevID)
2254 TRACE("(%u);\n", wDevID);
2255 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2256 WARN("can't start recording !\n");
2257 return MMSYSERR_INVALHANDLE;
2260 WInDev[wDevID].state = WINE_WS_PLAYING;
2261 return MMSYSERR_NOERROR;
2264 /**************************************************************************
2265 * widStop [internal]
2267 static DWORD widStop(WORD wDevID)
2269 WINE_WAVEIN* wwi = &WInDev[wDevID];
2271 TRACE("(%u);\n", wDevID);
2272 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2273 WARN("can't stop !\n");
2274 return MMSYSERR_INVALHANDLE;
2277 if (wwi->state != WINE_WS_STOPPED)
2279 WAVEHDR* lpWaveHdr;
2280 /* do something here to stop recording ??? */
2282 /* return current buffer to app */
2283 lpWaveHdr = wwi->lpQueuePtr;
2284 if (lpWaveHdr)
2286 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
2287 TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2288 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2289 lpWaveHdr->dwFlags |= WHDR_DONE;
2290 widNotifyClient(wwi, WIM_DATA, (DWORD_PTR)lpWaveHdr, 0);
2291 wwi->lpQueuePtr = lpNext;
2294 wwi->state = WINE_WS_STOPPED;
2296 return MMSYSERR_NOERROR;
2299 /**************************************************************************
2300 * widReset [internal]
2302 static DWORD widReset(WORD wDevID)
2304 WINE_WAVEIN* wwi = &WInDev[wDevID];
2305 WAVEHDR* lpWaveHdr;
2307 TRACE("(%u);\n", wDevID);
2308 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2309 WARN("can't reset !\n");
2310 return MMSYSERR_INVALHANDLE;
2313 wwi->state = WINE_WS_STOPPED;
2315 /* return all buffers to the app */
2316 for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
2317 TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2318 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2319 lpWaveHdr->dwFlags |= WHDR_DONE;
2321 widNotifyClient(wwi, WIM_DATA, (DWORD_PTR)lpWaveHdr, 0);
2323 wwi->lpQueuePtr = NULL;
2325 return MMSYSERR_NOERROR;
2328 /**************************************************************************
2329 * widGetNumDevs [internal]
2331 static DWORD widGetNumDevs(void)
2333 return MAX_WAVEINDRV;
2336 /**************************************************************************
2337 * widDevInterfaceSize [internal]
2339 static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
2341 TRACE("(%u, %p)\n", wDevID, dwParam1);
2344 *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2345 NULL, 0 ) * sizeof(WCHAR);
2346 return MMSYSERR_NOERROR;
2349 /**************************************************************************
2350 * widDevInterface [internal]
2352 static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
2354 if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2355 NULL, 0 ) * sizeof(WCHAR))
2357 MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2358 dwParam1, dwParam2 / sizeof(WCHAR));
2359 return MMSYSERR_NOERROR;
2361 return MMSYSERR_INVALPARAM;
2364 /**************************************************************************
2365 * widMessage (WINEJACK.6)
2367 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2368 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
2370 TRACE("(%u, %04X, %08X, %08lX, %08lX);\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2372 switch (wMsg) {
2373 case DRVM_INIT:
2374 return JACK_WaveInit();
2375 case DRVM_EXIT:
2376 return JACK_WaveRelease();
2377 case DRVM_ENABLE:
2378 case DRVM_DISABLE:
2379 /* FIXME: Pretend this is supported */
2380 return 0;
2381 case WIDM_OPEN: return widOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
2382 case WIDM_CLOSE: return widClose (wDevID);
2383 case WIDM_ADDBUFFER: return widAddBuffer (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2384 case WIDM_PREPARE: return MMSYSERR_NOTSUPPORTED;
2385 case WIDM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
2386 case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (LPWAVEINCAPSW)dwParam1, dwParam2);
2387 case WIDM_GETNUMDEVS: return widGetNumDevs();
2388 case WIDM_RESET: return widReset (wDevID);
2389 case WIDM_START: return widStart (wDevID);
2390 case WIDM_STOP: return widStop (wDevID);
2391 case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
2392 case DRV_QUERYDEVICEINTERFACE: return widDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
2393 default:
2394 FIXME("unknown message %d!\n", wMsg);
2397 return MMSYSERR_NOTSUPPORTED;
2400 /**************************************************************************
2401 * DriverProc (WINEJACK.1)
2403 LRESULT CALLBACK JACK_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
2404 LPARAM dwParam1, LPARAM dwParam2)
2406 TRACE("(%08lX, %p, %s (%08X), %08lX, %08lX)\n",
2407 dwDevID, hDriv, wMsg == DRV_LOAD ? "DRV_LOAD" :
2408 wMsg == DRV_FREE ? "DRV_FREE" :
2409 wMsg == DRV_OPEN ? "DRV_OPEN" :
2410 wMsg == DRV_CLOSE ? "DRV_CLOSE" :
2411 wMsg == DRV_ENABLE ? "DRV_ENABLE" :
2412 wMsg == DRV_DISABLE ? "DRV_DISABLE" :
2413 wMsg == DRV_QUERYCONFIGURE ? "DRV_QUERYCONFIGURE" :
2414 wMsg == DRV_CONFIGURE ? "DRV_CONFIGURE" :
2415 wMsg == DRV_INSTALL ? "DRV_INSTALL" :
2416 wMsg == DRV_REMOVE ? "DRV_REMOVE" : "UNKNOWN",
2417 wMsg, dwParam1, dwParam2);
2419 switch(wMsg) {
2420 case DRV_LOAD:
2421 jackhandle = wine_dlopen(SONAME_LIBJACK, RTLD_NOW, NULL, 0);
2422 if (!jackhandle)
2424 FIXME("error loading the jack library %s, please install this library to use jack\n",
2425 SONAME_LIBJACK);
2426 return 0;
2428 return 1;
2429 case DRV_FREE:
2430 if (jackhandle)
2432 TRACE("calling wine_dlclose() on jackhandle\n");
2433 wine_dlclose(jackhandle, NULL, 0);
2434 jackhandle = NULL;
2436 return 1;
2437 case DRV_OPEN:
2438 case DRV_CLOSE:
2439 case DRV_INSTALL:
2440 case DRV_REMOVE:
2441 case DRV_ENABLE:
2442 case DRV_DISABLE:
2443 case DRV_QUERYCONFIGURE:
2444 return 1;
2445 case DRV_CONFIGURE: MessageBoxA(0, "jack audio driver!", "jack driver", MB_OK); return 1;
2446 default:
2447 return 0;