winejack.drv: Add DebugInfo to critical sections
[wine/hacks.git] / dlls / winejack.drv / audio.c
blobc3a2177c873c32cbc8326a1fba63df64a124a940
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"
38 #include <stdlib.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <string.h>
42 #ifdef HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif
45 #include <fcntl.h>
46 #include "windef.h"
47 #include "winbase.h"
48 #include "winnls.h"
49 #include "wingdi.h"
50 #include "winerror.h"
51 #include "mmddk.h"
52 #include "dsound.h"
53 #include "dsdriver.h"
54 #include "jack.h"
55 #include "wine/unicode.h"
56 #include "wine/library.h"
57 #include "wine/debug.h"
59 #ifdef HAVE_JACK_JACK_H
60 #include <jack/jack.h>
61 #endif
64 WINE_DEFAULT_DEBUG_CHANNEL(wave);
66 #ifdef SONAME_LIBJACK
68 #define MAKE_FUNCPTR(f) static typeof(f) * fp_##f = NULL;
70 /* Function pointers for dynamic loading of libjack */
71 /* these are prefixed with "fp_", ie. "fp_jack_client_new" */
72 MAKE_FUNCPTR(jack_activate);
73 MAKE_FUNCPTR(jack_connect);
74 MAKE_FUNCPTR(jack_client_new);
75 MAKE_FUNCPTR(jack_client_close);
76 MAKE_FUNCPTR(jack_deactivate);
77 MAKE_FUNCPTR(jack_set_process_callback);
78 MAKE_FUNCPTR(jack_set_buffer_size_callback);
79 MAKE_FUNCPTR(jack_set_sample_rate_callback);
80 MAKE_FUNCPTR(jack_on_shutdown);
81 MAKE_FUNCPTR(jack_get_sample_rate);
82 MAKE_FUNCPTR(jack_port_register);
83 MAKE_FUNCPTR(jack_port_get_buffer);
84 MAKE_FUNCPTR(jack_get_ports);
85 MAKE_FUNCPTR(jack_port_name);
86 MAKE_FUNCPTR(jack_get_buffer_size);
87 #undef MAKE_FUNCPTR
89 /* define the below to work around a bug in jack where closing a port */
90 /* takes a very long time, so to get around this we actually don't */
91 /* close the port when the device is closed but instead mark the */
92 /* corresponding device as unused */
93 #define JACK_CLOSE_HACK 1
95 typedef jack_default_audio_sample_t sample_t;
96 typedef jack_nframes_t nframes_t;
98 /* only allow 10 output devices through this driver, this ought to be adequate */
99 #define MAX_WAVEOUTDRV (10)
100 #define MAX_WAVEINDRV (10)
102 /* state diagram for waveOut writing:
104 * +---------+-------------+---------------+---------------------------------+
105 * | state | function | event | new state |
106 * +---------+-------------+---------------+---------------------------------+
107 * | | open() | | STOPPED |
108 * | PAUSED | write() | | PAUSED |
109 * | STOPPED | write() | <thrd create> | PLAYING |
110 * | PLAYING | write() | HEADER | PLAYING |
111 * | (other) | write() | <error> | |
112 * | (any) | pause() | PAUSING | PAUSED |
113 * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
114 * | (any) | reset() | RESETTING | STOPPED |
115 * | (any) | close() | CLOSING | CLOSED |
116 * +---------+-------------+---------------+---------------------------------+
119 /* states of the playing device */
120 #define WINE_WS_PLAYING 0
121 #define WINE_WS_PAUSED 1
122 #define WINE_WS_STOPPED 2
123 #define WINE_WS_CLOSED 3
125 typedef struct {
126 volatile int state; /* one of the WINE_WS_ manifest constants */
127 WAVEOPENDESC waveDesc;
128 WORD wFlags;
129 PCMWAVEFORMAT format;
130 WAVEOUTCAPSW caps;
131 WORD wDevID;
132 char interface_name[32];
134 jack_port_t* out_port_l; /* ports for left and right channels */
135 jack_port_t* out_port_r;
136 jack_client_t* client;
137 long sample_rate; /* jack server sample rate */
139 #if JACK_CLOSE_HACK
140 BOOL in_use; /* TRUE if this device is in use */
141 #endif
143 char* sound_buffer;
144 unsigned long buffer_size;
146 DWORD volume_left;
147 DWORD volume_right;
149 LPWAVEHDR lpQueuePtr; /* start of queued WAVEHDRs (waiting to be notified) */
150 LPWAVEHDR lpPlayPtr; /* start of not yet fully played buffers */
151 DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
153 LPWAVEHDR lpLoopPtr; /* pointer of first buffer in loop, if any */
154 DWORD dwLoops; /* private copy of loop counter */
156 DWORD dwPlayedTotal; /* number of bytes actually played since opening */
157 DWORD dwWrittenTotal; /* number of bytes written to jack since opening */
159 DWORD bytesInJack; /* bytes that we wrote during the previous JACK_Callback() */
160 DWORD tickCountMS; /* time in MS of last JACK_Callback() */
162 /* synchronization stuff */
163 CRITICAL_SECTION access_crst;
164 } WINE_WAVEOUT;
166 typedef struct {
167 volatile int state;
168 WAVEOPENDESC waveDesc;
169 WORD wFlags;
170 PCMWAVEFORMAT format;
171 LPWAVEHDR lpQueuePtr;
172 DWORD dwTotalRecorded;
173 WAVEINCAPSW caps;
174 BOOL bTriggerSupport;
175 WORD wDevID;
176 char interface_name[32];
178 jack_port_t* in_port_l; /* ports for left and right channels */
179 jack_port_t* in_port_r;
180 jack_client_t* client;
181 long sample_rate; /* jack server sample rate */
183 #if JACK_CLOSE_HACK
184 BOOL in_use; /* TRUE if this device is in use */
185 #endif
187 char* sound_buffer;
188 unsigned long buffer_size;
190 /* synchronization stuff */
191 CRITICAL_SECTION access_crst;
192 } WINE_WAVEIN;
194 static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV];
195 static WINE_WAVEIN WInDev [MAX_WAVEINDRV ];
197 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
198 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
200 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo);
201 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force);
203 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo);
204 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels);
206 #if JACK_CLOSE_HACK
207 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client);
208 #else
209 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo);
210 #endif
212 #if JACK_CLOSE_HACK
213 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client);
214 #else
215 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi);
216 #endif
218 static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
219 PCMWAVEFORMAT* format)
221 TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%u nChannels=%u nAvgBytesPerSec=%u\n",
222 lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
223 format->wf.nChannels, format->wf.nAvgBytesPerSec);
224 TRACE("Position in bytes=%u\n", position);
226 switch (lpTime->wType) {
227 case TIME_SAMPLES:
228 lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
229 TRACE("TIME_SAMPLES=%u\n", lpTime->u.sample);
230 break;
231 case TIME_MS:
232 lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
233 TRACE("TIME_MS=%u\n", lpTime->u.ms);
234 break;
235 case TIME_SMPTE:
236 lpTime->u.smpte.fps = 30;
237 position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
238 position += (format->wf.nSamplesPerSec / lpTime->u.smpte.fps) - 1; /* round up */
239 lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
240 position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
241 lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
242 lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
243 lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
244 lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
245 lpTime->u.smpte.fps = 30;
246 lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
247 TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
248 lpTime->u.smpte.hour, lpTime->u.smpte.min,
249 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
250 break;
251 default:
252 WARN("Format %d not supported, using TIME_BYTES !\n", lpTime->wType);
253 lpTime->wType = TIME_BYTES;
254 /* fall through */
255 case TIME_BYTES:
256 lpTime->u.cb = position;
257 TRACE("TIME_BYTES=%u\n", lpTime->u.cb);
258 break;
260 return MMSYSERR_NOERROR;
264 /*======================================================================*
265 * Low level WAVE implementation *
266 *======================================================================*/
268 #define SAMPLE_MAX_16BIT 32767.0f
270 /* Alsaplayer function that applies volume changes to a buffer */
271 /* (C) Andy Lo A Foe */
272 /* Length is in terms of 32 bit samples */
273 void volume_effect32(void *buffer, int length, int left, int right)
275 short *data = (short *)buffer;
276 int i, v;
278 if (right == -1) right = left;
280 for(i = 0; i < length; i++) {
281 v = (int) ((*(data) * left) / 100);
282 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
283 v = (int) ((*(data) * right) / 100);
284 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
288 /* move 16 bit mono/stereo to 16 bit stereo */
289 void sample_move_d16_d16(short *dst, short *src,
290 unsigned long nsamples, int nChannels)
292 while(nsamples--)
294 *dst = *src;
295 dst++;
297 if(nChannels == 2) src++;
299 *dst = *src;
300 dst++;
302 src++;
306 /* convert from 16 bit to floating point */
307 /* allow for copying of stereo data with alternating left/right */
308 /* channels to a buffer that will hold a single channel stream */
309 /* nsamples is in terms of 16bit samples */
310 /* src_skip is in terms of 16bit samples */
311 void sample_move_d16_s16 (sample_t *dst, short *src,
312 unsigned long nsamples, unsigned long src_skip)
314 /* ALERT: signed sign-extension portability !!! */
315 while (nsamples--)
317 *dst = (*src) / SAMPLE_MAX_16BIT;
318 dst++;
319 src += src_skip;
323 /* convert from floating point to 16 bit */
324 /* allow for copying of a buffer that will hold a single channel stream */
325 /* to stereo data with alternating left/right channels */
326 /* nsamples is in terms of float samples */
327 /* dst_skip is in terms of 16bit samples */
328 void sample_move_s16_d16 (short *dst, sample_t *src,
329 unsigned long nsamples, unsigned long dst_skip)
331 /* ALERT: signed sign-extension portability !!! */
332 while (nsamples--)
334 *dst = (*src) * SAMPLE_MAX_16BIT;
335 /* TRACE("src=(%.8f,%p) dst=(%d,%p)\n",*src,src,*dst,dst); */
336 dst += dst_skip;
337 src++;
342 /* fill dst buffer with nsamples worth of silence */
343 void sample_silence_dS (sample_t *dst, unsigned long nsamples)
345 /* ALERT: signed sign-extension portability !!! */
346 while (nsamples--)
348 *dst = 0;
349 dst++;
353 /******************************************************************
354 * JACK_callback_wwo
356 /* everytime the jack server wants something from us it calls this
357 function, so we either deliver it some sound to play or deliver it nothing
358 to play */
359 int JACK_callback_wwo (nframes_t nframes, void *arg)
361 sample_t* out_l;
362 sample_t* out_r;
363 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
365 TRACE("wDevID: %u, nframes %u state=%u\n", wwo->wDevID, nframes,wwo->state);
367 if(!wwo->client)
368 ERR("client is closed, this is weird...\n");
370 out_l = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_l, nframes);
371 out_r = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_r, nframes);
373 if(wwo->state == WINE_WS_PLAYING)
375 DWORD jackFramesAvailable = nframes;
376 DWORD outputFramesAvailable;
377 DWORD numFramesToWrite;
379 long written = 0;
380 char* buffer;
382 #if JACK_CLOSE_HACK
383 if(wwo->in_use == FALSE)
385 /* output silence if nothing is being outputted */
386 sample_silence_dS(out_l, nframes);
387 sample_silence_dS(out_r, nframes);
389 return 0;
391 #endif
393 TRACE("wwo.state == WINE_WS_PLAYING\n");
395 /* see if our sound_buffer is large enough to hold the number of frames jack requested */
396 /* Note: sound_buffer is always filled with 16-bit stereo data, even for mono mode */
397 if(wwo->buffer_size < (nframes * sizeof(short) * 2))
399 ERR("for some reason JACK_BufSize() didn't allocate enough memory\n");
400 ERR("allocated %ld bytes, need %d bytes\n", wwo->buffer_size, (nframes * sizeof(short) * 2));
401 return 0;
404 /* while we have jackFramesAvailable and a wave header to be played */
405 while(jackFramesAvailable && wwo->lpPlayPtr)
407 /* find the amount of audio to be played at this time */
408 outputFramesAvailable = (wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset) / wwo->format.wf.nBlockAlign;
410 numFramesToWrite = min(jackFramesAvailable, outputFramesAvailable);
411 TRACE("dwBufferLength=(%d) dwPartialOffset=(%d)\n",wwo->lpPlayPtr->dwBufferLength,wwo->dwPartialOffset);
412 TRACE("outputFramesAvailable == %d, jackFramesAvailable == %d\n", outputFramesAvailable, jackFramesAvailable);
414 buffer = wwo->lpPlayPtr->lpData + wwo->dwPartialOffset;
416 /* convert from mono to stereo if necessary */
417 /* otherwise just memcpy to the output buffer */
419 if(wwo->format.wf.nChannels == 1)
421 sample_move_d16_d16((short*)wwo->sound_buffer + ((nframes - jackFramesAvailable) * sizeof(short)),
422 (short*)buffer, numFramesToWrite, wwo->format.wf.nChannels);
423 } else /* just copy the memory over */
425 memcpy(wwo->sound_buffer + ((nframes - jackFramesAvailable) * wwo->format.wf.nBlockAlign),
426 buffer, numFramesToWrite * wwo->format.wf.nBlockAlign);
429 /* advance to the next wave header if possible, or advance pointer */
430 /* inside of the current header if we haven't completed it */
431 if(numFramesToWrite == outputFramesAvailable)
433 wodHelper_PlayPtrNext(wwo); /* we wrote the whole waveheader, skip to the next one*/
435 else
437 wwo->dwPartialOffset+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* else advance by the bytes we took in to write */
440 written+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* add on what we wrote */
441 jackFramesAvailable-=numFramesToWrite; /* take away what was written in terms of output bytes */
444 wwo->tickCountMS = GetTickCount(); /* record the current time */
445 wwo->dwWrittenTotal+=written; /* update states on wave device */
446 wwo->dwPlayedTotal+=wwo->bytesInJack; /* we must have finished with the last bytes or we wouldn't be back inside of this callback again... */
447 wwo->bytesInJack = written; /* record the bytes inside of jack */
449 /* Now that we have finished filling the buffer either until it is full or until */
450 /* we have run out of application sound data to process, apply volume and output */
451 /* the audio to the jack server */
453 /* apply volume to the buffer */
454 volume_effect32(wwo->sound_buffer, (nframes - jackFramesAvailable), wwo->volume_left, wwo->volume_right);
456 /* convert from stereo 16 bit to single channel 32 bit float */
457 /* for each jack server channel */
458 /* NOTE: we skip over two sample since we want to only get either the left or right channel */
459 sample_move_d16_s16(out_l, (short*)wwo->sound_buffer, (nframes - jackFramesAvailable), 2);
460 sample_move_d16_s16(out_r, (short*)wwo->sound_buffer + 1, (nframes - jackFramesAvailable), 2);
462 /* see if we still have jackBytesLeft here, if we do that means that we
463 ran out of wave data to play and had a buffer underrun, fill in
464 the rest of the space with zero bytes */
465 if(jackFramesAvailable)
467 ERR("buffer underrun of %d frames\n", jackFramesAvailable);
468 sample_silence_dS(out_l + (nframes - jackFramesAvailable), jackFramesAvailable);
469 sample_silence_dS(out_r + (nframes - jackFramesAvailable), jackFramesAvailable);
472 else if(wwo->state == WINE_WS_PAUSED ||
473 wwo->state == WINE_WS_STOPPED ||
474 wwo->state == WINE_WS_CLOSED)
476 /* output silence if nothing is being outputted */
477 sample_silence_dS(out_l, nframes);
478 sample_silence_dS(out_r, nframes);
481 /* notify the client of completed wave headers */
482 EnterCriticalSection(&wwo->access_crst);
483 wodHelper_NotifyCompletions(wwo, FALSE);
484 LeaveCriticalSection(&wwo->access_crst);
486 return 0;
489 /******************************************************************
490 * JACK_bufsize_wwo
492 * Called whenever the jack server changes the max number
493 * of frames passed to JACK_callback
495 int JACK_bufsize_wwo (nframes_t nframes, void *arg)
497 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
498 DWORD buffer_required;
499 TRACE("wDevID=%d\n",wwo->wDevID);
500 TRACE("the maximum buffer size is now %u frames\n", nframes);
502 /* make sure the callback routine has adequate memory */
503 /* see if our buffer is large enough for the data we are writing */
504 /* ie. Buffer_size < (bytes we already wrote + bytes we are going to write in this loop) */
505 EnterCriticalSection(&wwo->access_crst);
507 /* wwo->sound_buffer is always filled with 16-bit stereo data, even for mono streams */
508 buffer_required = nframes * sizeof(short) * 2;
509 TRACE("wwo->buffer_size (%ld) buffer_required (%d).\n", wwo->buffer_size,buffer_required);
510 if(wwo->buffer_size < buffer_required)
512 TRACE("expanding buffer from wwo->buffer_size == %ld, to %d\n",
513 wwo->buffer_size, buffer_required);
514 TRACE("GetProcessHeap() == %p\n", GetProcessHeap());
515 wwo->buffer_size = buffer_required;
517 if (wwo->sound_buffer)
518 wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, wwo->buffer_size);
519 else
520 wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, wwo->buffer_size);
522 /* if we don't have a buffer then error out */
523 if(!wwo->sound_buffer)
525 ERR("error allocating sound_buffer memory\n");
526 LeaveCriticalSection(&wwo->access_crst);
527 return 0;
531 LeaveCriticalSection(&wwo->access_crst);
533 TRACE("ending\n");
535 return 0;
537 /******************************************************************
538 * JACK_bufsize_wwi
540 * Called whenever the jack server changes the max number
541 * of frames passed to JACK_callback
543 int JACK_bufsize_wwi (nframes_t nframes, void *arg)
545 TRACE("the maximum buffer size is now %u frames\n", nframes);
546 return 0;
549 /******************************************************************
550 * JACK_srate
552 int JACK_srate (nframes_t nframes, void *arg)
554 TRACE("the sample rate is now %u/sec\n", nframes);
555 return 0;
559 /******************************************************************
560 * JACK_shutdown_wwo
562 /* if this is called then jack shut down... handle this appropriately */
563 void JACK_shutdown_wwo(void* arg)
565 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
567 wwo->client = 0; /* reset client */
569 TRACE("trying to reconnect after sleeping for a short while...\n");
571 /* lets see if we can't reestablish the connection */
572 Sleep(750); /* pause for a short period of time */
573 if(!JACK_OpenWaveOutDevice(wwo))
575 ERR("unable to reconnect with jack...\n");
579 /******************************************************************
580 * JACK_shutdown_wwi
582 /* if this is called then jack shut down... handle this appropriately */
583 void JACK_shutdown_wwi(void* arg)
585 WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
587 wwi->client = 0; /* reset client */
589 TRACE("trying to reconnect after sleeping for a short while...\n");
591 /* lets see if we can't reestablish the connection */
592 Sleep(750); /* pause for a short period of time */
593 if(!JACK_OpenWaveInDevice(wwi,wwi->format.wf.nChannels))
595 ERR("unable to reconnect with jack...\n");
600 /******************************************************************
601 * JACK_OpenWaveOutDevice
603 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo)
605 const char** ports;
606 int i;
607 char client_name[64];
608 jack_port_t* out_port_l;
609 jack_port_t* out_port_r;
610 jack_client_t* client;
611 int failed = 0;
613 TRACE("creating jack client and setting up callbacks\n");
615 #if JACK_CLOSE_HACK
616 /* see if this device is already open */
617 if(wwo->client)
619 /* if this device is already in use then it is bad for us to be in here */
620 if(wwo->in_use)
621 return 0;
623 TRACE("using existing client\n");
624 wwo->in_use = TRUE;
625 return 1;
627 #endif
629 /* zero out the buffer pointer and the size of the buffer */
630 wwo->sound_buffer = 0;
631 wwo->buffer_size = 0;
633 /* try to become a client of the JACK server */
634 snprintf(client_name, sizeof(client_name), "wine_jack_out_%d", wwo->wDevID);
635 TRACE("client name '%s'\n", client_name);
636 if ((client = fp_jack_client_new (client_name)) == 0)
638 /* jack has problems with shutting down clients, so lets */
639 /* wait a short while and try once more before we give up */
640 Sleep(250);
641 if ((client = fp_jack_client_new (client_name)) == 0)
643 ERR("jack server not running?\n");
644 return 0;
648 /* tell the JACK server to call `JACK_callback_wwo()' whenever
649 there is work to be done. */
650 fp_jack_set_process_callback (client, JACK_callback_wwo, wwo);
652 /* tell the JACK server to call `JACK_bufsize_wwo()' whenever
653 the maximum number of frames that will be passed
654 to `JACK_Callback()' changes */
655 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwo, wwo);
657 /* tell the JACK server to call `srate()' whenever
658 the sample rate of the system changes. */
659 fp_jack_set_sample_rate_callback (client, JACK_srate, wwo);
661 /* tell the JACK server to call `jack_shutdown()' if
662 it ever shuts down, either entirely, or if it
663 just decides to stop calling us. */
664 fp_jack_on_shutdown (client, JACK_shutdown_wwo, wwo);
666 /* display the current sample rate. once the client is activated
667 (see below), you should rely on your own sample rate
668 callback (see above) for this value. */
669 wwo->sample_rate = fp_jack_get_sample_rate(client);
670 TRACE("engine sample rate: %lu\n", wwo->sample_rate);
672 /* create the left and right channel output ports */
673 /* jack's ports are all mono so for stereo you need two */
674 out_port_l = fp_jack_port_register (client, "out_l",
675 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
677 out_port_r = fp_jack_port_register (client, "out_r",
678 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
680 TRACE("Created ports. (%p) (%p)\n",out_port_l, out_port_r);
682 /* save away important values to the WINE_WAVEOUT struct */
683 wwo->client = client;
684 wwo->out_port_l = out_port_l;
685 wwo->out_port_r = out_port_r;
687 #if JACK_CLOSE_HACK
688 wwo->in_use = TRUE; /* mark this device as in use since it now is ;-) */
689 #endif
691 /* set initial buffer size */
692 JACK_bufsize_wwo (fp_jack_get_buffer_size(client),wwo);
694 /* tell the JACK server that we are ready to roll */
695 if (fp_jack_activate (client))
697 ERR( "cannot activate client\n");
698 return 0;
701 TRACE("jack activate.\n");
702 /* figure out what the ports that we want to output on are */
703 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
704 /* this way works if names are changed */
705 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
707 /* display a trace of the output ports we found */
708 for(i = 0; ports[i]; i++)
710 TRACE("ports[%d] = '%s'\n", i, ports[i]);
713 if(!ports)
715 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsInput'\n");
718 /* connect the ports. Note: you can't do this before
719 the client is activated (this may change in the future).
721 /* we want to connect to two ports so we have stereo output ;-) */
723 if(fp_jack_connect(client, fp_jack_port_name(out_port_l), ports[0]))
725 ERR ("cannot connect to output port %d('%s')\n", 0, ports[0]);
726 failed = 1;
729 if(fp_jack_connect(client, fp_jack_port_name(out_port_r), ports[1]))
731 ERR ("cannot connect to output port %d('%s')\n", 1, ports[1]);
732 failed = 1;
735 free(ports); /* free the returned array of ports */
737 /* if something failed we need to shut the client down and return 0 */
738 if(failed)
740 #if JACK_CLOSE_HACK
741 JACK_CloseWaveOutDevice(wwo, TRUE);
742 #else
743 JACK_CloseWaveOutDevice(wwo);
744 #endif
745 return 0;
748 return 1; /* return success */
751 /******************************************************************
752 * JACK_CloseWaveOutDevice
754 * Close the connection to the server cleanly.
755 * If close_client is TRUE we close the client for this device instead of
756 * just marking the device as in_use(JACK_CLOSE_HACK only)
758 #if JACK_CLOSE_HACK
759 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client)
760 #else
761 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
762 #endif
764 #if JACK_CLOSE_HACK
765 TRACE("wDevID: %d, close_client (wwo): %d\n", wwo->wDevID, close_client);
766 #else
767 TRACE("wDevID: %d\n", wwo->wDevID);
768 #endif
770 #if JACK_CLOSE_HACK
771 if(close_client)
773 #endif
774 fp_jack_deactivate(wwo->client); /* supposed to help the jack_client_close() to succeed */
775 fp_jack_client_close (wwo->client);
777 EnterCriticalSection(&wwo->access_crst);
778 wwo->client = 0; /* reset client */
779 HeapFree(GetProcessHeap(), 0, wwo->sound_buffer); /* free buffer memory */
780 wwo->sound_buffer = 0;
781 wwo->buffer_size = 0; /* zero out size of the buffer */
782 LeaveCriticalSection(&wwo->access_crst);
783 #if JACK_CLOSE_HACK
784 } else
786 EnterCriticalSection(&wwo->access_crst);
787 TRACE("setting in_use to FALSE\n");
788 wwo->in_use = FALSE;
789 LeaveCriticalSection(&wwo->access_crst);
791 #endif
794 /******************************************************************
795 * JACK_CloseWaveInDevice
797 * Close the connection to the server cleanly.
798 * If close_client is TRUE we close the client for this device instead of
799 * just marking the device as in_use(JACK_CLOSE_HACK only)
801 #if JACK_CLOSE_HACK
802 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client)
803 #else
804 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi)
805 #endif
807 #if JACK_CLOSE_HACK
808 TRACE("wDevID: %d, close_client (wwi): %d\n", wwi->wDevID, close_client);
809 #else
810 TRACE("wDevID: %d\n", wwi->wDevID);
811 #endif
813 #if JACK_CLOSE_HACK
814 if(close_client)
816 #endif
817 fp_jack_deactivate(wwi->client); /* supposed to help the jack_client_close() to succeed */
818 fp_jack_client_close (wwi->client);
820 EnterCriticalSection(&wwi->access_crst);
821 wwi->client = 0; /* reset client */
822 HeapFree(GetProcessHeap(), 0, wwi->sound_buffer); /* free buffer memory */
823 wwi->sound_buffer = 0;
824 wwi->buffer_size = 0; /* zero out size of the buffer */
825 LeaveCriticalSection(&wwi->access_crst);
826 #if JACK_CLOSE_HACK
827 } else
829 EnterCriticalSection(&wwi->access_crst);
830 TRACE("setting in_use to FALSE\n");
831 wwi->in_use = FALSE;
832 LeaveCriticalSection(&wwi->access_crst);
834 #endif
837 /******************************************************************
838 * JACK_WaveRelease
842 LONG JACK_WaveRelease(void)
844 int iDevice;
846 TRACE("closing all open waveout devices\n");
848 /* close all open output devices */
849 for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
851 TRACE("iDevice == %d\n", iDevice);
852 if(WOutDev[iDevice].client)
854 #if JACK_CLOSE_HACK
855 JACK_CloseWaveOutDevice(&WOutDev[iDevice], TRUE); /* close the device, FORCE the client to close */
856 #else
857 JACK_CloseWaveOutDevice(&WOutDev[iDevice]); /* close the device, FORCE the client to close */
858 #endif
859 #if JACK_CLOSE_HACK
860 if(WOutDev[iDevice].in_use) {
861 #endif
862 WOutDev[iDevice].access_crst.DebugInfo->Spare[0] = 0;
863 DeleteCriticalSection(&(WOutDev[iDevice].access_crst)); /* delete the critical section */
864 #if JACK_CLOSE_HACK
866 #endif
870 TRACE("closing all open wavein devices\n");
872 /* close all open input devices */
873 for(iDevice = 0; iDevice < MAX_WAVEINDRV; iDevice++)
875 TRACE("iDevice == %d\n", iDevice);
876 if(WInDev[iDevice].client)
878 #if JACK_CLOSE_HACK
879 JACK_CloseWaveInDevice(&WInDev[iDevice], TRUE); /* close the device, FORCE the client to close */
880 #else
881 JACK_CloseWaveInDevice(&WInDev[iDevice]); /* close the device, FORCE the client to close */
882 #endif
883 #if JACK_CLOSE_HACK
884 if(WOutDev[iDevice].in_use) {
885 #endif
886 WInDev[iDevice].access_crst.DebugInfo->Spare[0] = 0;
887 DeleteCriticalSection(&(WInDev[iDevice].access_crst)); /* delete the critical section */
888 #if JACK_CLOSE_HACK
890 #endif
894 TRACE("returning 1\n");
896 return 1;
899 /******************************************************************
900 * JACK_WaveInit
902 * Initialize internal structures from JACK server info
904 LONG JACK_WaveInit(void)
906 int i;
907 CHAR szPname[MAXPNAMELEN];
909 TRACE("called\n");
911 /* setup function pointers */
912 #define LOAD_FUNCPTR(f) if((fp_##f = wine_dlsym(jackhandle, #f, NULL, 0)) == NULL) goto sym_not_found;
913 LOAD_FUNCPTR(jack_activate);
914 LOAD_FUNCPTR(jack_connect);
915 LOAD_FUNCPTR(jack_client_new);
916 LOAD_FUNCPTR(jack_client_close);
917 LOAD_FUNCPTR(jack_deactivate);
918 LOAD_FUNCPTR(jack_set_process_callback);
919 LOAD_FUNCPTR(jack_set_buffer_size_callback);
920 LOAD_FUNCPTR(jack_set_sample_rate_callback);
921 LOAD_FUNCPTR(jack_on_shutdown);
922 LOAD_FUNCPTR(jack_get_sample_rate);
923 LOAD_FUNCPTR(jack_port_register);
924 LOAD_FUNCPTR(jack_port_get_buffer);
925 LOAD_FUNCPTR(jack_get_ports);
926 LOAD_FUNCPTR(jack_port_name);
927 LOAD_FUNCPTR(jack_get_buffer_size);
928 #undef LOAD_FUNCPTR
930 /* start with output device */
932 for (i = 0; i < MAX_WAVEOUTDRV; ++i)
934 WOutDev[i].client = 0; /* initialize the client to 0 */
936 #if JACK_CLOSE_HACK
937 WOutDev[i].in_use = FALSE;
938 WInDev[i].in_use = FALSE;
939 #endif
941 memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps));
943 WOutDev[i].caps.wMid = 0x00FF; /* Manufac ID */
944 WOutDev[i].caps.wPid = 0x0001; /* Product ID */
945 snprintf(szPname, sizeof(szPname), "JACK WaveOut %d", i);
946 MultiByteToWideChar(CP_ACP, 0, szPname, -1, WOutDev[i].caps.szPname, sizeof(WOutDev[i].caps.szPname)/sizeof(WCHAR));
947 snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "winejack: %d", i);
949 WOutDev[i].caps.vDriverVersion = 0x0100;
950 WOutDev[i].caps.dwFormats = 0x00000000;
951 WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
953 WOutDev[i].caps.wChannels = 2;
954 WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;
956 /* NOTE: we don't support any 8 bit modes so note that */
957 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
958 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
959 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
960 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
961 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
962 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
963 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
964 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
965 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
966 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
967 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
968 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
971 /* then do input device */
972 for (i = 0; i < MAX_WAVEINDRV; ++i)
974 /* TODO: we should initialize read stuff here */
975 memset(&WInDev[i].caps, 0, sizeof(WInDev[i].caps));
977 WInDev[i].caps.wMid = 0x00FF;
978 WInDev[i].caps.wPid = 0x0001;
979 snprintf(szPname, sizeof(szPname), "JACK WaveIn %d", i);
980 MultiByteToWideChar(CP_ACP, 0, szPname, -1, WInDev[i].caps.szPname, sizeof(WInDev[i].caps.szPname)/sizeof(WCHAR));
981 snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "winejack: %d", i);
983 WInDev[i].caps.vDriverVersion = 0x0100;
985 WInDev[i].caps.wChannels = 0x2;
986 /* NOTE: we don't support any 8 bit modes so note that */
987 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
988 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
989 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
990 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
991 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
992 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
993 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
994 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
995 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
996 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
997 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
998 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
999 WInDev[i].caps.wReserved1 = 0;
1002 return 1; /* return success */
1004 /* error path for function pointer loading errors */
1005 sym_not_found:
1006 WINE_MESSAGE(
1007 "Wine cannot find certain functions that it needs inside the jack"
1008 "library. To enable Wine to use the jack audio server please "
1009 "install libjack\n");
1010 wine_dlclose(jackhandle, NULL, 0);
1011 jackhandle = NULL;
1012 return FALSE;
1015 /*======================================================================*
1016 * Low level WAVE OUT implementation *
1017 *======================================================================*/
1019 /**************************************************************************
1020 * wodNotifyClient [internal]
1022 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1024 TRACE("wMsg = 0x%04x dwParm1 = %04X dwParam2 = %04X\n", wMsg, dwParam1, dwParam2);
1026 switch (wMsg) {
1027 case WOM_OPEN:
1028 case WOM_CLOSE:
1029 case WOM_DONE:
1030 if (wwo->wFlags != DCB_NULL &&
1031 !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags,
1032 (HDRVR)wwo->waveDesc.hWave, wMsg, wwo->waveDesc.dwInstance,
1033 dwParam1, dwParam2))
1035 WARN("can't notify client !\n");
1036 return MMSYSERR_ERROR;
1038 break;
1039 default:
1040 FIXME("Unknown callback message %u\n", wMsg);
1041 return MMSYSERR_INVALPARAM;
1043 return MMSYSERR_NOERROR;
1046 /**************************************************************************
1047 * wodHelper_BeginWaveHdr [internal]
1049 * Makes the specified lpWaveHdr the currently playing wave header.
1050 * If the specified wave header is a begin loop and we're not already in
1051 * a loop, setup the loop.
1053 static void wodHelper_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
1055 EnterCriticalSection(&wwo->access_crst);
1057 wwo->lpPlayPtr = lpWaveHdr;
1059 if (!lpWaveHdr)
1061 LeaveCriticalSection(&wwo->access_crst);
1062 return;
1065 if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)
1067 if (wwo->lpLoopPtr)
1069 WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1070 TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1071 } else
1073 TRACE("Starting loop (%dx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
1074 wwo->lpLoopPtr = lpWaveHdr;
1075 /* Windows does not touch WAVEHDR.dwLoops,
1076 * so we need to make an internal copy */
1077 wwo->dwLoops = lpWaveHdr->dwLoops;
1080 wwo->dwPartialOffset = 0;
1082 LeaveCriticalSection(&wwo->access_crst);
1086 /**************************************************************************
1087 * wodHelper_PlayPtrNext [internal]
1089 * Advance the play pointer to the next waveheader, looping if required.
1091 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
1093 LPWAVEHDR lpWaveHdr;
1095 EnterCriticalSection(&wwo->access_crst);
1097 lpWaveHdr = wwo->lpPlayPtr;
1099 wwo->dwPartialOffset = 0;
1100 if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr)
1102 /* We're at the end of a loop, loop if required */
1103 if (--wwo->dwLoops > 0)
1105 wwo->lpPlayPtr = wwo->lpLoopPtr;
1106 } else
1108 /* Handle overlapping loops correctly */
1109 if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
1110 FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
1111 /* shall we consider the END flag for the closing loop or for
1112 * the opening one or for both ???
1113 * code assumes for closing loop only
1115 } else
1117 lpWaveHdr = lpWaveHdr->lpNext;
1119 wwo->lpLoopPtr = NULL;
1120 wodHelper_BeginWaveHdr(wwo, lpWaveHdr);
1122 } else
1124 /* We're not in a loop. Advance to the next wave header */
1125 TRACE("not inside of a loop, advancing to next wave header\n");
1126 wodHelper_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
1129 LeaveCriticalSection(&wwo->access_crst);
1131 return lpWaveHdr;
1134 /* if force is TRUE then notify the client that all the headers were completed */
1135 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
1137 LPWAVEHDR lpWaveHdr;
1138 DWORD retval;
1140 TRACE("called\n");
1142 EnterCriticalSection(&wwo->access_crst);
1144 /* Start from lpQueuePtr and keep notifying until:
1145 * - we hit an unwritten wavehdr
1146 * - we hit the beginning of a running loop
1147 * - we hit a wavehdr which hasn't finished playing
1149 while ((lpWaveHdr = wwo->lpQueuePtr) &&
1150 (force ||
1151 (lpWaveHdr != wwo->lpPlayPtr &&
1152 lpWaveHdr != wwo->lpLoopPtr)))
1154 wwo->lpQueuePtr = lpWaveHdr->lpNext;
1156 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1157 lpWaveHdr->dwFlags |= WHDR_DONE;
1158 TRACE("notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) dwFlags=(%d)\n",
1159 lpWaveHdr, wwo->lpPlayPtr, lpWaveHdr->dwFlags);
1161 wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
1163 TRACE("Not notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) lpLoopPtr=(%p)\n",
1164 lpWaveHdr, wwo->lpPlayPtr, wwo->lpLoopPtr);
1165 retval = (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr !=
1166 wwo->lpLoopPtr) ? 0 : INFINITE;
1168 LeaveCriticalSection(&wwo->access_crst);
1170 return retval;
1173 /**************************************************************************
1174 * wodHelper_Reset [internal]
1176 * Resets current output stream.
1178 static void wodHelper_Reset(WINE_WAVEOUT* wwo, BOOL reset)
1180 EnterCriticalSection(&wwo->access_crst);
1182 /* updates current notify list */
1183 wodHelper_NotifyCompletions(wwo, FALSE);
1185 if (reset)
1187 /* remove all wave headers and notify client that all headers were completed */
1188 wodHelper_NotifyCompletions(wwo, TRUE);
1190 wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
1191 wwo->state = WINE_WS_STOPPED;
1192 wwo->dwPlayedTotal = wwo->dwWrittenTotal = wwo->bytesInJack = 0;
1194 wwo->dwPartialOffset = 0; /* Clear partial wavehdr */
1195 } else
1197 if (wwo->lpLoopPtr)
1199 /* complicated case, not handled yet (could imply modifying the loop counter) */
1200 FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
1201 wwo->lpPlayPtr = wwo->lpLoopPtr;
1202 wwo->dwPartialOffset = 0;
1203 wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
1204 } else
1206 LPWAVEHDR ptr;
1207 DWORD sz = wwo->dwPartialOffset;
1209 /* reset all the data as if we had written only up to lpPlayedTotal bytes */
1210 /* compute the max size playable from lpQueuePtr */
1211 for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext)
1213 sz += ptr->dwBufferLength;
1216 /* because the reset lpPlayPtr will be lpQueuePtr */
1217 if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("doh\n");
1218 wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal);
1219 wwo->dwWrittenTotal = wwo->dwPlayedTotal;
1220 wwo->lpPlayPtr = wwo->lpQueuePtr;
1223 wwo->state = WINE_WS_PAUSED;
1226 LeaveCriticalSection(&wwo->access_crst);
1229 /**************************************************************************
1230 * wodGetDevCaps [internal]
1232 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSW lpCaps, DWORD dwSize)
1234 TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
1236 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1238 if (wDevID >= MAX_WAVEOUTDRV)
1240 TRACE("MAX_WAVOUTDRV reached !\n");
1241 return MMSYSERR_BADDEVICEID;
1244 TRACE("dwSupport=(0x%x), dwFormats=(0x%x)\n", WOutDev[wDevID].caps.dwSupport, WOutDev[wDevID].caps.dwFormats);
1245 memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1246 return MMSYSERR_NOERROR;
1249 /**************************************************************************
1250 * wodOpen [internal]
1252 * NOTE: doesn't it seem like there is a race condition if you try to open
1253 * the same device twice?
1255 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1257 WINE_WAVEOUT* wwo;
1258 DWORD retval;
1260 TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
1261 if (lpDesc == NULL)
1263 WARN("Invalid Parameter !\n");
1264 return MMSYSERR_INVALPARAM;
1266 if (wDevID >= MAX_WAVEOUTDRV) {
1267 TRACE("MAX_WAVOUTDRV reached !\n");
1268 return MMSYSERR_BADDEVICEID;
1271 #if JACK_CLOSE_HACK
1272 if(WOutDev[wDevID].client && WOutDev[wDevID].in_use)
1273 #else
1274 if(WOutDev[wDevID].client)
1275 #endif
1277 TRACE("device %d already allocated\n", wDevID);
1278 return MMSYSERR_ALLOCATED;
1281 /* Only the PCM format is supported so far...
1282 * Also we only support 16 bit mode.
1284 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1285 lpDesc->lpFormat->nChannels == 0 ||
1286 lpDesc->lpFormat->nSamplesPerSec == 0 ||
1287 lpDesc->lpFormat->wBitsPerSample != 16)
1289 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
1290 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1291 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
1292 return WAVERR_BADFORMAT;
1295 if (dwFlags & WAVE_FORMAT_QUERY)
1297 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
1298 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1299 lpDesc->lpFormat->nSamplesPerSec);
1300 return MMSYSERR_NOERROR;
1303 wwo = &WOutDev[wDevID];
1304 wwo->wDevID = wDevID;
1306 /* Set things up before we call JACK_OpenWaveOutDevice because */
1307 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
1308 /* even returns and we want to be initialized before then */
1309 wwo->state = WINE_WS_STOPPED; /* start in a stopped state */
1310 wwo->dwPlayedTotal = 0; /* zero out these totals */
1311 wwo->dwWrittenTotal = 0;
1312 wwo->bytesInJack = 0;
1313 wwo->tickCountMS = 0;
1315 /* Initialize volume to full level */
1316 wwo->volume_left = 100;
1317 wwo->volume_right = 100;
1319 InitializeCriticalSection(&wwo->access_crst); /* initialize the critical section */
1320 wwo->access_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_WAVEOUT.access_crst");
1321 EnterCriticalSection(&wwo->access_crst);
1323 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
1325 wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1327 wwo->waveDesc = *lpDesc;
1328 memcpy(&wwo->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1330 /* open up jack ports for this device */
1331 if (!JACK_OpenWaveOutDevice(&WOutDev[wDevID]))
1333 ERR("JACK_OpenWaveOutDevice(%d) failed\n", wDevID);
1334 LeaveCriticalSection(&wwo->access_crst);
1335 wwo->access_crst.DebugInfo->Spare[0] = 0;
1336 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1337 return MMSYSERR_ERROR; /* return unspecified error */
1340 LeaveCriticalSection(&wwo->access_crst);
1342 /* display the current wave format */
1343 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%u, nSamplesPerSec=%u, nChannels=%u nBlockAlign=%u!\n",
1344 wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
1345 wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1346 wwo->format.wf.nBlockAlign);
1348 /* make sure that we have the same sample rate in our audio stream */
1349 /* as we do in the jack server */
1350 if(wwo->format.wf.nSamplesPerSec != wwo->sample_rate)
1352 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%d'\n",
1353 wwo->sample_rate, wwo->format.wf.nSamplesPerSec);
1355 #if JACK_CLOSE_HACK
1356 JACK_CloseWaveOutDevice(wwo, FALSE); /* close this device, don't force the client to close */
1357 #else
1358 JACK_CloseWaveOutDevice(wwo); /* close this device */
1359 #endif
1360 wwo->access_crst.DebugInfo->Spare[0] = 0;
1361 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1362 return WAVERR_BADFORMAT;
1365 /* check for an invalid number of bits per sample */
1366 if (wwo->format.wBitsPerSample == 0)
1368 WARN("Resetting zeroed wBitsPerSample\n");
1369 wwo->format.wBitsPerSample = 8 *
1370 (wwo->format.wf.nAvgBytesPerSec /
1371 wwo->format.wf.nSamplesPerSec) /
1372 wwo->format.wf.nChannels;
1375 EnterCriticalSection(&wwo->access_crst);
1376 retval = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
1377 LeaveCriticalSection(&wwo->access_crst);
1379 return retval;
1382 /**************************************************************************
1383 * wodClose [internal]
1385 static DWORD wodClose(WORD wDevID)
1387 DWORD ret = MMSYSERR_NOERROR;
1388 WINE_WAVEOUT* wwo;
1390 TRACE("(%u);\n", wDevID);
1392 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1394 WARN("bad device ID !\n");
1395 return MMSYSERR_BADDEVICEID;
1398 wwo = &WOutDev[wDevID];
1399 if (wwo->lpQueuePtr)
1401 WARN("buffers still playing !\n");
1402 ret = WAVERR_STILLPLAYING;
1403 } else
1405 /* sanity check: this should not happen since the device must have been reset before */
1406 if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
1408 wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
1410 #if JACK_CLOSE_HACK
1411 JACK_CloseWaveOutDevice(wwo, FALSE); /* close the jack device, DO NOT force the client to close */
1412 #else
1413 JACK_CloseWaveOutDevice(wwo); /* close the jack device */
1414 #endif
1415 wwo->access_crst.DebugInfo->Spare[0] = 0;
1416 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1418 ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
1421 return ret;
1425 /**************************************************************************
1426 * wodWrite [internal]
1429 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1431 LPWAVEHDR*wh;
1432 WINE_WAVEOUT *wwo;
1434 TRACE("(%u, %p, %08X);\n", wDevID, lpWaveHdr, dwSize);
1436 /* first, do the sanity checks... */
1437 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1439 WARN("bad dev ID !\n");
1440 return MMSYSERR_BADDEVICEID;
1443 wwo = &WOutDev[wDevID];
1445 if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1447 TRACE("unprepared\n");
1448 return WAVERR_UNPREPARED;
1451 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1453 TRACE("still playing\n");
1454 return WAVERR_STILLPLAYING;
1457 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1458 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1459 lpWaveHdr->lpNext = 0;
1461 EnterCriticalSection(&wwo->access_crst);
1463 /* insert buffer at the end of queue */
1464 for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
1465 *wh = lpWaveHdr;
1467 if (!wwo->lpPlayPtr)
1468 wodHelper_BeginWaveHdr(wwo,lpWaveHdr);
1469 if (wwo->state == WINE_WS_STOPPED)
1470 wwo->state = WINE_WS_PLAYING;
1471 LeaveCriticalSection(&wwo->access_crst);
1473 return MMSYSERR_NOERROR;
1476 /**************************************************************************
1477 * wodPause [internal]
1479 static DWORD wodPause(WORD wDevID)
1481 TRACE("(%u);!\n", wDevID);
1483 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1485 WARN("bad device ID !\n");
1486 return MMSYSERR_BADDEVICEID;
1489 TRACE("[3-PAUSING]\n");
1491 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1492 wodHelper_Reset(&WOutDev[wDevID], FALSE);
1493 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1495 return MMSYSERR_NOERROR;
1498 /**************************************************************************
1499 * wodRestart [internal]
1501 static DWORD wodRestart(WORD wDevID)
1503 TRACE("(%u);\n", wDevID);
1505 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1507 WARN("bad device ID !\n");
1508 return MMSYSERR_BADDEVICEID;
1511 if (WOutDev[wDevID].state == WINE_WS_PAUSED)
1513 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1514 WOutDev[wDevID].state = WINE_WS_PLAYING;
1515 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1518 return MMSYSERR_NOERROR;
1521 /**************************************************************************
1522 * wodReset [internal]
1524 static DWORD wodReset(WORD wDevID)
1526 TRACE("(%u);\n", wDevID);
1528 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1530 WARN("bad device ID !\n");
1531 return MMSYSERR_BADDEVICEID;
1534 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1535 wodHelper_Reset(&WOutDev[wDevID], TRUE);
1536 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1538 return MMSYSERR_NOERROR;
1541 /**************************************************************************
1542 * wodGetPosition [internal]
1544 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1546 DWORD val;
1547 WINE_WAVEOUT* wwo;
1548 DWORD elapsedMS;
1550 TRACE("(%u, %p, %u);\n", wDevID, lpTime, uSize);
1552 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1554 WARN("bad device ID !\n");
1555 return MMSYSERR_BADDEVICEID;
1558 /* if null pointer to time structure return error */
1559 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1561 wwo = &WOutDev[wDevID];
1563 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1564 val = wwo->dwPlayedTotal;
1565 elapsedMS = GetTickCount() - wwo->tickCountMS;
1566 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1568 /* account for the bytes played since the last JACK_Callback() */
1569 val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
1571 return bytes_to_mmtime(lpTime, val, &wwo->format);
1574 /**************************************************************************
1575 * wodBreakLoop [internal]
1577 static DWORD wodBreakLoop(WORD wDevID)
1579 TRACE("(%u);\n", wDevID);
1581 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1583 WARN("bad device ID !\n");
1584 return MMSYSERR_BADDEVICEID;
1587 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1589 if (WOutDev[wDevID].state == WINE_WS_PLAYING && WOutDev[wDevID].lpLoopPtr != NULL)
1591 /* ensure exit at end of current loop */
1592 WOutDev[wDevID].dwLoops = 1;
1595 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1597 return MMSYSERR_NOERROR;
1600 /**************************************************************************
1601 * wodGetVolume [internal]
1603 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1605 DWORD left, right;
1607 left = WOutDev[wDevID].volume_left;
1608 right = WOutDev[wDevID].volume_right;
1610 TRACE("(%u, %p);\n", wDevID, lpdwVol);
1612 *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
1613 16);
1615 return MMSYSERR_NOERROR;
1618 /**************************************************************************
1619 * wodSetVolume [internal]
1621 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1623 DWORD left, right;
1625 left = (LOWORD(dwParam) * 100) / 0xFFFFl;
1626 right = (HIWORD(dwParam) * 100) / 0xFFFFl;
1628 TRACE("(%u, %08X);\n", wDevID, dwParam);
1630 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1632 WOutDev[wDevID].volume_left = left;
1633 WOutDev[wDevID].volume_right = right;
1635 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1637 return MMSYSERR_NOERROR;
1640 /**************************************************************************
1641 * wodGetNumDevs [internal]
1643 static DWORD wodGetNumDevs(void)
1645 return MAX_WAVEOUTDRV;
1648 /**************************************************************************
1649 * wodDevInterfaceSize [internal]
1651 static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
1653 TRACE("(%u, %p)\n", wDevID, dwParam1);
1655 *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1656 NULL, 0 ) * sizeof(WCHAR);
1657 return MMSYSERR_NOERROR;
1660 /**************************************************************************
1661 * wodDevInterface [internal]
1663 static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
1665 if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1666 NULL, 0 ) * sizeof(WCHAR))
1668 MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1669 dwParam1, dwParam2 / sizeof(WCHAR));
1670 return MMSYSERR_NOERROR;
1672 return MMSYSERR_INVALPARAM;
1675 /**************************************************************************
1676 * wodMessage (WINEJACK.7)
1678 DWORD WINAPI JACK_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
1679 DWORD dwParam1, DWORD dwParam2)
1681 TRACE("(%u, %04X, %08X, %08X, %08X);\n",
1682 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1684 switch (wMsg) {
1685 case DRVM_INIT:
1686 case DRVM_EXIT:
1687 case DRVM_ENABLE:
1688 case DRVM_DISABLE:
1689 /* FIXME: Pretend this is supported */
1690 return 0;
1691 case WODM_OPEN: return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1692 case WODM_CLOSE: return wodClose(wDevID);
1693 case WODM_WRITE: return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1694 case WODM_PAUSE: return wodPause(wDevID);
1695 case WODM_GETPOS: return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1696 case WODM_BREAKLOOP: return wodBreakLoop(wDevID);
1697 case WODM_PREPARE: return MMSYSERR_NOTSUPPORTED;
1698 case WODM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
1699 case WODM_GETDEVCAPS: return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSW)dwParam1, dwParam2);
1700 case WODM_GETNUMDEVS: return wodGetNumDevs();
1701 case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED;
1702 case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED;
1703 case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1704 case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1705 case WODM_GETVOLUME: return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1706 case WODM_SETVOLUME: return wodSetVolume(wDevID, dwParam1);
1707 case WODM_RESTART: return wodRestart(wDevID);
1708 case WODM_RESET: return wodReset(wDevID);
1710 case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
1711 case DRV_QUERYDEVICEINTERFACE: return wodDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
1712 case DRV_QUERYDSOUNDIFACE: return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1);
1713 case DRV_QUERYDSOUNDDESC: return wodDsDesc(wDevID, (PDSDRIVERDESC)dwParam1);
1714 default:
1715 FIXME("unknown message %d!\n", wMsg);
1717 return MMSYSERR_NOTSUPPORTED;
1720 /*======================================================================*
1721 * Low level DSOUND implementation *
1722 *======================================================================*/
1724 typedef struct IDsDriverImpl IDsDriverImpl;
1725 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;
1727 struct IDsDriverImpl
1729 /* IUnknown fields */
1730 const IDsDriverVtbl *lpVtbl;
1731 DWORD ref;
1732 /* IDsDriverImpl fields */
1733 UINT wDevID;
1734 IDsDriverBufferImpl*primary;
1737 struct IDsDriverBufferImpl
1739 /* IUnknown fields */
1740 const IDsDriverBufferVtbl *lpVtbl;
1741 DWORD ref;
1742 /* IDsDriverBufferImpl fields */
1743 IDsDriverImpl* drv;
1744 DWORD buflen;
1747 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
1749 /* we can't perform memory mapping as we don't have a file stream
1750 interface with jack like we do with oss */
1751 MESSAGE("This sound card's driver does not support direct access\n");
1752 MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
1753 return MMSYSERR_NOTSUPPORTED;
1756 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
1758 memset(desc, 0, sizeof(*desc));
1759 strcpy(desc->szDesc, "Wine jack DirectSound Driver");
1760 strcpy(desc->szDrvname, "winejack.drv");
1761 return MMSYSERR_NOERROR;
1764 /*======================================================================*
1765 * Low level WAVE IN implementation *
1766 *======================================================================*/
1768 /**************************************************************************
1769 * widNotifyClient [internal]
1771 static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1773 TRACE("wMsg = 0x%04x dwParm1 = %04X dwParam2 = %04X\n", wMsg, dwParam1, dwParam2);
1775 switch (wMsg) {
1776 case WIM_OPEN:
1777 case WIM_CLOSE:
1778 case WIM_DATA:
1779 if (wwi->wFlags != DCB_NULL &&
1780 !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
1781 (HDRVR)wwi->waveDesc.hWave, wMsg, wwi->waveDesc.dwInstance,
1782 dwParam1, dwParam2))
1784 WARN("can't notify client !\n");
1785 return MMSYSERR_ERROR;
1787 break;
1788 default:
1789 FIXME("Unknown callback message %u\n", wMsg);
1790 return MMSYSERR_INVALPARAM;
1792 return MMSYSERR_NOERROR;
1795 /******************************************************************
1796 * JACK_callback_wwi
1798 /* everytime the jack server wants something from us it calls this
1799 function */
1800 int JACK_callback_wwi (nframes_t nframes, void *arg)
1802 sample_t* in_l;
1803 sample_t* in_r = 0;
1804 WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
1806 TRACE("wDevID: %u, nframes %u\n", wwi->wDevID, nframes);
1808 if(!wwi->client)
1809 ERR("client is closed, this is weird...\n");
1811 in_l = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_l, nframes);
1813 if (wwi->in_port_r)
1814 in_r = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_r, nframes);
1816 EnterCriticalSection(&wwi->access_crst);
1818 if((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
1820 LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
1821 nframes_t jackFramesLeft = nframes;
1823 #if JACK_CLOSE_HACK
1824 if(wwi->in_use == FALSE)
1826 /* do nothing if nothing is being recorded */
1827 LeaveCriticalSection(&wwi->access_crst);
1828 return 0;
1830 #endif
1832 TRACE("wwi.state == WINE_WS_PLAYING\n");
1834 while (lpWaveHdr && jackFramesLeft)
1836 DWORD waveHdrFramesLeft = (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded) / (sizeof(short) * wwi->format.wf.nChannels);
1837 DWORD numFrames = min (jackFramesLeft, waveHdrFramesLeft);
1839 TRACE ("dwBufferLength=(%u) dwBytesRecorded=(%d)\n", lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
1840 TRACE ("jackFramesLeft=(%u) waveHdrFramesLeft=(%u)\n", jackFramesLeft, waveHdrFramesLeft);
1842 if (!in_r) {
1843 /* mono */
1844 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded), in_l+(nframes-jackFramesLeft), numFrames, 1);
1845 } else {
1846 /* stereo */
1847 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded),
1848 in_l+(nframes-jackFramesLeft), numFrames, 2);
1849 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded + sizeof(short)),
1850 in_r+(nframes-jackFramesLeft), numFrames, 2);
1853 lpWaveHdr->dwBytesRecorded += (numFrames * sizeof(short) * wwi->format.wf.nChannels );
1854 jackFramesLeft -= numFrames;
1856 if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
1858 /* must copy the value of next waveHdr, because we have no idea of what
1859 * will be done with the content of lpWaveHdr in callback
1861 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
1863 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1864 lpWaveHdr->dwFlags |= WHDR_DONE;
1866 TRACE("WaveHdr full. dwBytesRecorded=(%u) dwFlags=(0x%x)\n",lpWaveHdr->dwBytesRecorded,lpWaveHdr->dwFlags);
1868 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1870 lpWaveHdr = wwi->lpQueuePtr = lpNext;
1873 TRACE ("jackFramesLeft=(%u) lpWaveHdr=(%p)\n", jackFramesLeft, lpWaveHdr);
1874 if (jackFramesLeft > 0) { WARN("Record buffer ran out of WaveHdrs\n"); }
1877 LeaveCriticalSection(&wwi->access_crst);
1879 return 0;
1882 /******************************************************************
1883 * JACK_OpenWaveInDevice
1885 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels)
1887 const char** ports;
1888 int i;
1889 char client_name[64];
1890 jack_port_t* in_port_l;
1891 jack_port_t* in_port_r = 0;
1892 jack_client_t* client;
1893 int failed = 0;
1895 TRACE("creating jack client and setting up callbacks\n");
1897 if ((nChannels == 0) || (nChannels > 2)) {
1898 ERR ("nChannels = (%d), but we only support mono or stereo.\n", nChannels);
1899 return 0;
1902 #if JACK_CLOSE_HACK
1903 /* see if this device is already open */
1904 if(wwi->client)
1906 /* if this device is already in use then it is bad for us to be in here */
1907 if(wwi->in_use)
1908 return 0;
1910 TRACE("using existing client\n");
1911 wwi->in_use = TRUE;
1912 return 1;
1914 #endif
1916 /* zero out the buffer pointer and the size of the buffer */
1917 wwi->sound_buffer = 0;
1918 wwi->buffer_size = 0;
1920 /* try to become a client of the JACK server */
1921 snprintf(client_name, sizeof(client_name), "wine_jack_in_%d", wwi->wDevID);
1922 TRACE("client name '%s'\n", client_name);
1923 if ((client = fp_jack_client_new (client_name)) == 0)
1925 /* jack has problems with shutting down clients, so lets */
1926 /* wait a short while and try once more before we give up */
1927 Sleep(250);
1928 if ((client = fp_jack_client_new (client_name)) == 0)
1930 ERR("jack server not running?\n");
1931 return 0;
1934 wwi->client = client;
1936 /* tell the JACK server to call `JACK_wwi_callback()' whenever
1937 there is work to be done. */
1938 fp_jack_set_process_callback (client, JACK_callback_wwi, wwi);
1940 /* tell the JACK server to call `JACK_bufsize_wwi()' whenever
1941 the maximum number of frames that will be passed
1942 to `JACK_Callback()' changes */
1943 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwi, wwi);
1945 /* tell the JACK server to call `srate()' whenever
1946 the sample rate of the system changes. */
1947 fp_jack_set_sample_rate_callback (client, JACK_srate, wwi);
1949 /* tell the JACK server to call `jack_shutdown()' if
1950 it ever shuts down, either entirely, or if it
1951 just decides to stop calling us. */
1952 fp_jack_on_shutdown (client, JACK_shutdown_wwi, wwi);
1954 /* display the current sample rate. once the client is activated
1955 (see below), you should rely on your own sample rate
1956 callback (see above) for this value. */
1957 wwi->sample_rate = fp_jack_get_sample_rate(client);
1958 TRACE("engine sample rate: %lu\n", wwi->sample_rate);
1960 /* create the left and right channel output ports */
1961 /* jack's ports are all mono so for stereo you need two */
1962 in_port_l = fp_jack_port_register (client, "in_l",
1963 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
1964 wwi->in_port_l = in_port_l;
1965 TRACE("Created port. (%p)\n", in_port_l);
1967 if (nChannels == 2)
1969 in_port_r = fp_jack_port_register (client, "in_r",
1970 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
1971 TRACE("Created port. (%p)\n", in_port_r);
1973 wwi->in_port_r = in_port_r;
1975 #if JACK_CLOSE_HACK
1976 wwi->in_use = TRUE; /* mark this device as in use since it now is ;-) */
1977 #endif
1979 TRACE("activating client.\n");
1980 /* tell the JACK server that we are ready to roll */
1981 if (fp_jack_activate (client))
1983 ERR( "cannot activate client\n");
1984 return 0;
1986 TRACE("activated client.\n");
1987 /* figure out what the ports that we want to output on are */
1988 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
1989 /* this way works if names are changed */
1990 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
1992 /* display a trace of the output ports we found */
1993 for(i = 0; ports[i]; i++)
1995 TRACE("ports[%d] = '%s'\n", i, ports[i]);
1998 if(!ports)
2000 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsOutput'\n");
2003 /* connect the ports. Note: you can't do this before
2004 the client is activated (this may change in the future).
2006 /* we want to connect to two ports so we have stereo input ;-) */
2008 if(fp_jack_connect(client, ports[0], fp_jack_port_name(in_port_l)))
2010 ERR ("cannot connect to input port %d('%s')\n", 0, ports[0]);
2011 failed = 1;
2013 TRACE("Connected (%s)<->(%s)\n",ports[0],fp_jack_port_name(in_port_l));
2015 if ((nChannels == 2) && in_port_r) {
2016 if(fp_jack_connect(client, ports[1], fp_jack_port_name(in_port_r)))
2018 ERR ("cannot connect to input port %d('%s')\n", 1, ports[1]);
2019 failed = 1;
2021 TRACE("Connected (%s)<->(%s)\n",ports[1],fp_jack_port_name(in_port_r));
2023 free(ports); /* free the returned array of ports */
2025 /* if something failed we need to shut the client down and return 0 */
2026 if(failed)
2028 #if JACK_CLOSE_HACK
2029 JACK_CloseWaveInDevice(wwi, TRUE);
2030 #else
2031 JACK_CloseWaveInDevice(wwi);
2032 #endif
2033 return 0;
2036 TRACE("return success.\n");
2037 return 1; /* return success */
2040 /**************************************************************************
2041 * widGetDevCaps [internal]
2043 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSW lpCaps, DWORD dwSize)
2045 TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
2047 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
2049 if (wDevID >= MAX_WAVEINDRV) {
2050 TRACE("MAX_WAVEINDRV reached !\n");
2051 return MMSYSERR_BADDEVICEID;
2054 memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
2055 return MMSYSERR_NOERROR;
2058 /**************************************************************************
2059 * widOpen [internal]
2061 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
2063 WINE_WAVEIN* wwi;
2064 DWORD retval;
2066 TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
2067 if (lpDesc == NULL)
2069 WARN("Invalid Parameter !\n");
2070 return MMSYSERR_INVALPARAM;
2072 if (wDevID >= MAX_WAVEINDRV) {
2073 TRACE ("MAX_WAVEINDRV reached !\n");
2074 return MMSYSERR_BADDEVICEID;
2077 #if JACK_CLOSE_HACK
2078 if(WInDev[wDevID].client && WOutDev[wDevID].in_use)
2079 #else
2080 if(WInDev[wDevID].client)
2081 #endif
2083 TRACE("device %d already allocated\n", wDevID);
2084 return MMSYSERR_ALLOCATED;
2087 /* Only the PCM format is supported so far...
2088 * Also we only support 16 bit mode.
2090 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
2091 lpDesc->lpFormat->nChannels == 0 ||
2092 lpDesc->lpFormat->nSamplesPerSec == 0 ||
2093 lpDesc->lpFormat->wBitsPerSample!=16)
2095 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
2096 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2097 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
2098 return WAVERR_BADFORMAT;
2101 if (dwFlags & WAVE_FORMAT_QUERY)
2103 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
2104 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2105 lpDesc->lpFormat->nSamplesPerSec);
2106 return MMSYSERR_NOERROR;
2109 wwi = &WInDev[wDevID];
2110 wwi->wDevID = wDevID;
2112 /* Set things up before we call JACK_OpenWaveOutDevice because */
2113 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
2114 /* even returns and we want to be initialized before then */
2115 wwi->state = WINE_WS_STOPPED; /* start in a stopped state */
2117 InitializeCriticalSection(&wwi->access_crst); /* initialize the critical section */
2118 wwi->access_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_WAVEIN.access_crst");
2119 EnterCriticalSection(&wwi->access_crst);
2121 /* open up jack ports for this device */
2122 if (!JACK_OpenWaveInDevice(&WInDev[wDevID], lpDesc->lpFormat->nChannels))
2124 ERR("JACK_OpenWaveInDevice(%d) failed\n", wDevID);
2125 LeaveCriticalSection(&wwi->access_crst);
2126 wwi->access_crst.DebugInfo->Spare[0] = 0;
2127 DeleteCriticalSection(&wwi->access_crst);
2128 return MMSYSERR_ERROR; /* return unspecified error */
2131 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
2133 wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
2135 wwi->waveDesc = *lpDesc;
2136 memcpy(&wwi->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
2138 LeaveCriticalSection(&wwi->access_crst);
2140 /* display the current wave format */
2141 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%u, nSamplesPerSec=%u, nChannels=%u nBlockAlign=%u!\n",
2142 wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
2143 wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
2144 wwi->format.wf.nBlockAlign);
2146 /* make sure that we have the same sample rate in our audio stream */
2147 /* as we do in the jack server */
2148 if(wwi->format.wf.nSamplesPerSec != wwi->sample_rate)
2150 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%d'\n",
2151 wwi->sample_rate, wwi->format.wf.nSamplesPerSec);
2153 #if JACK_CLOSE_HACK
2154 JACK_CloseWaveInDevice(wwi, FALSE); /* close this device, don't force the client to close */
2155 #else
2156 JACK_CloseWaveInDevice(wwi); /* close this device */
2157 #endif
2158 wwi->access_crst.DebugInfo->Spare[0] = 0;
2159 DeleteCriticalSection(&wwi->access_crst);
2160 return WAVERR_BADFORMAT;
2163 /* check for an invalid number of bits per sample */
2164 if (wwi->format.wBitsPerSample == 0)
2166 WARN("Resetting zeroed wBitsPerSample\n");
2167 wwi->format.wBitsPerSample = 8 *
2168 (wwi->format.wf.nAvgBytesPerSec /
2169 wwi->format.wf.nSamplesPerSec) /
2170 wwi->format.wf.nChannels;
2173 TRACE("notify client.\n");
2174 EnterCriticalSection(&wwi->access_crst);
2175 retval = widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
2176 LeaveCriticalSection(&wwi->access_crst);
2178 return retval;
2180 /**************************************************************************
2181 * widClose [internal]
2183 static DWORD widClose(WORD wDevID)
2185 DWORD ret = MMSYSERR_NOERROR;
2186 WINE_WAVEIN* wwi;
2188 TRACE("(%u);\n", wDevID);
2190 if (wDevID >= MAX_WAVEINDRV || !WInDev[wDevID].client)
2192 WARN("bad device ID !\n");
2193 return MMSYSERR_BADDEVICEID;
2196 wwi = &WInDev[wDevID];
2197 if (wwi->lpQueuePtr)
2199 WARN("buffers still playing !\n");
2200 ret = WAVERR_STILLPLAYING;
2201 } else
2203 /* sanity check: this should not happen since the device must have been reset before */
2204 if (wwi->lpQueuePtr) ERR("out of sync\n");
2206 wwi->state = WINE_WS_CLOSED; /* mark the device as closed */
2208 #if JACK_CLOSE_HACK
2209 JACK_CloseWaveInDevice(wwi, FALSE); /* close the jack device, DO NOT force the client to close */
2210 #else
2211 JACK_CloseWaveInDevice(wwi); /* close the jack device */
2212 #endif
2213 wwi->access_crst.DebugInfo->Spare[0] = 0;
2214 DeleteCriticalSection(&wwi->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
2216 ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
2219 return ret;
2222 /**************************************************************************
2223 * widAddBuffer [internal]
2225 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2227 WINE_WAVEIN* wwi = &WInDev[wDevID];
2229 TRACE("(%u, %p, %08X);\n", wDevID, lpWaveHdr, dwSize);
2231 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2232 WARN("can't do it !\n");
2233 return MMSYSERR_INVALHANDLE;
2235 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
2236 TRACE("never been prepared !\n");
2237 return WAVERR_UNPREPARED;
2239 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2240 TRACE("header already in use !\n");
2241 return WAVERR_STILLPLAYING;
2244 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
2245 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2246 lpWaveHdr->dwBytesRecorded = 0;
2247 lpWaveHdr->lpNext = NULL;
2249 EnterCriticalSection(&wwi->access_crst);
2250 /* insert buffer at end of queue */
2252 LPWAVEHDR* wh;
2253 for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
2254 *wh=lpWaveHdr;
2256 LeaveCriticalSection(&wwi->access_crst);
2258 return MMSYSERR_NOERROR;
2261 /**************************************************************************
2262 * widStart [internal]
2264 static DWORD widStart(WORD wDevID)
2266 TRACE("(%u);\n", wDevID);
2267 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2268 WARN("can't start recording !\n");
2269 return MMSYSERR_INVALHANDLE;
2272 WInDev[wDevID].state = WINE_WS_PLAYING;
2273 return MMSYSERR_NOERROR;
2276 /**************************************************************************
2277 * widStop [internal]
2279 static DWORD widStop(WORD wDevID)
2281 WINE_WAVEIN* wwi = &WInDev[wDevID];
2283 TRACE("(%u);\n", wDevID);
2284 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2285 WARN("can't stop !\n");
2286 return MMSYSERR_INVALHANDLE;
2289 if (wwi->state != WINE_WS_STOPPED)
2291 WAVEHDR* lpWaveHdr;
2292 /* do something here to stop recording ??? */
2294 /* return current buffer to app */
2295 lpWaveHdr = wwi->lpQueuePtr;
2296 if (lpWaveHdr)
2298 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
2299 TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2300 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2301 lpWaveHdr->dwFlags |= WHDR_DONE;
2302 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2303 wwi->lpQueuePtr = lpNext;
2306 wwi->state = WINE_WS_STOPPED;
2308 return MMSYSERR_NOERROR;
2311 /**************************************************************************
2312 * widReset [internal]
2314 static DWORD widReset(WORD wDevID)
2316 WINE_WAVEIN* wwi = &WInDev[wDevID];
2317 WAVEHDR* lpWaveHdr;
2319 TRACE("(%u);\n", wDevID);
2320 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2321 WARN("can't reset !\n");
2322 return MMSYSERR_INVALHANDLE;
2325 wwi->state = WINE_WS_STOPPED;
2327 /* return all buffers to the app */
2328 for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
2329 TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2330 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2331 lpWaveHdr->dwFlags |= WHDR_DONE;
2333 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2335 wwi->lpQueuePtr = NULL;
2337 return MMSYSERR_NOERROR;
2340 /**************************************************************************
2341 * widGetNumDevs [internal]
2343 static DWORD widGetNumDevs(void)
2345 return MAX_WAVEINDRV;
2348 /**************************************************************************
2349 * widDevInterfaceSize [internal]
2351 static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
2353 TRACE("(%u, %p)\n", wDevID, dwParam1);
2356 *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2357 NULL, 0 ) * sizeof(WCHAR);
2358 return MMSYSERR_NOERROR;
2361 /**************************************************************************
2362 * widDevInterface [internal]
2364 static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
2366 if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2367 NULL, 0 ) * sizeof(WCHAR))
2369 MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2370 dwParam1, dwParam2 / sizeof(WCHAR));
2371 return MMSYSERR_NOERROR;
2373 return MMSYSERR_INVALPARAM;
2376 /**************************************************************************
2377 * widMessage (WINEJACK.6)
2379 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2380 DWORD dwParam1, DWORD dwParam2)
2382 TRACE("(%u, %04X, %08X, %08X, %08X);\n",
2383 wDevID, wMsg, dwUser, dwParam1, dwParam2);
2385 switch (wMsg) {
2386 case DRVM_INIT:
2387 case DRVM_EXIT:
2388 case DRVM_ENABLE:
2389 case DRVM_DISABLE:
2390 /* FIXME: Pretend this is supported */
2391 return 0;
2392 case WIDM_OPEN: return widOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
2393 case WIDM_CLOSE: return widClose (wDevID);
2394 case WIDM_ADDBUFFER: return widAddBuffer (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2395 case WIDM_PREPARE: return MMSYSERR_NOTSUPPORTED;
2396 case WIDM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
2397 case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (LPWAVEINCAPSW)dwParam1, dwParam2);
2398 case WIDM_GETNUMDEVS: return widGetNumDevs();
2399 case WIDM_RESET: return widReset (wDevID);
2400 case WIDM_START: return widStart (wDevID);
2401 case WIDM_STOP: return widStop (wDevID);
2402 case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
2403 case DRV_QUERYDEVICEINTERFACE: return widDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
2404 default:
2405 FIXME("unknown message %d!\n", wMsg);
2408 return MMSYSERR_NOTSUPPORTED;
2411 #else /* !SONAME_LIBJACK */
2413 /**************************************************************************
2414 * widMessage (WINEJACK.6)
2416 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2417 DWORD dwParam1, DWORD dwParam2)
2419 FIXME("(%u, %04X, %08X, %08X, %08X):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2420 return MMSYSERR_NOTENABLED;
2423 /**************************************************************************
2424 * wodMessage (WINEJACK.7)
2426 DWORD WINAPI JACK_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2427 DWORD dwParam1, DWORD dwParam2)
2429 FIXME("(%u, %04X, %08X, %08X, %08X):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2430 return MMSYSERR_NOTENABLED;
2433 #endif /* SONAME_LIBJACK */