1 /* -*- tab-width: 8; c-basic-offset: 2 -*- */
3 * Wine Driver for jack Sound Server
4 * http://jackit.sourceforge.net
6 * Copyright 1994 Martin Ayotte
7 * Copyright 1999 Eric Pouech (async playing in waveOut/waveIn)
8 * Copyright 2000 Eric Pouech (loops in waveOut)
9 * Copyright 2002 Chris Morgan (jack version of this file)
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * implement audio stream resampling for any arbitrary frequenty
29 * right now we use the winmm layer to do resampling although it would
30 * be nice to have a full set of algorithms to choose from based on cpu
34 * pause in waveOut during loop is not handled correctly
51 #include "wine/winuser16.h"
56 #include "wine/debug.h"
58 #ifdef HAVE_JACK_JACK_H
59 #include <jack/jack.h>
63 WINE_DEFAULT_DEBUG_CHANNEL(wave);
65 #ifdef HAVE_JACK_JACK_H
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_new" */
71 MAKE_FUNCPTR(jack_activate);
72 MAKE_FUNCPTR(jack_connect);
73 MAKE_FUNCPTR(jack_client_new);
74 MAKE_FUNCPTR(jack_client_close);
75 MAKE_FUNCPTR(jack_deactivate);
76 MAKE_FUNCPTR(jack_set_process_callback);
77 MAKE_FUNCPTR(jack_set_buffer_size_callback);
78 MAKE_FUNCPTR(jack_set_sample_rate_callback);
79 MAKE_FUNCPTR(jack_on_shutdown);
80 MAKE_FUNCPTR(jack_get_sample_rate);
81 MAKE_FUNCPTR(jack_port_register);
82 MAKE_FUNCPTR(jack_port_get_buffer);
83 MAKE_FUNCPTR(jack_get_ports);
84 MAKE_FUNCPTR(jack_port_name);
85 MAKE_FUNCPTR(jack_get_buffer_size);
88 /* define the below to work around a bug in jack where closing a port */
89 /* takes a very long time, so to get around this we actually don't */
90 /* close the port when the device is closed but instead mark the */
91 /* corresponding device as unused */
92 #define JACK_CLOSE_HACK 1
94 typedef jack_default_audio_sample_t sample_t;
95 typedef jack_nframes_t nframes_t;
97 /* only allow 10 output devices through this driver, this ought to be adequate */
98 #define MAX_WAVEOUTDRV (10)
99 #define MAX_WAVEINDRV (10)
101 /* state diagram for waveOut writing:
103 * +---------+-------------+---------------+---------------------------------+
104 * | state | function | event | new state |
105 * +---------+-------------+---------------+---------------------------------+
106 * | | open() | | STOPPED |
107 * | PAUSED | write() | | PAUSED |
108 * | STOPPED | write() | <thrd create> | PLAYING |
109 * | PLAYING | write() | HEADER | PLAYING |
110 * | (other) | write() | <error> | |
111 * | (any) | pause() | PAUSING | PAUSED |
112 * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
113 * | (any) | reset() | RESETTING | STOPPED |
114 * | (any) | close() | CLOSING | CLOSED |
115 * +---------+-------------+---------------+---------------------------------+
118 /* states of the playing device */
119 #define WINE_WS_PLAYING 0
120 #define WINE_WS_PAUSED 1
121 #define WINE_WS_STOPPED 2
122 #define WINE_WS_CLOSED 3
125 volatile int state; /* one of the WINE_WS_ manifest constants */
126 WAVEOPENDESC waveDesc;
128 PCMWAVEFORMAT format;
131 char interface_name[32];
133 jack_port_t* out_port_l; /* ports for left and right channels */
134 jack_port_t* out_port_r;
135 jack_client_t* client;
136 long sample_rate; /* jack server sample rate */
139 BOOL in_use; /* TRUE if this device is in use */
143 unsigned long buffer_size;
148 LPWAVEHDR lpQueuePtr; /* start of queued WAVEHDRs (waiting to be notified) */
149 LPWAVEHDR lpPlayPtr; /* start of not yet fully played buffers */
150 DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
152 LPWAVEHDR lpLoopPtr; /* pointer of first buffer in loop, if any */
153 DWORD dwLoops; /* private copy of loop counter */
155 DWORD dwPlayedTotal; /* number of bytes actually played since opening */
156 DWORD dwWrittenTotal; /* number of bytes written to jack since opening */
158 DWORD bytesInJack; /* bytes that we wrote during the previous JACK_Callback() */
159 DWORD tickCountMS; /* time in MS of last JACK_Callback() */
161 /* synchronization stuff */
162 CRITICAL_SECTION access_crst;
167 WAVEOPENDESC waveDesc;
169 PCMWAVEFORMAT format;
170 LPWAVEHDR lpQueuePtr;
171 DWORD dwTotalRecorded;
173 BOOL bTriggerSupport;
175 char interface_name[32];
177 jack_port_t* in_port_l; /* ports for left and right channels */
178 jack_port_t* in_port_r;
179 jack_client_t* client;
180 long sample_rate; /* jack server sample rate */
183 BOOL in_use; /* TRUE if this device is in use */
187 unsigned long buffer_size;
189 /* synchronization stuff */
190 CRITICAL_SECTION access_crst;
193 static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV];
194 static WINE_WAVEIN WInDev [MAX_WAVEINDRV ];
196 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
197 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
199 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo);
200 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force);
202 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo);
203 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels);
206 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client);
208 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo);
212 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client);
214 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi);
217 static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
218 PCMWAVEFORMAT* format)
220 TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
221 lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
222 format->wf.nChannels, format->wf.nAvgBytesPerSec);
223 TRACE("Position in bytes=%lu\n", position);
225 switch (lpTime->wType) {
227 lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
228 TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
231 lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
232 TRACE("TIME_MS=%lu\n", lpTime->u.ms);
235 position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
236 lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
237 position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
238 lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
239 lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
240 lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
241 lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
242 lpTime->u.smpte.fps = 30;
243 lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
244 position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
248 lpTime->u.smpte.frame++;
250 TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
251 lpTime->u.smpte.hour, lpTime->u.smpte.min,
252 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
255 FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
256 lpTime->wType = TIME_BYTES;
259 lpTime->u.cb = position;
260 TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
263 return MMSYSERR_NOERROR;
267 /*======================================================================*
268 * Low level WAVE implementation *
269 *======================================================================*/
271 #define SAMPLE_MAX_16BIT 32767.0f
273 /* Alsaplayer function that applies volume changes to a buffer */
274 /* (C) Andy Lo A Foe */
275 /* Length is in terms of 32 bit samples */
276 void volume_effect32(void *buffer, int length, int left, int right)
278 short *data = (short *)buffer;
281 if (right == -1) right = left;
283 for(i = 0; i < length; i++) {
284 v = (int) ((*(data) * left) / 100);
285 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
286 v = (int) ((*(data) * right) / 100);
287 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
291 /* move 16 bit mono/stereo to 16 bit stereo */
292 void sample_move_d16_d16(short *dst, short *src,
293 unsigned long nsamples, int nChannels)
300 if(nChannels == 2) src++;
309 /* convert from 16 bit to floating point */
310 /* allow for copying of stereo data with alternating left/right */
311 /* channels to a buffer that will hold a single channel stream */
312 /* nsamples is in terms of 16bit samples */
313 /* src_skip is in terms of 16bit samples */
314 void sample_move_d16_s16 (sample_t *dst, short *src,
315 unsigned long nsamples, unsigned long src_skip)
317 /* ALERT: signed sign-extension portability !!! */
320 *dst = (*src) / SAMPLE_MAX_16BIT;
326 /* convert from floating point to 16 bit */
327 /* allow for copying of a buffer that will hold a single channel stream */
328 /* to stereo data with alternating left/right channels */
329 /* nsamples is in terms of float samples */
330 /* dst_skip is in terms of 16bit samples */
331 void sample_move_s16_d16 (short *dst, sample_t *src,
332 unsigned long nsamples, unsigned long dst_skip)
334 /* ALERT: signed sign-extension portability !!! */
337 *dst = (*src) * SAMPLE_MAX_16BIT;
338 /* TRACE("src=(%.8f,%p) dst=(%d,%p)\n",*src,src,*dst,dst); */
345 /* fill dst buffer with nsamples worth of silence */
346 void sample_silence_dS (sample_t *dst, unsigned long nsamples)
348 /* ALERT: signed sign-extension portability !!! */
356 /******************************************************************
359 /* everytime the jack server wants something from us it calls this
360 function, so we either deliver it some sound to play or deliver it nothing
362 int JACK_callback_wwo (nframes_t nframes, void *arg)
366 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
368 TRACE("wDevID: %u, nframes %u state=%u\n", wwo->wDevID, nframes,wwo->state);
371 ERR("client is closed, this is weird...\n");
373 out_l = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_l, nframes);
374 out_r = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_r, nframes);
376 if(wwo->state == WINE_WS_PLAYING)
378 DWORD jackFramesAvailable = nframes;
379 DWORD outputFramesAvailable;
380 DWORD numFramesToWrite;
386 if(wwo->in_use == FALSE)
388 /* output silence if nothing is being outputted */
389 sample_silence_dS(out_l, nframes);
390 sample_silence_dS(out_r, nframes);
396 TRACE("wwo.state == WINE_WS_PLAYING\n");
398 /* see if our sound_buffer is large enough to hold the number of frames jack requested */
399 /* Note: sound_buffer is always filled with 16-bit stereo data, even for mono mode */
400 if(wwo->buffer_size < (nframes * sizeof(short) * 2))
402 ERR("for some reason JACK_BufSize() didn't allocate enough memory\n");
403 ERR("allocated %ld bytes, need %d bytes\n", wwo->buffer_size, (nframes * sizeof(short) * 2));
407 /* while we have jackFramesAvailable and a wave header to be played */
408 while(jackFramesAvailable && wwo->lpPlayPtr)
410 /* find the amount of audio to be played at this time */
411 outputFramesAvailable = (wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset) / wwo->format.wf.nBlockAlign;
413 numFramesToWrite = min(jackFramesAvailable, outputFramesAvailable);
414 TRACE("dwBufferLength=(%ld) dwPartialOffset=(%ld)\n",wwo->lpPlayPtr->dwBufferLength,wwo->dwPartialOffset);
415 TRACE("outputFramesAvailable == %ld, jackFramesAvailable == %ld\n", outputFramesAvailable, jackFramesAvailable);
417 buffer = wwo->lpPlayPtr->lpData + wwo->dwPartialOffset;
419 /* convert from mono to stereo if necessary */
420 /* otherwise just memcpy to the output buffer */
422 if(wwo->format.wf.nChannels == 1)
424 sample_move_d16_d16((short*)wwo->sound_buffer + ((nframes - jackFramesAvailable) * sizeof(short)),
425 (short*)buffer, numFramesToWrite, wwo->format.wf.nChannels);
426 } else /* just copy the memory over */
428 memcpy(wwo->sound_buffer + ((nframes - jackFramesAvailable) * wwo->format.wf.nBlockAlign),
429 buffer, numFramesToWrite * wwo->format.wf.nBlockAlign);
432 /* advance to the next wave header if possible, or advance pointer */
433 /* inside of the current header if we haven't completed it */
434 if(numFramesToWrite == outputFramesAvailable)
436 wodHelper_PlayPtrNext(wwo); /* we wrote the whole waveheader, skip to the next one*/
440 wwo->dwPartialOffset+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* else advance by the bytes we took in to write */
443 written+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* add on what we wrote */
444 jackFramesAvailable-=numFramesToWrite; /* take away what was written in terms of output bytes */
447 wwo->tickCountMS = GetTickCount(); /* record the current time */
448 wwo->dwWrittenTotal+=written; /* update states on wave device */
449 wwo->dwPlayedTotal+=wwo->bytesInJack; /* we must have finished with the last bytes or we wouldn't be back inside of this callback again... */
450 wwo->bytesInJack = written; /* record the bytes inside of jack */
452 /* Now that we have finished filling the buffer either until it is full or until */
453 /* we have run out of application sound data to process, apply volume and output */
454 /* the audio to the jack server */
456 /* apply volume to the buffer */
457 volume_effect32(wwo->sound_buffer, (nframes - jackFramesAvailable), wwo->volume_left, wwo->volume_right);
459 /* convert from stereo 16 bit to single channel 32 bit float */
460 /* for each jack server channel */
461 /* NOTE: we skip over two sample since we want to only get either the left or right channel */
462 sample_move_d16_s16(out_l, (short*)wwo->sound_buffer, (nframes - jackFramesAvailable), 2);
463 sample_move_d16_s16(out_r, (short*)wwo->sound_buffer + 1, (nframes - jackFramesAvailable), 2);
465 /* see if we still have jackBytesLeft here, if we do that means that we
466 ran out of wave data to play and had a buffer underrun, fill in
467 the rest of the space with zero bytes */
468 if(jackFramesAvailable)
470 ERR("buffer underrun of %ld frames\n", jackFramesAvailable);
471 sample_silence_dS(out_l + (nframes - jackFramesAvailable), jackFramesAvailable);
472 sample_silence_dS(out_r + (nframes - jackFramesAvailable), jackFramesAvailable);
475 else if(wwo->state == WINE_WS_PAUSED ||
476 wwo->state == WINE_WS_STOPPED ||
477 wwo->state == WINE_WS_CLOSED)
479 /* output silence if nothing is being outputted */
480 sample_silence_dS(out_l, nframes);
481 sample_silence_dS(out_r, nframes);
484 /* notify the client of completed wave headers */
485 EnterCriticalSection(&wwo->access_crst);
486 wodHelper_NotifyCompletions(wwo, FALSE);
487 LeaveCriticalSection(&wwo->access_crst);
492 /******************************************************************
495 * Called whenever the jack server changes the the max number
496 * of frames passed to JACK_callback
498 int JACK_bufsize_wwo (nframes_t nframes, void *arg)
500 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
501 DWORD buffer_required;
502 TRACE("wDevID=%d\n",wwo->wDevID);
503 TRACE("the maximum buffer size is now %u frames\n", nframes);
505 /* make sure the callback routine has adequate memory */
506 /* see if our buffer is large enough for the data we are writing */
507 /* ie. Buffer_size < (bytes we already wrote + bytes we are going to write in this loop) */
508 EnterCriticalSection(&wwo->access_crst);
510 /* wwo->sound_buffer is always filled with 16-bit stereo data, even for mono streams */
511 buffer_required = nframes * sizeof(short) * 2;
512 TRACE("wwo->buffer_size (%ld) buffer_required (%ld).\n", wwo->buffer_size,buffer_required);
513 if(wwo->buffer_size < buffer_required)
515 TRACE("expanding buffer from wwo->buffer_size == %ld, to %ld\n",
516 wwo->buffer_size, buffer_required);
517 TRACE("GetProcessHeap() == %p\n", GetProcessHeap());
518 wwo->buffer_size = buffer_required;
520 if (wwo->sound_buffer)
521 wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, wwo->buffer_size);
523 wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, wwo->buffer_size);
525 /* if we don't have a buffer then error out */
526 if(!wwo->sound_buffer)
528 ERR("error allocating sound_buffer memory\n");
529 LeaveCriticalSection(&wwo->access_crst);
534 LeaveCriticalSection(&wwo->access_crst);
540 /******************************************************************
543 * Called whenever the jack server changes the the max number
544 * of frames passed to JACK_callback
546 int JACK_bufsize_wwi (nframes_t nframes, void *arg)
548 TRACE("the maximum buffer size is now %u frames\n", nframes);
552 /******************************************************************
555 int JACK_srate (nframes_t nframes, void *arg)
557 TRACE("the sample rate is now %u/sec\n", nframes);
562 /******************************************************************
565 /* if this is called then jack shut down... handle this appropriately */
566 void JACK_shutdown_wwo(void* arg)
568 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
570 wwo->client = 0; /* reset client */
572 TRACE("trying to reconnect after sleeping for a short while...\n");
574 /* lets see if we can't reestablish the connection */
575 Sleep(750); /* pause for a short period of time */
576 if(!JACK_OpenWaveOutDevice(wwo))
578 ERR("unable to reconnect with jack...\n");
582 /******************************************************************
585 /* if this is called then jack shut down... handle this appropriately */
586 void JACK_shutdown_wwi(void* arg)
588 WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
590 wwi->client = 0; /* reset client */
592 TRACE("trying to reconnect after sleeping for a short while...\n");
594 /* lets see if we can't reestablish the connection */
595 Sleep(750); /* pause for a short period of time */
596 if(!JACK_OpenWaveInDevice(wwi,wwi->format.wf.nChannels))
598 ERR("unable to reconnect with jack...\n");
603 /******************************************************************
604 * JACK_OpenWaveOutDevice
606 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo)
610 char client_name[64];
611 jack_port_t* out_port_l;
612 jack_port_t* out_port_r;
613 jack_client_t* client;
616 TRACE("creating jack client and setting up callbacks\n");
619 /* see if this device is already open */
622 /* if this device is already in use then it is bad for us to be in here */
626 TRACE("using existing client\n");
632 /* zero out the buffer pointer and the size of the buffer */
633 wwo->sound_buffer = 0;
634 wwo->buffer_size = 0;
636 /* try to become a client of the JACK server */
637 snprintf(client_name, sizeof(client_name), "wine_jack_out_%d", wwo->wDevID);
638 TRACE("client name '%s'\n", client_name);
639 if ((client = fp_jack_client_new (client_name)) == 0)
641 /* jack has problems with shutting down clients, so lets */
642 /* wait a short while and try once more before we give up */
644 if ((client = fp_jack_client_new (client_name)) == 0)
646 ERR("jack server not running?\n");
651 /* tell the JACK server to call `JACK_callback_wwo()' whenever
652 there is work to be done. */
653 fp_jack_set_process_callback (client, JACK_callback_wwo, wwo);
655 /* tell the JACK server to call `JACK_bufsize_wwo()' whenever
656 the maximum number of frames that will be passed
657 to `JACK_Callback()' changes */
658 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwo, wwo);
660 /* tell the JACK server to call `srate()' whenever
661 the sample rate of the system changes. */
662 fp_jack_set_sample_rate_callback (client, JACK_srate, wwo);
664 /* tell the JACK server to call `jack_shutdown()' if
665 it ever shuts down, either entirely, or if it
666 just decides to stop calling us. */
667 fp_jack_on_shutdown (client, JACK_shutdown_wwo, wwo);
669 /* display the current sample rate. once the client is activated
670 (see below), you should rely on your own sample rate
671 callback (see above) for this value. */
672 wwo->sample_rate = fp_jack_get_sample_rate(client);
673 TRACE("engine sample rate: %lu\n", wwo->sample_rate);
675 /* create the left and right channel output ports */
676 /* jack's ports are all mono so for stereo you need two */
677 out_port_l = fp_jack_port_register (client, "out_l",
678 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
680 out_port_r = fp_jack_port_register (client, "out_r",
681 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
683 TRACE("Created ports. (%p) (%p)\n",out_port_l, out_port_r);
685 /* save away important values to the WINE_WAVEOUT struct */
686 wwo->client = client;
687 wwo->out_port_l = out_port_l;
688 wwo->out_port_r = out_port_r;
691 wwo->in_use = TRUE; /* mark this device as in use since it now is ;-) */
694 /* set initial buffer size */
695 JACK_bufsize_wwo (fp_jack_get_buffer_size(client),wwo);
697 /* tell the JACK server that we are ready to roll */
698 if (fp_jack_activate (client))
700 ERR( "cannot activate client\n");
704 TRACE("jack activate.\n");
705 /* figure out what the ports that we want to output on are */
706 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
707 /* this way works if names are changed */
708 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
710 /* display a trace of the output ports we found */
711 for(i = 0; ports[i]; i++)
713 TRACE("ports[%d] = '%s'\n", i, ports[i]);
718 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsInput'\n");
721 /* connect the ports. Note: you can't do this before
722 the client is activated (this may change in the future).
724 /* we want to connect to two ports so we have stereo output ;-) */
726 if(fp_jack_connect(client, fp_jack_port_name(out_port_l), ports[0]))
728 ERR ("cannot connect to output port %d('%s')\n", 0, ports[0]);
732 if(fp_jack_connect(client, fp_jack_port_name(out_port_r), ports[1]))
734 ERR ("cannot connect to output port %d('%s')\n", 1, ports[1]);
738 free(ports); /* free the returned array of ports */
740 /* if something failed we need to shut the client down and return 0 */
744 JACK_CloseWaveOutDevice(wwo, TRUE);
746 JACK_CloseWaveOutDevice(wwo);
751 return 1; /* return success */
754 /******************************************************************
755 * JACK_CloseWaveOutDevice
757 * Close the connection to the server cleanly.
758 * If close_client is TRUE we close the client for this device instead of
759 * just marking the device as in_use(JACK_CLOSE_HACK only)
762 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client)
764 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
768 TRACE("wDevID: %d, close_client (wwo): %d\n", wwo->wDevID, close_client);
770 TRACE("wDevID: %d\n", wwo->wDevID);
777 fp_jack_deactivate(wwo->client); /* supposed to help the jack_client_close() to succeed */
778 fp_jack_client_close (wwo->client);
780 EnterCriticalSection(&wwo->access_crst);
781 wwo->client = 0; /* reset client */
782 HeapFree(GetProcessHeap(), 0, wwo->sound_buffer); /* free buffer memory */
783 wwo->sound_buffer = 0;
784 wwo->buffer_size = 0; /* zero out size of the buffer */
785 LeaveCriticalSection(&wwo->access_crst);
789 EnterCriticalSection(&wwo->access_crst);
790 TRACE("setting in_use to FALSE\n");
792 LeaveCriticalSection(&wwo->access_crst);
797 /******************************************************************
798 * JACK_CloseWaveInDevice
800 * Close the connection to the server cleanly.
801 * If close_client is TRUE we close the client for this device instead of
802 * just marking the device as in_use(JACK_CLOSE_HACK only)
805 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client)
807 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi)
811 TRACE("wDevID: %d, close_client (wwi): %d\n", wwi->wDevID, close_client);
813 TRACE("wDevID: %d\n", wwi->wDevID);
820 fp_jack_deactivate(wwi->client); /* supposed to help the jack_client_close() to succeed */
821 fp_jack_client_close (wwi->client);
823 EnterCriticalSection(&wwi->access_crst);
824 wwi->client = 0; /* reset client */
825 HeapFree(GetProcessHeap(), 0, wwi->sound_buffer); /* free buffer memory */
826 wwi->sound_buffer = 0;
827 wwi->buffer_size = 0; /* zero out size of the buffer */
828 LeaveCriticalSection(&wwi->access_crst);
832 EnterCriticalSection(&wwi->access_crst);
833 TRACE("setting in_use to FALSE\n");
835 LeaveCriticalSection(&wwi->access_crst);
840 /******************************************************************
845 LONG JACK_WaveRelease(void)
849 TRACE("closing all open waveout devices\n");
851 /* close all open output devices */
852 for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
854 TRACE("iDevice == %d\n", iDevice);
855 if(WOutDev[iDevice].client)
858 JACK_CloseWaveOutDevice(&WOutDev[iDevice], TRUE); /* close the device, FORCE the client to close */
860 JACK_CloseWaveOutDevice(&WOutDev[iDevice]); /* close the device, FORCE the client to close */
862 DeleteCriticalSection(&(WOutDev[iDevice].access_crst)); /* delete the critical section */
866 TRACE("closing all open wavein devices\n");
868 /* close all open input devices */
869 for(iDevice = 0; iDevice < MAX_WAVEINDRV; iDevice++)
871 TRACE("iDevice == %d\n", iDevice);
872 if(WInDev[iDevice].client)
875 JACK_CloseWaveInDevice(&WInDev[iDevice], TRUE); /* close the device, FORCE the client to close */
877 JACK_CloseWaveInDevice(&WInDev[iDevice]); /* close the device, FORCE the client to close */
879 DeleteCriticalSection(&(WInDev[iDevice].access_crst)); /* delete the critical section */
883 TRACE("returning 1\n");
888 /******************************************************************
891 * Initialize internal structures from JACK server info
893 LONG JACK_WaveInit(void)
899 /* setup function pointers */
900 #define LOAD_FUNCPTR(f) if((fp_##f = wine_dlsym(jackhandle, #f, NULL, 0)) == NULL) goto sym_not_found;
901 LOAD_FUNCPTR(jack_activate);
902 LOAD_FUNCPTR(jack_connect);
903 LOAD_FUNCPTR(jack_client_new);
904 LOAD_FUNCPTR(jack_client_close);
905 LOAD_FUNCPTR(jack_deactivate);
906 LOAD_FUNCPTR(jack_set_process_callback);
907 LOAD_FUNCPTR(jack_set_buffer_size_callback);
908 LOAD_FUNCPTR(jack_set_sample_rate_callback);
909 LOAD_FUNCPTR(jack_on_shutdown);
910 LOAD_FUNCPTR(jack_get_sample_rate);
911 LOAD_FUNCPTR(jack_port_register);
912 LOAD_FUNCPTR(jack_port_get_buffer);
913 LOAD_FUNCPTR(jack_get_ports);
914 LOAD_FUNCPTR(jack_port_name);
915 LOAD_FUNCPTR(jack_get_buffer_size);
918 /* start with output device */
920 for (i = 0; i < MAX_WAVEOUTDRV; ++i)
922 WOutDev[i].client = 0; /* initialize the client to 0 */
925 WOutDev[i].in_use = FALSE;
926 WInDev[i].in_use = FALSE;
929 memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps));
931 /* FIXME: some programs compare this string against the content of the registry
932 * for MM drivers. The names have to match in order for the program to work
933 * (e.g. MS win9x mplayer.exe)
936 WOutDev[i].caps.wMid = 0x0002;
937 WOutDev[i].caps.wPid = 0x0104;
938 strcpy(WOutDev[i].caps.szPname, "SB16 Wave Out");
940 WOutDev[i].caps.wMid = 0x00FF; /* Manufac ID */
941 WOutDev[i].caps.wPid = 0x0001; /* Product ID */
942 /* strcpy(WOutDev[i].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/
943 strcpy(WOutDev[i].caps.szPname, "CS4236/37/38");
946 snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "winejack: %d", i);
948 WOutDev[i].caps.vDriverVersion = 0x0100;
949 WOutDev[i].caps.dwFormats = 0x00000000;
950 WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
952 WOutDev[i].caps.wChannels = 2;
953 WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;
955 /* NOTE: we don't support any 8 bit modes so note that */
956 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
957 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
958 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
959 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
960 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
961 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
962 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
963 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
964 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
965 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
966 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
967 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
970 /* then do input device */
971 for (i = 0; i < MAX_WAVEINDRV; ++i)
973 /* TODO: we should initialize read stuff here */
974 memset(&WInDev[0].caps, 0, sizeof(WInDev[0].caps));
976 /* FIXME: some programs compare this string against the content of the registry
977 * for MM drivers. The names have to match in order for the program to work
978 * (e.g. MS win9x mplayer.exe)
981 WInDev[i].caps.wMid = 0x0002;
982 WInDev[i].caps.wPid = 0x0104;
983 strcpy(WInDev[i].caps.szPname, "SB16 Wave In");
985 WInDev[i].caps.wMid = 0x00FF;
986 WInDev[i].caps.wPid = 0x0001;
987 strcpy(WInDev[i].caps.szPname,"CS4236/37/38");
989 snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "winejack: %d", i);
991 WInDev[i].caps.vDriverVersion = 0x0100;
993 WInDev[i].caps.wChannels = 0x2;
994 /* NOTE: we don't support any 8 bit modes so note that */
995 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
996 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
997 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
998 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
999 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
1000 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
1001 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
1002 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
1003 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
1004 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
1005 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
1006 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
1007 WInDev[i].caps.wReserved1 = 0;
1010 return 1; /* return success */
1012 /* error path for function pointer loading errors */
1015 "Wine cannot find certain functions that it needs inside the jack"
1016 "library. To enable Wine to use the jack audio server please "
1017 "install libjack\n");
1018 wine_dlclose(jackhandle, NULL, 0);
1023 /*======================================================================*
1024 * Low level WAVE OUT implementation *
1025 *======================================================================*/
1027 /**************************************************************************
1028 * wodNotifyClient [internal]
1030 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1032 TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
1038 if (wwo->wFlags != DCB_NULL &&
1039 !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags,
1040 (HDRVR)wwo->waveDesc.hWave, wMsg, wwo->waveDesc.dwInstance,
1041 dwParam1, dwParam2))
1043 WARN("can't notify client !\n");
1044 return MMSYSERR_ERROR;
1048 FIXME("Unknown callback message %u\n", wMsg);
1049 return MMSYSERR_INVALPARAM;
1051 return MMSYSERR_NOERROR;
1054 /**************************************************************************
1055 * wodHelper_BeginWaveHdr [internal]
1057 * Makes the specified lpWaveHdr the currently playing wave header.
1058 * If the specified wave header is a begin loop and we're not already in
1059 * a loop, setup the loop.
1061 static void wodHelper_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
1063 EnterCriticalSection(&wwo->access_crst);
1065 wwo->lpPlayPtr = lpWaveHdr;
1069 LeaveCriticalSection(&wwo->access_crst);
1073 if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)
1077 WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1078 TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1081 TRACE("Starting loop (%ldx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
1082 wwo->lpLoopPtr = lpWaveHdr;
1083 /* Windows does not touch WAVEHDR.dwLoops,
1084 * so we need to make an internal copy */
1085 wwo->dwLoops = lpWaveHdr->dwLoops;
1088 wwo->dwPartialOffset = 0;
1090 LeaveCriticalSection(&wwo->access_crst);
1094 /**************************************************************************
1095 * wodHelper_PlayPtrNext [internal]
1097 * Advance the play pointer to the next waveheader, looping if required.
1099 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
1101 LPWAVEHDR lpWaveHdr;
1103 EnterCriticalSection(&wwo->access_crst);
1105 lpWaveHdr = wwo->lpPlayPtr;
1107 wwo->dwPartialOffset = 0;
1108 if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr)
1110 /* We're at the end of a loop, loop if required */
1111 if (--wwo->dwLoops > 0)
1113 wwo->lpPlayPtr = wwo->lpLoopPtr;
1116 /* Handle overlapping loops correctly */
1117 if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
1118 FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
1119 /* shall we consider the END flag for the closing loop or for
1120 * the opening one or for both ???
1121 * code assumes for closing loop only
1125 lpWaveHdr = lpWaveHdr->lpNext;
1127 wwo->lpLoopPtr = NULL;
1128 wodHelper_BeginWaveHdr(wwo, lpWaveHdr);
1132 /* We're not in a loop. Advance to the next wave header */
1133 TRACE("not inside of a loop, advancing to next wave header\n");
1134 wodHelper_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
1137 LeaveCriticalSection(&wwo->access_crst);
1142 /* if force is TRUE then notify the client that all the headers were completed */
1143 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
1145 LPWAVEHDR lpWaveHdr;
1150 EnterCriticalSection(&wwo->access_crst);
1152 /* Start from lpQueuePtr and keep notifying until:
1153 * - we hit an unwritten wavehdr
1154 * - we hit the beginning of a running loop
1155 * - we hit a wavehdr which hasn't finished playing
1157 while ((lpWaveHdr = wwo->lpQueuePtr) &&
1159 (lpWaveHdr != wwo->lpPlayPtr &&
1160 lpWaveHdr != wwo->lpLoopPtr)))
1162 wwo->lpQueuePtr = lpWaveHdr->lpNext;
1164 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1165 lpWaveHdr->dwFlags |= WHDR_DONE;
1166 TRACE("notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) dwFlags=(%ld)\n",
1167 lpWaveHdr, wwo->lpPlayPtr, lpWaveHdr->dwFlags);
1169 wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
1171 TRACE("Not notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) lpLoopPtr=(%p)\n",
1172 lpWaveHdr, wwo->lpPlayPtr, wwo->lpLoopPtr);
1173 retval = (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr !=
1174 wwo->lpLoopPtr) ? 0 : INFINITE;
1176 LeaveCriticalSection(&wwo->access_crst);
1181 /**************************************************************************
1182 * wodHelper_Reset [internal]
1184 * Resets current output stream.
1186 static void wodHelper_Reset(WINE_WAVEOUT* wwo, BOOL reset)
1188 EnterCriticalSection(&wwo->access_crst);
1190 /* updates current notify list */
1191 wodHelper_NotifyCompletions(wwo, FALSE);
1195 /* remove all wave headers and notify client that all headers were completed */
1196 wodHelper_NotifyCompletions(wwo, TRUE);
1198 wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
1199 wwo->state = WINE_WS_STOPPED;
1200 wwo->dwPlayedTotal = wwo->dwWrittenTotal = wwo->bytesInJack = 0;
1202 wwo->dwPartialOffset = 0; /* Clear partial wavehdr */
1207 /* complicated case, not handled yet (could imply modifying the loop counter) */
1208 FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
1209 wwo->lpPlayPtr = wwo->lpLoopPtr;
1210 wwo->dwPartialOffset = 0;
1211 wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
1215 DWORD sz = wwo->dwPartialOffset;
1217 /* reset all the data as if we had written only up to lpPlayedTotal bytes */
1218 /* compute the max size playable from lpQueuePtr */
1219 for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext)
1221 sz += ptr->dwBufferLength;
1224 /* because the reset lpPlayPtr will be lpQueuePtr */
1225 if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("doh\n");
1226 wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal);
1227 wwo->dwWrittenTotal = wwo->dwPlayedTotal;
1228 wwo->lpPlayPtr = wwo->lpQueuePtr;
1231 wwo->state = WINE_WS_PAUSED;
1234 LeaveCriticalSection(&wwo->access_crst);
1237 /**************************************************************************
1238 * wodGetDevCaps [internal]
1240 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSA lpCaps, DWORD dwSize)
1242 TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1244 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1246 if (wDevID >= MAX_WAVEOUTDRV)
1248 TRACE("MAX_WAVOUTDRV reached !\n");
1249 return MMSYSERR_BADDEVICEID;
1252 TRACE("dwSupport=(0x%lx), dwFormats=(0x%lx)\n", WOutDev[wDevID].caps.dwSupport, WOutDev[wDevID].caps.dwFormats);
1253 memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1254 return MMSYSERR_NOERROR;
1257 /**************************************************************************
1258 * wodOpen [internal]
1260 * NOTE: doesn't it seem like there is a race condition if you try to open
1261 * the same device twice?
1263 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1268 TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1271 WARN("Invalid Parameter !\n");
1272 return MMSYSERR_INVALPARAM;
1274 if (wDevID >= MAX_WAVEOUTDRV) {
1275 TRACE("MAX_WAVOUTDRV reached !\n");
1276 return MMSYSERR_BADDEVICEID;
1280 if(WOutDev[wDevID].client && WOutDev[wDevID].in_use)
1282 if(WOutDev[wDevID].client)
1285 TRACE("device %d already allocated\n", wDevID);
1286 return MMSYSERR_ALLOCATED;
1289 /* Only the PCM format is supported so far...
1290 * Also we only support 16 bit mode.
1292 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1293 lpDesc->lpFormat->nChannels == 0 ||
1294 lpDesc->lpFormat->nSamplesPerSec == 0 ||
1295 lpDesc->lpFormat->wBitsPerSample != 16)
1297 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
1298 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1299 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
1300 return WAVERR_BADFORMAT;
1303 if (dwFlags & WAVE_FORMAT_QUERY)
1305 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1306 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1307 lpDesc->lpFormat->nSamplesPerSec);
1308 return MMSYSERR_NOERROR;
1311 wwo = &WOutDev[wDevID];
1312 wwo->wDevID = wDevID;
1314 /* Set things up before we call JACK_OpenWaveOutDevice because */
1315 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
1316 /* even returns and we want to be initialized before then */
1317 wwo->state = WINE_WS_STOPPED; /* start in a stopped state */
1318 wwo->dwPlayedTotal = 0; /* zero out these totals */
1319 wwo->dwWrittenTotal = 0;
1320 wwo->bytesInJack = 0;
1321 wwo->tickCountMS = 0;
1323 /* Initialize volume to full level */
1324 wwo->volume_left = 100;
1325 wwo->volume_right = 100;
1327 InitializeCriticalSection(&wwo->access_crst); /* initialize the critical section */
1328 EnterCriticalSection(&wwo->access_crst);
1330 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
1332 wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1334 memcpy(&wwo->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1335 memcpy(&wwo->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1337 /* open up jack ports for this device */
1338 if (!JACK_OpenWaveOutDevice(&WOutDev[wDevID]))
1340 ERR("JACK_OpenWaveOutDevice(%d) failed\n", wDevID);
1341 LeaveCriticalSection(&wwo->access_crst);
1342 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1343 return MMSYSERR_ERROR; /* return unspecified error */
1346 LeaveCriticalSection(&wwo->access_crst);
1348 /* display the current wave format */
1349 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
1350 wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
1351 wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1352 wwo->format.wf.nBlockAlign);
1354 /* make sure that we have the same sample rate in our audio stream */
1355 /* as we do in the jack server */
1356 if(wwo->format.wf.nSamplesPerSec != wwo->sample_rate)
1358 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
1359 wwo->sample_rate, wwo->format.wf.nSamplesPerSec);
1362 JACK_CloseWaveOutDevice(wwo, FALSE); /* close this device, don't force the client to close */
1364 JACK_CloseWaveOutDevice(wwo); /* close this device */
1366 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1367 return WAVERR_BADFORMAT;
1370 /* check for an invalid number of bits per sample */
1371 if (wwo->format.wBitsPerSample == 0)
1373 WARN("Resetting zeroed wBitsPerSample\n");
1374 wwo->format.wBitsPerSample = 8 *
1375 (wwo->format.wf.nAvgBytesPerSec /
1376 wwo->format.wf.nSamplesPerSec) /
1377 wwo->format.wf.nChannels;
1380 EnterCriticalSection(&wwo->access_crst);
1381 retval = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
1382 LeaveCriticalSection(&wwo->access_crst);
1387 /**************************************************************************
1388 * wodClose [internal]
1390 static DWORD wodClose(WORD wDevID)
1392 DWORD ret = MMSYSERR_NOERROR;
1395 TRACE("(%u);\n", wDevID);
1397 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1399 WARN("bad device ID !\n");
1400 return MMSYSERR_BADDEVICEID;
1403 wwo = &WOutDev[wDevID];
1404 if (wwo->lpQueuePtr)
1406 WARN("buffers still playing !\n");
1407 ret = WAVERR_STILLPLAYING;
1410 /* sanity check: this should not happen since the device must have been reset before */
1411 if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
1413 wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
1416 JACK_CloseWaveOutDevice(wwo, FALSE); /* close the jack device, DO NOT force the client to close */
1418 JACK_CloseWaveOutDevice(wwo); /* close the jack device */
1420 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1422 ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
1429 /**************************************************************************
1430 * wodWrite [internal]
1433 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1438 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1440 /* first, do the sanity checks... */
1441 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1443 WARN("bad dev ID !\n");
1444 return MMSYSERR_BADDEVICEID;
1447 wwo = &WOutDev[wDevID];
1449 if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1451 TRACE("unprepared\n");
1452 return WAVERR_UNPREPARED;
1455 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1457 TRACE("still playing\n");
1458 return WAVERR_STILLPLAYING;
1461 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1462 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1463 lpWaveHdr->lpNext = 0;
1465 EnterCriticalSection(&wwo->access_crst);
1467 /* insert buffer at the end of queue */
1468 for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
1471 if (!wwo->lpPlayPtr)
1472 wodHelper_BeginWaveHdr(wwo,lpWaveHdr);
1473 if (wwo->state == WINE_WS_STOPPED)
1474 wwo->state = WINE_WS_PLAYING;
1475 LeaveCriticalSection(&wwo->access_crst);
1477 return MMSYSERR_NOERROR;
1480 /**************************************************************************
1481 * wodPrepare [internal]
1483 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1485 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1487 if (wDevID >= MAX_WAVEOUTDRV)
1489 WARN("bad device ID !\n");
1490 return MMSYSERR_BADDEVICEID;
1493 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1494 return WAVERR_STILLPLAYING;
1496 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1497 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1498 return MMSYSERR_NOERROR;
1501 /**************************************************************************
1502 * wodUnprepare [internal]
1504 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1506 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1508 if (wDevID >= MAX_WAVEOUTDRV)
1510 WARN("bad device ID !\n");
1511 return MMSYSERR_BADDEVICEID;
1514 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1515 return WAVERR_STILLPLAYING;
1517 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1518 lpWaveHdr->dwFlags |= WHDR_DONE;
1520 return MMSYSERR_NOERROR;
1523 /**************************************************************************
1524 * wodPause [internal]
1526 static DWORD wodPause(WORD wDevID)
1528 TRACE("(%u);!\n", wDevID);
1530 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1532 WARN("bad device ID !\n");
1533 return MMSYSERR_BADDEVICEID;
1536 TRACE("[3-PAUSING]\n");
1538 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1539 wodHelper_Reset(&WOutDev[wDevID], FALSE);
1540 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1542 return MMSYSERR_NOERROR;
1545 /**************************************************************************
1546 * wodRestart [internal]
1548 static DWORD wodRestart(WORD wDevID)
1550 TRACE("(%u);\n", wDevID);
1552 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1554 WARN("bad device ID !\n");
1555 return MMSYSERR_BADDEVICEID;
1558 if (WOutDev[wDevID].state == WINE_WS_PAUSED)
1560 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1561 WOutDev[wDevID].state = WINE_WS_PLAYING;
1562 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1565 return MMSYSERR_NOERROR;
1568 /**************************************************************************
1569 * wodReset [internal]
1571 static DWORD wodReset(WORD wDevID)
1573 TRACE("(%u);\n", wDevID);
1575 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1577 WARN("bad device ID !\n");
1578 return MMSYSERR_BADDEVICEID;
1581 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1582 wodHelper_Reset(&WOutDev[wDevID], TRUE);
1583 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1585 return MMSYSERR_NOERROR;
1588 /**************************************************************************
1589 * wodGetPosition [internal]
1591 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1597 TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1599 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1601 WARN("bad device ID !\n");
1602 return MMSYSERR_BADDEVICEID;
1605 /* if null pointer to time structure return error */
1606 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1608 wwo = &WOutDev[wDevID];
1610 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1611 val = wwo->dwPlayedTotal;
1612 elapsedMS = GetTickCount() - wwo->tickCountMS;
1613 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1615 /* account for the bytes played since the last JACK_Callback() */
1616 val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
1618 return bytes_to_mmtime(lpTime, val, &wwo->format);
1621 /**************************************************************************
1622 * wodBreakLoop [internal]
1624 static DWORD wodBreakLoop(WORD wDevID)
1626 TRACE("(%u);\n", wDevID);
1628 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1630 WARN("bad device ID !\n");
1631 return MMSYSERR_BADDEVICEID;
1634 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1636 if (WOutDev[wDevID].state == WINE_WS_PLAYING && WOutDev[wDevID].lpLoopPtr != NULL)
1638 /* ensure exit at end of current loop */
1639 WOutDev[wDevID].dwLoops = 1;
1642 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1644 return MMSYSERR_NOERROR;
1647 /**************************************************************************
1648 * wodGetVolume [internal]
1650 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1654 left = WOutDev[wDevID].volume_left;
1655 right = WOutDev[wDevID].volume_right;
1657 TRACE("(%u, %p);\n", wDevID, lpdwVol);
1659 *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
1662 return MMSYSERR_NOERROR;
1665 /**************************************************************************
1666 * wodSetVolume [internal]
1668 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1672 left = (LOWORD(dwParam) * 100) / 0xFFFFl;
1673 right = (HIWORD(dwParam) * 100) / 0xFFFFl;
1675 TRACE("(%u, %08lX);\n", wDevID, dwParam);
1677 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1679 WOutDev[wDevID].volume_left = left;
1680 WOutDev[wDevID].volume_right = right;
1682 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1684 return MMSYSERR_NOERROR;
1687 /**************************************************************************
1688 * wodGetNumDevs [internal]
1690 static DWORD wodGetNumDevs(void)
1692 return MAX_WAVEOUTDRV;
1695 /**************************************************************************
1696 * wodDevInterfaceSize [internal]
1698 static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
1700 TRACE("(%u, %p)\n", wDevID, dwParam1);
1702 *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1703 NULL, 0 ) * sizeof(WCHAR);
1704 return MMSYSERR_NOERROR;
1707 /**************************************************************************
1708 * wodDevInterface [internal]
1710 static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
1712 if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1713 NULL, 0 ) * sizeof(WCHAR))
1715 MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1716 dwParam1, dwParam2 / sizeof(WCHAR));
1717 return MMSYSERR_NOERROR;
1719 return MMSYSERR_INVALPARAM;
1722 /**************************************************************************
1723 * wodMessage (WINEJACK.7)
1725 DWORD WINAPI JACK_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
1726 DWORD dwParam1, DWORD dwParam2)
1728 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
1729 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1733 TRACE("DRVM_INIT\n");
1734 return JACK_WaveInit();
1736 TRACE("DRVM_EXIT\n");
1737 return JACK_WaveRelease();
1739 /* FIXME: Pretend this is supported */
1740 TRACE("DRVM_ENABLE\n");
1743 /* FIXME: Pretend this is supported */
1744 TRACE("DRVM_DISABLE\n");
1746 case WODM_OPEN: return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1747 case WODM_CLOSE: return wodClose(wDevID);
1748 case WODM_WRITE: return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1749 case WODM_PAUSE: return wodPause(wDevID);
1750 case WODM_GETPOS: return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1751 case WODM_BREAKLOOP: return wodBreakLoop(wDevID);
1752 case WODM_PREPARE: return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1753 case WODM_UNPREPARE: return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1754 case WODM_GETDEVCAPS: return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSA)dwParam1, dwParam2);
1755 case WODM_GETNUMDEVS: return wodGetNumDevs();
1756 case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED;
1757 case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED;
1758 case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1759 case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1760 case WODM_GETVOLUME: return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1761 case WODM_SETVOLUME: return wodSetVolume(wDevID, dwParam1);
1762 case WODM_RESTART: return wodRestart(wDevID);
1763 case WODM_RESET: return wodReset(wDevID);
1765 case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
1766 case DRV_QUERYDEVICEINTERFACE: return wodDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
1767 case DRV_QUERYDSOUNDIFACE: return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1);
1768 case DRV_QUERYDSOUNDDESC: return wodDsDesc(wDevID, (PDSDRIVERDESC)dwParam1);
1770 FIXME("unknown message %d!\n", wMsg);
1772 return MMSYSERR_NOTSUPPORTED;
1775 /*======================================================================*
1776 * Low level DSOUND implementation *
1777 *======================================================================*/
1779 typedef struct IDsDriverImpl IDsDriverImpl;
1780 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;
1782 struct IDsDriverImpl
1784 /* IUnknown fields */
1785 IDsDriverVtbl *lpVtbl;
1787 /* IDsDriverImpl fields */
1789 IDsDriverBufferImpl*primary;
1792 struct IDsDriverBufferImpl
1794 /* IUnknown fields */
1795 IDsDriverBufferVtbl *lpVtbl;
1797 /* IDsDriverBufferImpl fields */
1802 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
1804 /* we can't perform memory mapping as we don't have a file stream
1805 interface with jack like we do with oss */
1806 MESSAGE("This sound card's driver does not support direct access\n");
1807 MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
1808 return MMSYSERR_NOTSUPPORTED;
1811 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
1813 memset(desc, 0, sizeof(*desc));
1814 strcpy(desc->szDesc, "Wine jack DirectSound Driver");
1815 strcpy(desc->szDrvName, "winejack.drv");
1816 return MMSYSERR_NOERROR;
1819 /*======================================================================*
1820 * Low level WAVE IN implementation *
1821 *======================================================================*/
1823 /**************************************************************************
1824 * widNotifyClient [internal]
1826 static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1828 TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
1834 if (wwi->wFlags != DCB_NULL &&
1835 !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
1836 (HDRVR)wwi->waveDesc.hWave, wMsg, wwi->waveDesc.dwInstance,
1837 dwParam1, dwParam2))
1839 WARN("can't notify client !\n");
1840 return MMSYSERR_ERROR;
1844 FIXME("Unknown callback message %u\n", wMsg);
1845 return MMSYSERR_INVALPARAM;
1847 return MMSYSERR_NOERROR;
1850 /******************************************************************
1853 /* everytime the jack server wants something from us it calls this
1855 int JACK_callback_wwi (nframes_t nframes, void *arg)
1859 WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
1861 TRACE("wDevID: %u, nframes %u\n", wwi->wDevID, nframes);
1864 ERR("client is closed, this is weird...\n");
1866 in_l = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_l, nframes);
1869 in_r = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_r, nframes);
1871 EnterCriticalSection(&wwi->access_crst);
1873 if((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
1875 LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
1876 nframes_t jackFramesLeft = nframes;
1879 if(wwi->in_use == FALSE)
1881 /* do nothing if nothing is being recorded */
1886 TRACE("wwi.state == WINE_WS_PLAYING\n");
1888 while (lpWaveHdr && jackFramesLeft)
1890 DWORD waveHdrFramesLeft = (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded) / (sizeof(short) * wwi->format.wf.nChannels);
1891 DWORD numFrames = min (jackFramesLeft, waveHdrFramesLeft);
1893 TRACE ("dwBufferLength=(%lu) dwBytesRecorded=(%ld)\n", lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
1894 TRACE ("jackFramesLeft=(%u) waveHdrFramesLeft=(%lu)\n", jackFramesLeft, waveHdrFramesLeft);
1898 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded), in_l+(nframes-jackFramesLeft), numFrames, 1);
1901 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded),
1902 in_l+(nframes-jackFramesLeft), numFrames, 2);
1903 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded + sizeof(short)),
1904 in_r+(nframes-jackFramesLeft), numFrames, 2);
1907 lpWaveHdr->dwBytesRecorded += (numFrames * sizeof(short) * wwi->format.wf.nChannels );
1908 jackFramesLeft -= numFrames;
1910 if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
1912 /* must copy the value of next waveHdr, because we have no idea of what
1913 * will be done with the content of lpWaveHdr in callback
1915 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
1917 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1918 lpWaveHdr->dwFlags |= WHDR_DONE;
1920 TRACE("WaveHdr full. dwBytesRecorded=(%lu) dwFlags=(0x%lx)\n",lpWaveHdr->dwBytesRecorded,lpWaveHdr->dwFlags);
1922 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1924 lpWaveHdr = wwi->lpQueuePtr = lpNext;
1927 TRACE ("jackFramesLeft=(%u) lpWaveHdr=(%p)\n", jackFramesLeft, lpWaveHdr);
1928 if (jackFramesLeft > 0) { WARN("Record buffer ran out of WaveHdrs\n"); }
1931 LeaveCriticalSection(&wwi->access_crst);
1936 /******************************************************************
1937 * JACK_OpenWaveInDevice
1939 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels)
1943 char client_name[64];
1944 jack_port_t* in_port_l;
1945 jack_port_t* in_port_r = 0;
1946 jack_client_t* client;
1949 TRACE("creating jack client and setting up callbacks\n");
1951 if ((nChannels == 0) || (nChannels > 2)) {
1952 ERR ("nChannels = (%d), but we only support mono or stereo.\n", nChannels);
1957 /* see if this device is already open */
1960 /* if this device is already in use then it is bad for us to be in here */
1964 TRACE("using existing client\n");
1970 /* zero out the buffer pointer and the size of the buffer */
1971 wwi->sound_buffer = 0;
1972 wwi->buffer_size = 0;
1974 /* try to become a client of the JACK server */
1975 snprintf(client_name, sizeof(client_name), "wine_jack_in_%d", wwi->wDevID);
1976 TRACE("client name '%s'\n", client_name);
1977 if ((client = fp_jack_client_new (client_name)) == 0)
1979 /* jack has problems with shutting down clients, so lets */
1980 /* wait a short while and try once more before we give up */
1982 if ((client = fp_jack_client_new (client_name)) == 0)
1984 ERR("jack server not running?\n");
1988 wwi->client = client;
1990 /* tell the JACK server to call `JACK_wwi_callback()' whenever
1991 there is work to be done. */
1992 fp_jack_set_process_callback (client, JACK_callback_wwi, wwi);
1994 /* tell the JACK server to call `JACK_bufsize_wwi()' whenever
1995 the maximum number of frames that will be passed
1996 to `JACK_Callback()' changes */
1997 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwi, wwi);
1999 /* tell the JACK server to call `srate()' whenever
2000 the sample rate of the system changes. */
2001 fp_jack_set_sample_rate_callback (client, JACK_srate, wwi);
2003 /* tell the JACK server to call `jack_shutdown()' if
2004 it ever shuts down, either entirely, or if it
2005 just decides to stop calling us. */
2006 fp_jack_on_shutdown (client, JACK_shutdown_wwi, wwi);
2008 /* display the current sample rate. once the client is activated
2009 (see below), you should rely on your own sample rate
2010 callback (see above) for this value. */
2011 wwi->sample_rate = fp_jack_get_sample_rate(client);
2012 TRACE("engine sample rate: %lu\n", wwi->sample_rate);
2014 /* create the left and right channel output ports */
2015 /* jack's ports are all mono so for stereo you need two */
2016 in_port_l = fp_jack_port_register (client, "in_l",
2017 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
2018 wwi->in_port_l = in_port_l;
2019 TRACE("Created port. (%p)\n", in_port_l);
2023 in_port_r = fp_jack_port_register (client, "in_r",
2024 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
2025 TRACE("Created port. (%p)\n", in_port_r);
2027 wwi->in_port_r = in_port_r;
2030 wwi->in_use = TRUE; /* mark this device as in use since it now is ;-) */
2033 TRACE("activating client.\n");
2034 /* tell the JACK server that we are ready to roll */
2035 if (fp_jack_activate (client))
2037 ERR( "cannot activate client\n");
2040 TRACE("activated client.\n");
2041 /* figure out what the ports that we want to output on are */
2042 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
2043 /* this way works if names are changed */
2044 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
2046 /* display a trace of the output ports we found */
2047 for(i = 0; ports[i]; i++)
2049 TRACE("ports[%d] = '%s'\n", i, ports[i]);
2054 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsOutput'\n");
2057 /* connect the ports. Note: you can't do this before
2058 the client is activated (this may change in the future).
2060 /* we want to connect to two ports so we have stereo input ;-) */
2062 if(fp_jack_connect(client, ports[0], fp_jack_port_name(in_port_l)))
2064 ERR ("cannot connect to input port %d('%s')\n", 0, ports[0]);
2067 TRACE("Connected (%s)<->(%s)\n",ports[0],fp_jack_port_name(in_port_l));
2069 if ((nChannels == 2) && in_port_r) {
2070 if(fp_jack_connect(client, ports[1], fp_jack_port_name(in_port_r)))
2072 ERR ("cannot connect to input port %d('%s')\n", 1, ports[1]);
2075 TRACE("Connected (%s)<->(%s)\n",ports[1],fp_jack_port_name(in_port_r));
2077 free(ports); /* free the returned array of ports */
2079 /* if something failed we need to shut the client down and return 0 */
2083 JACK_CloseWaveInDevice(wwi, TRUE);
2085 JACK_CloseWaveInDevice(wwi);
2090 TRACE("return success.\n");
2091 return 1; /* return success */
2094 /**************************************************************************
2095 * widGetDevCaps [internal]
2097 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSA lpCaps, DWORD dwSize)
2099 TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
2101 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
2103 if (wDevID >= MAX_WAVEINDRV) {
2104 TRACE("MAX_WAVEINDRV reached !\n");
2105 return MMSYSERR_BADDEVICEID;
2108 memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
2109 return MMSYSERR_NOERROR;
2112 /**************************************************************************
2113 * widOpen [internal]
2115 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
2120 TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
2123 WARN("Invalid Parameter !\n");
2124 return MMSYSERR_INVALPARAM;
2126 if (wDevID >= MAX_WAVEINDRV) {
2127 TRACE ("MAX_WAVEINDRV reached !\n");
2128 return MMSYSERR_BADDEVICEID;
2132 if(WInDev[wDevID].client && WOutDev[wDevID].in_use)
2134 if(WInDev[wDevID].client)
2137 TRACE("device %d already allocated\n", wDevID);
2138 return MMSYSERR_ALLOCATED;
2141 /* Only the PCM format is supported so far...
2142 * Also we only support 16 bit mode.
2144 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
2145 lpDesc->lpFormat->nChannels == 0 ||
2146 lpDesc->lpFormat->nSamplesPerSec == 0 ||
2147 lpDesc->lpFormat->wBitsPerSample!=16)
2149 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
2150 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2151 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
2152 return WAVERR_BADFORMAT;
2155 if (dwFlags & WAVE_FORMAT_QUERY)
2157 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
2158 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2159 lpDesc->lpFormat->nSamplesPerSec);
2160 return MMSYSERR_NOERROR;
2163 wwi = &WInDev[wDevID];
2164 wwi->wDevID = wDevID;
2166 /* Set things up before we call JACK_OpenWaveOutDevice because */
2167 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
2168 /* even returns and we want to be initialized before then */
2169 wwi->state = WINE_WS_STOPPED; /* start in a stopped state */
2171 InitializeCriticalSection(&wwi->access_crst); /* initialize the critical section */
2172 EnterCriticalSection(&wwi->access_crst);
2174 /* open up jack ports for this device */
2175 if (!JACK_OpenWaveInDevice(&WInDev[wDevID], lpDesc->lpFormat->nChannels))
2177 ERR("JACK_OpenWaveInDevice(%d) failed\n", wDevID);
2178 LeaveCriticalSection(&wwi->access_crst);
2179 DeleteCriticalSection(&wwi->access_crst);
2180 return MMSYSERR_ERROR; /* return unspecified error */
2183 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
2185 wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
2187 memcpy(&wwi->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
2188 memcpy(&wwi->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
2190 LeaveCriticalSection(&wwi->access_crst);
2192 /* display the current wave format */
2193 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
2194 wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
2195 wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
2196 wwi->format.wf.nBlockAlign);
2198 /* make sure that we have the same sample rate in our audio stream */
2199 /* as we do in the jack server */
2200 if(wwi->format.wf.nSamplesPerSec != wwi->sample_rate)
2202 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
2203 wwi->sample_rate, wwi->format.wf.nSamplesPerSec);
2206 JACK_CloseWaveInDevice(wwi, FALSE); /* close this device, don't force the client to close */
2208 JACK_CloseWaveInDevice(wwi); /* close this device */
2210 DeleteCriticalSection(&wwi->access_crst);
2211 return WAVERR_BADFORMAT;
2214 /* check for an invalid number of bits per sample */
2215 if (wwi->format.wBitsPerSample == 0)
2217 WARN("Resetting zeroed wBitsPerSample\n");
2218 wwi->format.wBitsPerSample = 8 *
2219 (wwi->format.wf.nAvgBytesPerSec /
2220 wwi->format.wf.nSamplesPerSec) /
2221 wwi->format.wf.nChannels;
2224 TRACE("notify client.\n");
2225 EnterCriticalSection(&wwi->access_crst);
2226 retval = widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
2227 LeaveCriticalSection(&wwi->access_crst);
2231 /**************************************************************************
2232 * widClose [internal]
2234 static DWORD widClose(WORD wDevID)
2236 DWORD ret = MMSYSERR_NOERROR;
2239 TRACE("(%u);\n", wDevID);
2241 if (wDevID >= MAX_WAVEINDRV || !WInDev[wDevID].client)
2243 WARN("bad device ID !\n");
2244 return MMSYSERR_BADDEVICEID;
2247 wwi = &WInDev[wDevID];
2248 if (wwi->lpQueuePtr)
2250 WARN("buffers still playing !\n");
2251 ret = WAVERR_STILLPLAYING;
2254 /* sanity check: this should not happen since the device must have been reset before */
2255 if (wwi->lpQueuePtr) ERR("out of sync\n");
2257 wwi->state = WINE_WS_CLOSED; /* mark the device as closed */
2260 JACK_CloseWaveInDevice(wwi, FALSE); /* close the jack device, DO NOT force the client to close */
2262 JACK_CloseWaveInDevice(wwi); /* close the jack device */
2264 DeleteCriticalSection(&wwi->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
2266 ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
2272 /**************************************************************************
2273 * widAddBuffer [internal]
2275 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2277 WINE_WAVEIN* wwi = &WInDev[wDevID];
2279 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2281 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2282 WARN("can't do it !\n");
2283 return MMSYSERR_INVALHANDLE;
2285 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
2286 TRACE("never been prepared !\n");
2287 return WAVERR_UNPREPARED;
2289 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2290 TRACE("header already in use !\n");
2291 return WAVERR_STILLPLAYING;
2294 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
2295 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2296 lpWaveHdr->dwBytesRecorded = 0;
2297 lpWaveHdr->lpNext = NULL;
2299 EnterCriticalSection(&wwi->access_crst);
2300 /* insert buffer at end of queue */
2303 for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
2306 LeaveCriticalSection(&wwi->access_crst);
2308 return MMSYSERR_NOERROR;
2311 /**************************************************************************
2312 * widPrepare [internal]
2314 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2316 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2318 if (wDevID >= MAX_WAVEINDRV) return MMSYSERR_INVALHANDLE;
2320 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
2321 return WAVERR_STILLPLAYING;
2323 lpWaveHdr->dwFlags |= WHDR_PREPARED;
2324 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2325 lpWaveHdr->dwBytesRecorded = 0;
2326 lpWaveHdr->lpNext = NULL;
2328 return MMSYSERR_NOERROR;
2331 /**************************************************************************
2332 * widUnprepare [internal]
2334 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2336 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2337 if (wDevID >= MAX_WAVEINDRV) {
2338 WARN("bad device ID !\n");
2339 return MMSYSERR_INVALHANDLE;
2342 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2343 TRACE("Still playing...\n");
2344 return WAVERR_STILLPLAYING;
2347 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
2348 lpWaveHdr->dwFlags |= WHDR_DONE;
2350 return MMSYSERR_NOERROR;
2353 /**************************************************************************
2354 * widStart [internal]
2356 static DWORD widStart(WORD wDevID)
2358 TRACE("(%u);\n", wDevID);
2359 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2360 WARN("can't start recording !\n");
2361 return MMSYSERR_INVALHANDLE;
2364 WInDev[wDevID].state = WINE_WS_PLAYING;
2365 return MMSYSERR_NOERROR;
2368 /**************************************************************************
2369 * widStop [internal]
2371 static DWORD widStop(WORD wDevID)
2373 WINE_WAVEIN* wwi = &WInDev[wDevID];
2375 TRACE("(%u);\n", wDevID);
2376 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2377 WARN("can't stop !\n");
2378 return MMSYSERR_INVALHANDLE;
2381 if (wwi->state != WINE_WS_STOPPED)
2384 /* do something here to stop recording ??? */
2386 /* return current buffer to app */
2387 lpWaveHdr = wwi->lpQueuePtr;
2390 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
2391 TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2392 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2393 lpWaveHdr->dwFlags |= WHDR_DONE;
2394 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2395 wwi->lpQueuePtr = lpNext;
2398 wwi->state = WINE_WS_STOPPED;
2400 return MMSYSERR_NOERROR;
2403 /**************************************************************************
2404 * widReset [internal]
2406 static DWORD widReset(WORD wDevID)
2408 WINE_WAVEIN* wwi = &WInDev[wDevID];
2411 TRACE("(%u);\n", wDevID);
2412 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2413 WARN("can't reset !\n");
2414 return MMSYSERR_INVALHANDLE;
2417 wwi->state = WINE_WS_STOPPED;
2419 /* return all buffers to the app */
2420 for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
2421 TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2422 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2423 lpWaveHdr->dwFlags |= WHDR_DONE;
2425 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2427 wwi->lpQueuePtr = NULL;
2429 return MMSYSERR_NOERROR;
2432 /**************************************************************************
2433 * widGetNumDevs [internal]
2435 static DWORD widGetNumDevs(void)
2437 return MAX_WAVEINDRV;
2440 /**************************************************************************
2441 * widDevInterfaceSize [internal]
2443 static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
2445 TRACE("(%u, %p)\n", wDevID, dwParam1);
2448 *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2449 NULL, 0 ) * sizeof(WCHAR);
2450 return MMSYSERR_NOERROR;
2453 /**************************************************************************
2454 * widDevInterface [internal]
2456 static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
2458 if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2459 NULL, 0 ) * sizeof(WCHAR))
2461 MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2462 dwParam1, dwParam2 / sizeof(WCHAR));
2463 return MMSYSERR_NOERROR;
2465 return MMSYSERR_INVALPARAM;
2468 /**************************************************************************
2469 * widMessage (WINEJACK.6)
2471 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2472 DWORD dwParam1, DWORD dwParam2)
2474 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
2475 wDevID, wMsg, dwUser, dwParam1, dwParam2);
2482 /* FIXME: Pretend this is supported */
2484 case WIDM_OPEN: return widOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
2485 case WIDM_CLOSE: return widClose (wDevID);
2486 case WIDM_ADDBUFFER: return widAddBuffer (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2487 case WIDM_PREPARE: return widPrepare (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2488 case WIDM_UNPREPARE: return widUnprepare (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2489 case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (LPWAVEINCAPSA)dwParam1, dwParam2);
2490 case WIDM_GETNUMDEVS: return widGetNumDevs();
2491 case WIDM_RESET: return widReset (wDevID);
2492 case WIDM_START: return widStart (wDevID);
2493 case WIDM_STOP: return widStop (wDevID);
2494 case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
2495 case DRV_QUERYDEVICEINTERFACE: return widDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
2497 FIXME("unknown message %d!\n", wMsg);
2500 return MMSYSERR_NOTSUPPORTED;
2503 #else /* !HAVE_JACK_JACK_H */
2505 /**************************************************************************
2506 * widMessage (WINEJACK.6)
2508 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2509 DWORD dwParam1, DWORD dwParam2)
2511 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2512 return MMSYSERR_NOTENABLED;
2515 /**************************************************************************
2516 * wodMessage (WINEJACK.7)
2518 DWORD WINAPI JACK_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2519 DWORD dwParam1, DWORD dwParam2)
2521 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2522 return MMSYSERR_NOTENABLED;
2525 #endif /* HAVE_JACK_JACK_H */