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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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
33 * pause in waveOut during loop is not handled correctly
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>
64 WINE_DEFAULT_DEBUG_CHANNEL(wave
);
66 #ifdef HAVE_JACK_JACK_H
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
);
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
126 volatile int state
; /* one of the WINE_WS_ manifest constants */
127 WAVEOPENDESC waveDesc
;
129 PCMWAVEFORMAT format
;
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 */
140 BOOL in_use
; /* TRUE if this device is in use */
144 unsigned long buffer_size
;
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
;
168 WAVEOPENDESC waveDesc
;
170 PCMWAVEFORMAT format
;
171 LPWAVEHDR lpQueuePtr
;
172 DWORD dwTotalRecorded
;
174 BOOL bTriggerSupport
;
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 */
184 BOOL in_use
; /* TRUE if this device is in use */
188 unsigned long buffer_size
;
190 /* synchronization stuff */
191 CRITICAL_SECTION access_crst
;
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
);
207 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT
* wwo
, BOOL close_client
);
209 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT
* wwo
);
213 static void JACK_CloseWaveInDevice(WINE_WAVEIN
* wwi
, BOOL close_client
);
215 static void JACK_CloseWaveInDevice(WINE_WAVEIN
* wwi
);
218 static DWORD
bytes_to_mmtime(LPMMTIME lpTime
, DWORD position
,
219 PCMWAVEFORMAT
* format
)
221 TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
222 lpTime
->wType
, format
->wBitsPerSample
, format
->wf
.nSamplesPerSec
,
223 format
->wf
.nChannels
, format
->wf
.nAvgBytesPerSec
);
224 TRACE("Position in bytes=%lu\n", position
);
226 switch (lpTime
->wType
) {
228 lpTime
->u
.sample
= position
/ (format
->wBitsPerSample
/ 8 * format
->wf
.nChannels
);
229 TRACE("TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
232 lpTime
->u
.ms
= 1000.0 * position
/ (format
->wBitsPerSample
/ 8 * format
->wf
.nChannels
* format
->wf
.nSamplesPerSec
);
233 TRACE("TIME_MS=%lu\n", lpTime
->u
.ms
);
236 position
= position
/ (format
->wBitsPerSample
/ 8 * format
->wf
.nChannels
);
237 lpTime
->u
.smpte
.sec
= position
/ format
->wf
.nSamplesPerSec
;
238 position
-= lpTime
->u
.smpte
.sec
* format
->wf
.nSamplesPerSec
;
239 lpTime
->u
.smpte
.min
= lpTime
->u
.smpte
.sec
/ 60;
240 lpTime
->u
.smpte
.sec
-= 60 * lpTime
->u
.smpte
.min
;
241 lpTime
->u
.smpte
.hour
= lpTime
->u
.smpte
.min
/ 60;
242 lpTime
->u
.smpte
.min
-= 60 * lpTime
->u
.smpte
.hour
;
243 lpTime
->u
.smpte
.fps
= 30;
244 lpTime
->u
.smpte
.frame
= position
* lpTime
->u
.smpte
.fps
/ format
->wf
.nSamplesPerSec
;
245 position
-= lpTime
->u
.smpte
.frame
* format
->wf
.nSamplesPerSec
/ lpTime
->u
.smpte
.fps
;
249 lpTime
->u
.smpte
.frame
++;
251 TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
252 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
253 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
256 WARN("Format %d not supported, using TIME_BYTES !\n", lpTime
->wType
);
257 lpTime
->wType
= TIME_BYTES
;
260 lpTime
->u
.cb
= position
;
261 TRACE("TIME_BYTES=%lu\n", lpTime
->u
.cb
);
264 return MMSYSERR_NOERROR
;
268 /*======================================================================*
269 * Low level WAVE implementation *
270 *======================================================================*/
272 #define SAMPLE_MAX_16BIT 32767.0f
274 /* Alsaplayer function that applies volume changes to a buffer */
275 /* (C) Andy Lo A Foe */
276 /* Length is in terms of 32 bit samples */
277 void volume_effect32(void *buffer
, int length
, int left
, int right
)
279 short *data
= (short *)buffer
;
282 if (right
== -1) right
= left
;
284 for(i
= 0; i
< length
; i
++) {
285 v
= (int) ((*(data
) * left
) / 100);
286 *(data
++) = (v
>32767) ? 32767 : ((v
<-32768) ? -32768 : v
);
287 v
= (int) ((*(data
) * right
) / 100);
288 *(data
++) = (v
>32767) ? 32767 : ((v
<-32768) ? -32768 : v
);
292 /* move 16 bit mono/stereo to 16 bit stereo */
293 void sample_move_d16_d16(short *dst
, short *src
,
294 unsigned long nsamples
, int nChannels
)
301 if(nChannels
== 2) src
++;
310 /* convert from 16 bit to floating point */
311 /* allow for copying of stereo data with alternating left/right */
312 /* channels to a buffer that will hold a single channel stream */
313 /* nsamples is in terms of 16bit samples */
314 /* src_skip is in terms of 16bit samples */
315 void sample_move_d16_s16 (sample_t
*dst
, short *src
,
316 unsigned long nsamples
, unsigned long src_skip
)
318 /* ALERT: signed sign-extension portability !!! */
321 *dst
= (*src
) / SAMPLE_MAX_16BIT
;
327 /* convert from floating point to 16 bit */
328 /* allow for copying of a buffer that will hold a single channel stream */
329 /* to stereo data with alternating left/right channels */
330 /* nsamples is in terms of float samples */
331 /* dst_skip is in terms of 16bit samples */
332 void sample_move_s16_d16 (short *dst
, sample_t
*src
,
333 unsigned long nsamples
, unsigned long dst_skip
)
335 /* ALERT: signed sign-extension portability !!! */
338 *dst
= (*src
) * SAMPLE_MAX_16BIT
;
339 /* TRACE("src=(%.8f,%p) dst=(%d,%p)\n",*src,src,*dst,dst); */
346 /* fill dst buffer with nsamples worth of silence */
347 void sample_silence_dS (sample_t
*dst
, unsigned long nsamples
)
349 /* ALERT: signed sign-extension portability !!! */
357 /******************************************************************
360 /* everytime the jack server wants something from us it calls this
361 function, so we either deliver it some sound to play or deliver it nothing
363 int JACK_callback_wwo (nframes_t nframes
, void *arg
)
367 WINE_WAVEOUT
* wwo
= (WINE_WAVEOUT
*)arg
;
369 TRACE("wDevID: %u, nframes %u state=%u\n", wwo
->wDevID
, nframes
,wwo
->state
);
372 ERR("client is closed, this is weird...\n");
374 out_l
= (sample_t
*) fp_jack_port_get_buffer(wwo
->out_port_l
, nframes
);
375 out_r
= (sample_t
*) fp_jack_port_get_buffer(wwo
->out_port_r
, nframes
);
377 if(wwo
->state
== WINE_WS_PLAYING
)
379 DWORD jackFramesAvailable
= nframes
;
380 DWORD outputFramesAvailable
;
381 DWORD numFramesToWrite
;
387 if(wwo
->in_use
== FALSE
)
389 /* output silence if nothing is being outputted */
390 sample_silence_dS(out_l
, nframes
);
391 sample_silence_dS(out_r
, nframes
);
397 TRACE("wwo.state == WINE_WS_PLAYING\n");
399 /* see if our sound_buffer is large enough to hold the number of frames jack requested */
400 /* Note: sound_buffer is always filled with 16-bit stereo data, even for mono mode */
401 if(wwo
->buffer_size
< (nframes
* sizeof(short) * 2))
403 ERR("for some reason JACK_BufSize() didn't allocate enough memory\n");
404 ERR("allocated %ld bytes, need %d bytes\n", wwo
->buffer_size
, (nframes
* sizeof(short) * 2));
408 /* while we have jackFramesAvailable and a wave header to be played */
409 while(jackFramesAvailable
&& wwo
->lpPlayPtr
)
411 /* find the amount of audio to be played at this time */
412 outputFramesAvailable
= (wwo
->lpPlayPtr
->dwBufferLength
- wwo
->dwPartialOffset
) / wwo
->format
.wf
.nBlockAlign
;
414 numFramesToWrite
= min(jackFramesAvailable
, outputFramesAvailable
);
415 TRACE("dwBufferLength=(%ld) dwPartialOffset=(%ld)\n",wwo
->lpPlayPtr
->dwBufferLength
,wwo
->dwPartialOffset
);
416 TRACE("outputFramesAvailable == %ld, jackFramesAvailable == %ld\n", outputFramesAvailable
, jackFramesAvailable
);
418 buffer
= wwo
->lpPlayPtr
->lpData
+ wwo
->dwPartialOffset
;
420 /* convert from mono to stereo if necessary */
421 /* otherwise just memcpy to the output buffer */
423 if(wwo
->format
.wf
.nChannels
== 1)
425 sample_move_d16_d16((short*)wwo
->sound_buffer
+ ((nframes
- jackFramesAvailable
) * sizeof(short)),
426 (short*)buffer
, numFramesToWrite
, wwo
->format
.wf
.nChannels
);
427 } else /* just copy the memory over */
429 memcpy(wwo
->sound_buffer
+ ((nframes
- jackFramesAvailable
) * wwo
->format
.wf
.nBlockAlign
),
430 buffer
, numFramesToWrite
* wwo
->format
.wf
.nBlockAlign
);
433 /* advance to the next wave header if possible, or advance pointer */
434 /* inside of the current header if we haven't completed it */
435 if(numFramesToWrite
== outputFramesAvailable
)
437 wodHelper_PlayPtrNext(wwo
); /* we wrote the whole waveheader, skip to the next one*/
441 wwo
->dwPartialOffset
+=(numFramesToWrite
* wwo
->format
.wf
.nBlockAlign
); /* else advance by the bytes we took in to write */
444 written
+=(numFramesToWrite
* wwo
->format
.wf
.nBlockAlign
); /* add on what we wrote */
445 jackFramesAvailable
-=numFramesToWrite
; /* take away what was written in terms of output bytes */
448 wwo
->tickCountMS
= GetTickCount(); /* record the current time */
449 wwo
->dwWrittenTotal
+=written
; /* update states on wave device */
450 wwo
->dwPlayedTotal
+=wwo
->bytesInJack
; /* we must have finished with the last bytes or we wouldn't be back inside of this callback again... */
451 wwo
->bytesInJack
= written
; /* record the bytes inside of jack */
453 /* Now that we have finished filling the buffer either until it is full or until */
454 /* we have run out of application sound data to process, apply volume and output */
455 /* the audio to the jack server */
457 /* apply volume to the buffer */
458 volume_effect32(wwo
->sound_buffer
, (nframes
- jackFramesAvailable
), wwo
->volume_left
, wwo
->volume_right
);
460 /* convert from stereo 16 bit to single channel 32 bit float */
461 /* for each jack server channel */
462 /* NOTE: we skip over two sample since we want to only get either the left or right channel */
463 sample_move_d16_s16(out_l
, (short*)wwo
->sound_buffer
, (nframes
- jackFramesAvailable
), 2);
464 sample_move_d16_s16(out_r
, (short*)wwo
->sound_buffer
+ 1, (nframes
- jackFramesAvailable
), 2);
466 /* see if we still have jackBytesLeft here, if we do that means that we
467 ran out of wave data to play and had a buffer underrun, fill in
468 the rest of the space with zero bytes */
469 if(jackFramesAvailable
)
471 ERR("buffer underrun of %ld frames\n", jackFramesAvailable
);
472 sample_silence_dS(out_l
+ (nframes
- jackFramesAvailable
), jackFramesAvailable
);
473 sample_silence_dS(out_r
+ (nframes
- jackFramesAvailable
), jackFramesAvailable
);
476 else if(wwo
->state
== WINE_WS_PAUSED
||
477 wwo
->state
== WINE_WS_STOPPED
||
478 wwo
->state
== WINE_WS_CLOSED
)
480 /* output silence if nothing is being outputted */
481 sample_silence_dS(out_l
, nframes
);
482 sample_silence_dS(out_r
, nframes
);
485 /* notify the client of completed wave headers */
486 EnterCriticalSection(&wwo
->access_crst
);
487 wodHelper_NotifyCompletions(wwo
, FALSE
);
488 LeaveCriticalSection(&wwo
->access_crst
);
493 /******************************************************************
496 * Called whenever the jack server changes the the max number
497 * of frames passed to JACK_callback
499 int JACK_bufsize_wwo (nframes_t nframes
, void *arg
)
501 WINE_WAVEOUT
* wwo
= (WINE_WAVEOUT
*)arg
;
502 DWORD buffer_required
;
503 TRACE("wDevID=%d\n",wwo
->wDevID
);
504 TRACE("the maximum buffer size is now %u frames\n", nframes
);
506 /* make sure the callback routine has adequate memory */
507 /* see if our buffer is large enough for the data we are writing */
508 /* ie. Buffer_size < (bytes we already wrote + bytes we are going to write in this loop) */
509 EnterCriticalSection(&wwo
->access_crst
);
511 /* wwo->sound_buffer is always filled with 16-bit stereo data, even for mono streams */
512 buffer_required
= nframes
* sizeof(short) * 2;
513 TRACE("wwo->buffer_size (%ld) buffer_required (%ld).\n", wwo
->buffer_size
,buffer_required
);
514 if(wwo
->buffer_size
< buffer_required
)
516 TRACE("expanding buffer from wwo->buffer_size == %ld, to %ld\n",
517 wwo
->buffer_size
, buffer_required
);
518 TRACE("GetProcessHeap() == %p\n", GetProcessHeap());
519 wwo
->buffer_size
= buffer_required
;
521 if (wwo
->sound_buffer
)
522 wwo
->sound_buffer
= HeapReAlloc(GetProcessHeap(), 0, wwo
->sound_buffer
, wwo
->buffer_size
);
524 wwo
->sound_buffer
= HeapAlloc(GetProcessHeap(), 0, wwo
->buffer_size
);
526 /* if we don't have a buffer then error out */
527 if(!wwo
->sound_buffer
)
529 ERR("error allocating sound_buffer memory\n");
530 LeaveCriticalSection(&wwo
->access_crst
);
535 LeaveCriticalSection(&wwo
->access_crst
);
541 /******************************************************************
544 * Called whenever the jack server changes the the max number
545 * of frames passed to JACK_callback
547 int JACK_bufsize_wwi (nframes_t nframes
, void *arg
)
549 TRACE("the maximum buffer size is now %u frames\n", nframes
);
553 /******************************************************************
556 int JACK_srate (nframes_t nframes
, void *arg
)
558 TRACE("the sample rate is now %u/sec\n", nframes
);
563 /******************************************************************
566 /* if this is called then jack shut down... handle this appropriately */
567 void JACK_shutdown_wwo(void* arg
)
569 WINE_WAVEOUT
* wwo
= (WINE_WAVEOUT
*)arg
;
571 wwo
->client
= 0; /* reset client */
573 TRACE("trying to reconnect after sleeping for a short while...\n");
575 /* lets see if we can't reestablish the connection */
576 Sleep(750); /* pause for a short period of time */
577 if(!JACK_OpenWaveOutDevice(wwo
))
579 ERR("unable to reconnect with jack...\n");
583 /******************************************************************
586 /* if this is called then jack shut down... handle this appropriately */
587 void JACK_shutdown_wwi(void* arg
)
589 WINE_WAVEIN
* wwi
= (WINE_WAVEIN
*)arg
;
591 wwi
->client
= 0; /* reset client */
593 TRACE("trying to reconnect after sleeping for a short while...\n");
595 /* lets see if we can't reestablish the connection */
596 Sleep(750); /* pause for a short period of time */
597 if(!JACK_OpenWaveInDevice(wwi
,wwi
->format
.wf
.nChannels
))
599 ERR("unable to reconnect with jack...\n");
604 /******************************************************************
605 * JACK_OpenWaveOutDevice
607 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT
* wwo
)
611 char client_name
[64];
612 jack_port_t
* out_port_l
;
613 jack_port_t
* out_port_r
;
614 jack_client_t
* client
;
617 TRACE("creating jack client and setting up callbacks\n");
620 /* see if this device is already open */
623 /* if this device is already in use then it is bad for us to be in here */
627 TRACE("using existing client\n");
633 /* zero out the buffer pointer and the size of the buffer */
634 wwo
->sound_buffer
= 0;
635 wwo
->buffer_size
= 0;
637 /* try to become a client of the JACK server */
638 snprintf(client_name
, sizeof(client_name
), "wine_jack_out_%d", wwo
->wDevID
);
639 TRACE("client name '%s'\n", client_name
);
640 if ((client
= fp_jack_client_new (client_name
)) == 0)
642 /* jack has problems with shutting down clients, so lets */
643 /* wait a short while and try once more before we give up */
645 if ((client
= fp_jack_client_new (client_name
)) == 0)
647 ERR("jack server not running?\n");
652 /* tell the JACK server to call `JACK_callback_wwo()' whenever
653 there is work to be done. */
654 fp_jack_set_process_callback (client
, JACK_callback_wwo
, wwo
);
656 /* tell the JACK server to call `JACK_bufsize_wwo()' whenever
657 the maximum number of frames that will be passed
658 to `JACK_Callback()' changes */
659 fp_jack_set_buffer_size_callback (client
, JACK_bufsize_wwo
, wwo
);
661 /* tell the JACK server to call `srate()' whenever
662 the sample rate of the system changes. */
663 fp_jack_set_sample_rate_callback (client
, JACK_srate
, wwo
);
665 /* tell the JACK server to call `jack_shutdown()' if
666 it ever shuts down, either entirely, or if it
667 just decides to stop calling us. */
668 fp_jack_on_shutdown (client
, JACK_shutdown_wwo
, wwo
);
670 /* display the current sample rate. once the client is activated
671 (see below), you should rely on your own sample rate
672 callback (see above) for this value. */
673 wwo
->sample_rate
= fp_jack_get_sample_rate(client
);
674 TRACE("engine sample rate: %lu\n", wwo
->sample_rate
);
676 /* create the left and right channel output ports */
677 /* jack's ports are all mono so for stereo you need two */
678 out_port_l
= fp_jack_port_register (client
, "out_l",
679 JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
681 out_port_r
= fp_jack_port_register (client
, "out_r",
682 JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
684 TRACE("Created ports. (%p) (%p)\n",out_port_l
, out_port_r
);
686 /* save away important values to the WINE_WAVEOUT struct */
687 wwo
->client
= client
;
688 wwo
->out_port_l
= out_port_l
;
689 wwo
->out_port_r
= out_port_r
;
692 wwo
->in_use
= TRUE
; /* mark this device as in use since it now is ;-) */
695 /* set initial buffer size */
696 JACK_bufsize_wwo (fp_jack_get_buffer_size(client
),wwo
);
698 /* tell the JACK server that we are ready to roll */
699 if (fp_jack_activate (client
))
701 ERR( "cannot activate client\n");
705 TRACE("jack activate.\n");
706 /* figure out what the ports that we want to output on are */
707 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
708 /* this way works if names are changed */
709 ports
= fp_jack_get_ports(client
, NULL
, NULL
, JackPortIsPhysical
|JackPortIsInput
);
711 /* display a trace of the output ports we found */
712 for(i
= 0; ports
[i
]; i
++)
714 TRACE("ports[%d] = '%s'\n", i
, ports
[i
]);
719 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsInput'\n");
722 /* connect the ports. Note: you can't do this before
723 the client is activated (this may change in the future).
725 /* we want to connect to two ports so we have stereo output ;-) */
727 if(fp_jack_connect(client
, fp_jack_port_name(out_port_l
), ports
[0]))
729 ERR ("cannot connect to output port %d('%s')\n", 0, ports
[0]);
733 if(fp_jack_connect(client
, fp_jack_port_name(out_port_r
), ports
[1]))
735 ERR ("cannot connect to output port %d('%s')\n", 1, ports
[1]);
739 free(ports
); /* free the returned array of ports */
741 /* if something failed we need to shut the client down and return 0 */
745 JACK_CloseWaveOutDevice(wwo
, TRUE
);
747 JACK_CloseWaveOutDevice(wwo
);
752 return 1; /* return success */
755 /******************************************************************
756 * JACK_CloseWaveOutDevice
758 * Close the connection to the server cleanly.
759 * If close_client is TRUE we close the client for this device instead of
760 * just marking the device as in_use(JACK_CLOSE_HACK only)
763 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT
* wwo
, BOOL close_client
)
765 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT
* wwo
)
769 TRACE("wDevID: %d, close_client (wwo): %d\n", wwo
->wDevID
, close_client
);
771 TRACE("wDevID: %d\n", wwo
->wDevID
);
778 fp_jack_deactivate(wwo
->client
); /* supposed to help the jack_client_close() to succeed */
779 fp_jack_client_close (wwo
->client
);
781 EnterCriticalSection(&wwo
->access_crst
);
782 wwo
->client
= 0; /* reset client */
783 HeapFree(GetProcessHeap(), 0, wwo
->sound_buffer
); /* free buffer memory */
784 wwo
->sound_buffer
= 0;
785 wwo
->buffer_size
= 0; /* zero out size of the buffer */
786 LeaveCriticalSection(&wwo
->access_crst
);
790 EnterCriticalSection(&wwo
->access_crst
);
791 TRACE("setting in_use to FALSE\n");
793 LeaveCriticalSection(&wwo
->access_crst
);
798 /******************************************************************
799 * JACK_CloseWaveInDevice
801 * Close the connection to the server cleanly.
802 * If close_client is TRUE we close the client for this device instead of
803 * just marking the device as in_use(JACK_CLOSE_HACK only)
806 static void JACK_CloseWaveInDevice(WINE_WAVEIN
* wwi
, BOOL close_client
)
808 static void JACK_CloseWaveInDevice(WINE_WAVEIN
* wwi
)
812 TRACE("wDevID: %d, close_client (wwi): %d\n", wwi
->wDevID
, close_client
);
814 TRACE("wDevID: %d\n", wwi
->wDevID
);
821 fp_jack_deactivate(wwi
->client
); /* supposed to help the jack_client_close() to succeed */
822 fp_jack_client_close (wwi
->client
);
824 EnterCriticalSection(&wwi
->access_crst
);
825 wwi
->client
= 0; /* reset client */
826 HeapFree(GetProcessHeap(), 0, wwi
->sound_buffer
); /* free buffer memory */
827 wwi
->sound_buffer
= 0;
828 wwi
->buffer_size
= 0; /* zero out size of the buffer */
829 LeaveCriticalSection(&wwi
->access_crst
);
833 EnterCriticalSection(&wwi
->access_crst
);
834 TRACE("setting in_use to FALSE\n");
836 LeaveCriticalSection(&wwi
->access_crst
);
841 /******************************************************************
846 LONG
JACK_WaveRelease(void)
850 TRACE("closing all open waveout devices\n");
852 /* close all open output devices */
853 for(iDevice
= 0; iDevice
< MAX_WAVEOUTDRV
; iDevice
++)
855 TRACE("iDevice == %d\n", iDevice
);
856 if(WOutDev
[iDevice
].client
)
859 JACK_CloseWaveOutDevice(&WOutDev
[iDevice
], TRUE
); /* close the device, FORCE the client to close */
861 JACK_CloseWaveOutDevice(&WOutDev
[iDevice
]); /* close the device, FORCE the client to close */
863 DeleteCriticalSection(&(WOutDev
[iDevice
].access_crst
)); /* delete the critical section */
867 TRACE("closing all open wavein devices\n");
869 /* close all open input devices */
870 for(iDevice
= 0; iDevice
< MAX_WAVEINDRV
; iDevice
++)
872 TRACE("iDevice == %d\n", iDevice
);
873 if(WInDev
[iDevice
].client
)
876 JACK_CloseWaveInDevice(&WInDev
[iDevice
], TRUE
); /* close the device, FORCE the client to close */
878 JACK_CloseWaveInDevice(&WInDev
[iDevice
]); /* close the device, FORCE the client to close */
880 DeleteCriticalSection(&(WInDev
[iDevice
].access_crst
)); /* delete the critical section */
884 TRACE("returning 1\n");
889 /******************************************************************
892 * Initialize internal structures from JACK server info
894 LONG
JACK_WaveInit(void)
898 static const WCHAR ini_out
[] = {'J','A','C','K',' ','W','a','v','e','O','u','t',' ','D','r','i','v','e','r',0};
899 static const WCHAR ini_in
[] = {'J','A','C','K',' ','W','a','v','e','I','n',' ',' ','D','r','i','v','e','r',0};
903 /* setup function pointers */
904 #define LOAD_FUNCPTR(f) if((fp_##f = wine_dlsym(jackhandle, #f, NULL, 0)) == NULL) goto sym_not_found;
905 LOAD_FUNCPTR(jack_activate
);
906 LOAD_FUNCPTR(jack_connect
);
907 LOAD_FUNCPTR(jack_client_new
);
908 LOAD_FUNCPTR(jack_client_close
);
909 LOAD_FUNCPTR(jack_deactivate
);
910 LOAD_FUNCPTR(jack_set_process_callback
);
911 LOAD_FUNCPTR(jack_set_buffer_size_callback
);
912 LOAD_FUNCPTR(jack_set_sample_rate_callback
);
913 LOAD_FUNCPTR(jack_on_shutdown
);
914 LOAD_FUNCPTR(jack_get_sample_rate
);
915 LOAD_FUNCPTR(jack_port_register
);
916 LOAD_FUNCPTR(jack_port_get_buffer
);
917 LOAD_FUNCPTR(jack_get_ports
);
918 LOAD_FUNCPTR(jack_port_name
);
919 LOAD_FUNCPTR(jack_get_buffer_size
);
922 /* start with output device */
924 for (i
= 0; i
< MAX_WAVEOUTDRV
; ++i
)
926 WOutDev
[i
].client
= 0; /* initialize the client to 0 */
929 WOutDev
[i
].in_use
= FALSE
;
930 WInDev
[i
].in_use
= FALSE
;
933 memset(&WOutDev
[i
].caps
, 0, sizeof(WOutDev
[i
].caps
));
935 WOutDev
[i
].caps
.wMid
= 0x00FF; /* Manufac ID */
936 WOutDev
[i
].caps
.wPid
= 0x0001; /* Product ID */
937 strcpyW(WOutDev
[i
].caps
.szPname
, ini_out
);
939 snprintf(WOutDev
[i
].interface_name
, sizeof(WOutDev
[i
].interface_name
), "winejack: %d", i
);
941 WOutDev
[i
].caps
.vDriverVersion
= 0x0100;
942 WOutDev
[i
].caps
.dwFormats
= 0x00000000;
943 WOutDev
[i
].caps
.dwSupport
= WAVECAPS_VOLUME
;
945 WOutDev
[i
].caps
.wChannels
= 2;
946 WOutDev
[i
].caps
.dwSupport
|= WAVECAPS_LRVOLUME
;
948 /* NOTE: we don't support any 8 bit modes so note that */
949 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
950 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
951 WOutDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_4S16
;
952 WOutDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_4M16
;
953 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
954 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
955 WOutDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_2M16
;
956 WOutDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_2S16
;
957 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
958 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
959 WOutDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_1M16
;
960 WOutDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_1S16
;
963 /* then do input device */
964 for (i
= 0; i
< MAX_WAVEINDRV
; ++i
)
966 /* TODO: we should initialize read stuff here */
967 memset(&WInDev
[0].caps
, 0, sizeof(WInDev
[0].caps
));
969 WInDev
[i
].caps
.wMid
= 0x00FF;
970 WInDev
[i
].caps
.wPid
= 0x0001;
971 strcpyW(WInDev
[i
].caps
.szPname
, ini_in
);
972 snprintf(WInDev
[i
].interface_name
, sizeof(WInDev
[i
].interface_name
), "winejack: %d", i
);
974 WInDev
[i
].caps
.vDriverVersion
= 0x0100;
976 WInDev
[i
].caps
.wChannels
= 0x2;
977 /* NOTE: we don't support any 8 bit modes so note that */
978 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
979 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
980 WInDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_4S16
;
981 WInDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_4M16
;
982 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
983 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
984 WInDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_2M16
;
985 WInDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_2S16
;
986 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
987 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
988 WInDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_1M16
;
989 WInDev
[i
].caps
.dwFormats
|= WAVE_FORMAT_1S16
;
990 WInDev
[i
].caps
.wReserved1
= 0;
993 return 1; /* return success */
995 /* error path for function pointer loading errors */
998 "Wine cannot find certain functions that it needs inside the jack"
999 "library. To enable Wine to use the jack audio server please "
1000 "install libjack\n");
1001 wine_dlclose(jackhandle
, NULL
, 0);
1006 /*======================================================================*
1007 * Low level WAVE OUT implementation *
1008 *======================================================================*/
1010 /**************************************************************************
1011 * wodNotifyClient [internal]
1013 static DWORD
wodNotifyClient(WINE_WAVEOUT
* wwo
, WORD wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1015 TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg
, dwParam1
, dwParam2
);
1021 if (wwo
->wFlags
!= DCB_NULL
&&
1022 !DriverCallback(wwo
->waveDesc
.dwCallback
, wwo
->wFlags
,
1023 (HDRVR
)wwo
->waveDesc
.hWave
, wMsg
, wwo
->waveDesc
.dwInstance
,
1024 dwParam1
, dwParam2
))
1026 WARN("can't notify client !\n");
1027 return MMSYSERR_ERROR
;
1031 FIXME("Unknown callback message %u\n", wMsg
);
1032 return MMSYSERR_INVALPARAM
;
1034 return MMSYSERR_NOERROR
;
1037 /**************************************************************************
1038 * wodHelper_BeginWaveHdr [internal]
1040 * Makes the specified lpWaveHdr the currently playing wave header.
1041 * If the specified wave header is a begin loop and we're not already in
1042 * a loop, setup the loop.
1044 static void wodHelper_BeginWaveHdr(WINE_WAVEOUT
* wwo
, LPWAVEHDR lpWaveHdr
)
1046 EnterCriticalSection(&wwo
->access_crst
);
1048 wwo
->lpPlayPtr
= lpWaveHdr
;
1052 LeaveCriticalSection(&wwo
->access_crst
);
1056 if (lpWaveHdr
->dwFlags
& WHDR_BEGINLOOP
)
1060 WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr
);
1061 TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr
);
1064 TRACE("Starting loop (%ldx) with %p\n", lpWaveHdr
->dwLoops
, lpWaveHdr
);
1065 wwo
->lpLoopPtr
= lpWaveHdr
;
1066 /* Windows does not touch WAVEHDR.dwLoops,
1067 * so we need to make an internal copy */
1068 wwo
->dwLoops
= lpWaveHdr
->dwLoops
;
1071 wwo
->dwPartialOffset
= 0;
1073 LeaveCriticalSection(&wwo
->access_crst
);
1077 /**************************************************************************
1078 * wodHelper_PlayPtrNext [internal]
1080 * Advance the play pointer to the next waveheader, looping if required.
1082 static LPWAVEHDR
wodHelper_PlayPtrNext(WINE_WAVEOUT
* wwo
)
1084 LPWAVEHDR lpWaveHdr
;
1086 EnterCriticalSection(&wwo
->access_crst
);
1088 lpWaveHdr
= wwo
->lpPlayPtr
;
1090 wwo
->dwPartialOffset
= 0;
1091 if ((lpWaveHdr
->dwFlags
& WHDR_ENDLOOP
) && wwo
->lpLoopPtr
)
1093 /* We're at the end of a loop, loop if required */
1094 if (--wwo
->dwLoops
> 0)
1096 wwo
->lpPlayPtr
= wwo
->lpLoopPtr
;
1099 /* Handle overlapping loops correctly */
1100 if (wwo
->lpLoopPtr
!= lpWaveHdr
&& (lpWaveHdr
->dwFlags
& WHDR_BEGINLOOP
)) {
1101 FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
1102 /* shall we consider the END flag for the closing loop or for
1103 * the opening one or for both ???
1104 * code assumes for closing loop only
1108 lpWaveHdr
= lpWaveHdr
->lpNext
;
1110 wwo
->lpLoopPtr
= NULL
;
1111 wodHelper_BeginWaveHdr(wwo
, lpWaveHdr
);
1115 /* We're not in a loop. Advance to the next wave header */
1116 TRACE("not inside of a loop, advancing to next wave header\n");
1117 wodHelper_BeginWaveHdr(wwo
, lpWaveHdr
= lpWaveHdr
->lpNext
);
1120 LeaveCriticalSection(&wwo
->access_crst
);
1125 /* if force is TRUE then notify the client that all the headers were completed */
1126 static DWORD
wodHelper_NotifyCompletions(WINE_WAVEOUT
* wwo
, BOOL force
)
1128 LPWAVEHDR lpWaveHdr
;
1133 EnterCriticalSection(&wwo
->access_crst
);
1135 /* Start from lpQueuePtr and keep notifying until:
1136 * - we hit an unwritten wavehdr
1137 * - we hit the beginning of a running loop
1138 * - we hit a wavehdr which hasn't finished playing
1140 while ((lpWaveHdr
= wwo
->lpQueuePtr
) &&
1142 (lpWaveHdr
!= wwo
->lpPlayPtr
&&
1143 lpWaveHdr
!= wwo
->lpLoopPtr
)))
1145 wwo
->lpQueuePtr
= lpWaveHdr
->lpNext
;
1147 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1148 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1149 TRACE("notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) dwFlags=(%ld)\n",
1150 lpWaveHdr
, wwo
->lpPlayPtr
, lpWaveHdr
->dwFlags
);
1152 wodNotifyClient(wwo
, WOM_DONE
, (DWORD
)lpWaveHdr
, 0);
1154 TRACE("Not notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) lpLoopPtr=(%p)\n",
1155 lpWaveHdr
, wwo
->lpPlayPtr
, wwo
->lpLoopPtr
);
1156 retval
= (lpWaveHdr
&& lpWaveHdr
!= wwo
->lpPlayPtr
&& lpWaveHdr
!=
1157 wwo
->lpLoopPtr
) ? 0 : INFINITE
;
1159 LeaveCriticalSection(&wwo
->access_crst
);
1164 /**************************************************************************
1165 * wodHelper_Reset [internal]
1167 * Resets current output stream.
1169 static void wodHelper_Reset(WINE_WAVEOUT
* wwo
, BOOL reset
)
1171 EnterCriticalSection(&wwo
->access_crst
);
1173 /* updates current notify list */
1174 wodHelper_NotifyCompletions(wwo
, FALSE
);
1178 /* remove all wave headers and notify client that all headers were completed */
1179 wodHelper_NotifyCompletions(wwo
, TRUE
);
1181 wwo
->lpPlayPtr
= wwo
->lpQueuePtr
= wwo
->lpLoopPtr
= NULL
;
1182 wwo
->state
= WINE_WS_STOPPED
;
1183 wwo
->dwPlayedTotal
= wwo
->dwWrittenTotal
= wwo
->bytesInJack
= 0;
1185 wwo
->dwPartialOffset
= 0; /* Clear partial wavehdr */
1190 /* complicated case, not handled yet (could imply modifying the loop counter) */
1191 FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
1192 wwo
->lpPlayPtr
= wwo
->lpLoopPtr
;
1193 wwo
->dwPartialOffset
= 0;
1194 wwo
->dwWrittenTotal
= wwo
->dwPlayedTotal
; /* this is wrong !!! */
1198 DWORD sz
= wwo
->dwPartialOffset
;
1200 /* reset all the data as if we had written only up to lpPlayedTotal bytes */
1201 /* compute the max size playable from lpQueuePtr */
1202 for (ptr
= wwo
->lpQueuePtr
; ptr
!= wwo
->lpPlayPtr
; ptr
= ptr
->lpNext
)
1204 sz
+= ptr
->dwBufferLength
;
1207 /* because the reset lpPlayPtr will be lpQueuePtr */
1208 if (wwo
->dwWrittenTotal
> wwo
->dwPlayedTotal
+ sz
) ERR("doh\n");
1209 wwo
->dwPartialOffset
= sz
- (wwo
->dwWrittenTotal
- wwo
->dwPlayedTotal
);
1210 wwo
->dwWrittenTotal
= wwo
->dwPlayedTotal
;
1211 wwo
->lpPlayPtr
= wwo
->lpQueuePtr
;
1214 wwo
->state
= WINE_WS_PAUSED
;
1217 LeaveCriticalSection(&wwo
->access_crst
);
1220 /**************************************************************************
1221 * wodGetDevCaps [internal]
1223 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPSW lpCaps
, DWORD dwSize
)
1225 TRACE("(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1227 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1229 if (wDevID
>= MAX_WAVEOUTDRV
)
1231 TRACE("MAX_WAVOUTDRV reached !\n");
1232 return MMSYSERR_BADDEVICEID
;
1235 TRACE("dwSupport=(0x%lx), dwFormats=(0x%lx)\n", WOutDev
[wDevID
].caps
.dwSupport
, WOutDev
[wDevID
].caps
.dwFormats
);
1236 memcpy(lpCaps
, &WOutDev
[wDevID
].caps
, min(dwSize
, sizeof(*lpCaps
)));
1237 return MMSYSERR_NOERROR
;
1240 /**************************************************************************
1241 * wodOpen [internal]
1243 * NOTE: doesn't it seem like there is a race condition if you try to open
1244 * the same device twice?
1246 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1251 TRACE("(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1254 WARN("Invalid Parameter !\n");
1255 return MMSYSERR_INVALPARAM
;
1257 if (wDevID
>= MAX_WAVEOUTDRV
) {
1258 TRACE("MAX_WAVOUTDRV reached !\n");
1259 return MMSYSERR_BADDEVICEID
;
1263 if(WOutDev
[wDevID
].client
&& WOutDev
[wDevID
].in_use
)
1265 if(WOutDev
[wDevID
].client
)
1268 TRACE("device %d already allocated\n", wDevID
);
1269 return MMSYSERR_ALLOCATED
;
1272 /* Only the PCM format is supported so far...
1273 * Also we only support 16 bit mode.
1275 if (lpDesc
->lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
||
1276 lpDesc
->lpFormat
->nChannels
== 0 ||
1277 lpDesc
->lpFormat
->nSamplesPerSec
== 0 ||
1278 lpDesc
->lpFormat
->wBitsPerSample
!= 16)
1280 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
1281 lpDesc
->lpFormat
->wFormatTag
, lpDesc
->lpFormat
->nChannels
,
1282 lpDesc
->lpFormat
->nSamplesPerSec
, lpDesc
->lpFormat
->wBitsPerSample
);
1283 return WAVERR_BADFORMAT
;
1286 if (dwFlags
& WAVE_FORMAT_QUERY
)
1288 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1289 lpDesc
->lpFormat
->wFormatTag
, lpDesc
->lpFormat
->nChannels
,
1290 lpDesc
->lpFormat
->nSamplesPerSec
);
1291 return MMSYSERR_NOERROR
;
1294 wwo
= &WOutDev
[wDevID
];
1295 wwo
->wDevID
= wDevID
;
1297 /* Set things up before we call JACK_OpenWaveOutDevice because */
1298 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
1299 /* even returns and we want to be initialized before then */
1300 wwo
->state
= WINE_WS_STOPPED
; /* start in a stopped state */
1301 wwo
->dwPlayedTotal
= 0; /* zero out these totals */
1302 wwo
->dwWrittenTotal
= 0;
1303 wwo
->bytesInJack
= 0;
1304 wwo
->tickCountMS
= 0;
1306 /* Initialize volume to full level */
1307 wwo
->volume_left
= 100;
1308 wwo
->volume_right
= 100;
1310 InitializeCriticalSection(&wwo
->access_crst
); /* initialize the critical section */
1311 EnterCriticalSection(&wwo
->access_crst
);
1313 dwFlags
&= ~WAVE_DIRECTSOUND
; /* direct sound not supported, ignore the flag */
1315 wwo
->wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1317 memcpy(&wwo
->waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1318 memcpy(&wwo
->format
, lpDesc
->lpFormat
, sizeof(PCMWAVEFORMAT
));
1320 /* open up jack ports for this device */
1321 if (!JACK_OpenWaveOutDevice(&WOutDev
[wDevID
]))
1323 ERR("JACK_OpenWaveOutDevice(%d) failed\n", wDevID
);
1324 LeaveCriticalSection(&wwo
->access_crst
);
1325 DeleteCriticalSection(&wwo
->access_crst
); /* delete the critical section so we can initialize it again from wodOpen() */
1326 return MMSYSERR_ERROR
; /* return unspecified error */
1329 LeaveCriticalSection(&wwo
->access_crst
);
1331 /* display the current wave format */
1332 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
1333 wwo
->format
.wBitsPerSample
, wwo
->format
.wf
.nAvgBytesPerSec
,
1334 wwo
->format
.wf
.nSamplesPerSec
, wwo
->format
.wf
.nChannels
,
1335 wwo
->format
.wf
.nBlockAlign
);
1337 /* make sure that we have the same sample rate in our audio stream */
1338 /* as we do in the jack server */
1339 if(wwo
->format
.wf
.nSamplesPerSec
!= wwo
->sample_rate
)
1341 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
1342 wwo
->sample_rate
, wwo
->format
.wf
.nSamplesPerSec
);
1345 JACK_CloseWaveOutDevice(wwo
, FALSE
); /* close this device, don't force the client to close */
1347 JACK_CloseWaveOutDevice(wwo
); /* close this device */
1349 DeleteCriticalSection(&wwo
->access_crst
); /* delete the critical section so we can initialize it again from wodOpen() */
1350 return WAVERR_BADFORMAT
;
1353 /* check for an invalid number of bits per sample */
1354 if (wwo
->format
.wBitsPerSample
== 0)
1356 WARN("Resetting zeroed wBitsPerSample\n");
1357 wwo
->format
.wBitsPerSample
= 8 *
1358 (wwo
->format
.wf
.nAvgBytesPerSec
/
1359 wwo
->format
.wf
.nSamplesPerSec
) /
1360 wwo
->format
.wf
.nChannels
;
1363 EnterCriticalSection(&wwo
->access_crst
);
1364 retval
= wodNotifyClient(wwo
, WOM_OPEN
, 0L, 0L);
1365 LeaveCriticalSection(&wwo
->access_crst
);
1370 /**************************************************************************
1371 * wodClose [internal]
1373 static DWORD
wodClose(WORD wDevID
)
1375 DWORD ret
= MMSYSERR_NOERROR
;
1378 TRACE("(%u);\n", wDevID
);
1380 if (wDevID
>= MAX_WAVEOUTDRV
|| !WOutDev
[wDevID
].client
)
1382 WARN("bad device ID !\n");
1383 return MMSYSERR_BADDEVICEID
;
1386 wwo
= &WOutDev
[wDevID
];
1387 if (wwo
->lpQueuePtr
)
1389 WARN("buffers still playing !\n");
1390 ret
= WAVERR_STILLPLAYING
;
1393 /* sanity check: this should not happen since the device must have been reset before */
1394 if (wwo
->lpQueuePtr
|| wwo
->lpPlayPtr
) ERR("out of sync\n");
1396 wwo
->state
= WINE_WS_CLOSED
; /* mark the device as closed */
1399 JACK_CloseWaveOutDevice(wwo
, FALSE
); /* close the jack device, DO NOT force the client to close */
1401 JACK_CloseWaveOutDevice(wwo
); /* close the jack device */
1403 DeleteCriticalSection(&wwo
->access_crst
); /* delete the critical section so we can initialize it again from wodOpen() */
1405 ret
= wodNotifyClient(wwo
, WOM_CLOSE
, 0L, 0L);
1412 /**************************************************************************
1413 * wodWrite [internal]
1416 static DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1421 TRACE("(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1423 /* first, do the sanity checks... */
1424 if (wDevID
>= MAX_WAVEOUTDRV
|| !WOutDev
[wDevID
].client
)
1426 WARN("bad dev ID !\n");
1427 return MMSYSERR_BADDEVICEID
;
1430 wwo
= &WOutDev
[wDevID
];
1432 if (lpWaveHdr
->lpData
== NULL
|| !(lpWaveHdr
->dwFlags
& WHDR_PREPARED
))
1434 TRACE("unprepared\n");
1435 return WAVERR_UNPREPARED
;
1438 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
1440 TRACE("still playing\n");
1441 return WAVERR_STILLPLAYING
;
1444 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1445 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1446 lpWaveHdr
->lpNext
= 0;
1448 EnterCriticalSection(&wwo
->access_crst
);
1450 /* insert buffer at the end of queue */
1451 for (wh
= &(wwo
->lpQueuePtr
); *wh
; wh
= &((*wh
)->lpNext
));
1454 if (!wwo
->lpPlayPtr
)
1455 wodHelper_BeginWaveHdr(wwo
,lpWaveHdr
);
1456 if (wwo
->state
== WINE_WS_STOPPED
)
1457 wwo
->state
= WINE_WS_PLAYING
;
1458 LeaveCriticalSection(&wwo
->access_crst
);
1460 return MMSYSERR_NOERROR
;
1463 /**************************************************************************
1464 * wodPrepare [internal]
1466 static DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1468 TRACE("(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1470 if (wDevID
>= MAX_WAVEOUTDRV
)
1472 WARN("bad device ID !\n");
1473 return MMSYSERR_BADDEVICEID
;
1476 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
1477 return WAVERR_STILLPLAYING
;
1479 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1480 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1481 return MMSYSERR_NOERROR
;
1484 /**************************************************************************
1485 * wodUnprepare [internal]
1487 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1489 TRACE("(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1491 if (wDevID
>= MAX_WAVEOUTDRV
)
1493 WARN("bad device ID !\n");
1494 return MMSYSERR_BADDEVICEID
;
1497 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
1498 return WAVERR_STILLPLAYING
;
1500 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1501 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1503 return MMSYSERR_NOERROR
;
1506 /**************************************************************************
1507 * wodPause [internal]
1509 static DWORD
wodPause(WORD wDevID
)
1511 TRACE("(%u);!\n", wDevID
);
1513 if (wDevID
>= MAX_WAVEOUTDRV
|| !WOutDev
[wDevID
].client
)
1515 WARN("bad device ID !\n");
1516 return MMSYSERR_BADDEVICEID
;
1519 TRACE("[3-PAUSING]\n");
1521 EnterCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1522 wodHelper_Reset(&WOutDev
[wDevID
], FALSE
);
1523 LeaveCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1525 return MMSYSERR_NOERROR
;
1528 /**************************************************************************
1529 * wodRestart [internal]
1531 static DWORD
wodRestart(WORD wDevID
)
1533 TRACE("(%u);\n", wDevID
);
1535 if (wDevID
>= MAX_WAVEOUTDRV
|| !WOutDev
[wDevID
].client
)
1537 WARN("bad device ID !\n");
1538 return MMSYSERR_BADDEVICEID
;
1541 if (WOutDev
[wDevID
].state
== WINE_WS_PAUSED
)
1543 EnterCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1544 WOutDev
[wDevID
].state
= WINE_WS_PLAYING
;
1545 LeaveCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1548 return MMSYSERR_NOERROR
;
1551 /**************************************************************************
1552 * wodReset [internal]
1554 static DWORD
wodReset(WORD wDevID
)
1556 TRACE("(%u);\n", wDevID
);
1558 if (wDevID
>= MAX_WAVEOUTDRV
|| !WOutDev
[wDevID
].client
)
1560 WARN("bad device ID !\n");
1561 return MMSYSERR_BADDEVICEID
;
1564 EnterCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1565 wodHelper_Reset(&WOutDev
[wDevID
], TRUE
);
1566 LeaveCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1568 return MMSYSERR_NOERROR
;
1571 /**************************************************************************
1572 * wodGetPosition [internal]
1574 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1580 TRACE("(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1582 if (wDevID
>= MAX_WAVEOUTDRV
|| !WOutDev
[wDevID
].client
)
1584 WARN("bad device ID !\n");
1585 return MMSYSERR_BADDEVICEID
;
1588 /* if null pointer to time structure return error */
1589 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1591 wwo
= &WOutDev
[wDevID
];
1593 EnterCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1594 val
= wwo
->dwPlayedTotal
;
1595 elapsedMS
= GetTickCount() - wwo
->tickCountMS
;
1596 LeaveCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1598 /* account for the bytes played since the last JACK_Callback() */
1599 val
+=((elapsedMS
* wwo
->format
.wf
.nAvgBytesPerSec
) / 1000);
1601 return bytes_to_mmtime(lpTime
, val
, &wwo
->format
);
1604 /**************************************************************************
1605 * wodBreakLoop [internal]
1607 static DWORD
wodBreakLoop(WORD wDevID
)
1609 TRACE("(%u);\n", wDevID
);
1611 if (wDevID
>= MAX_WAVEOUTDRV
|| !WOutDev
[wDevID
].client
)
1613 WARN("bad device ID !\n");
1614 return MMSYSERR_BADDEVICEID
;
1617 EnterCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1619 if (WOutDev
[wDevID
].state
== WINE_WS_PLAYING
&& WOutDev
[wDevID
].lpLoopPtr
!= NULL
)
1621 /* ensure exit at end of current loop */
1622 WOutDev
[wDevID
].dwLoops
= 1;
1625 LeaveCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1627 return MMSYSERR_NOERROR
;
1630 /**************************************************************************
1631 * wodGetVolume [internal]
1633 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1637 left
= WOutDev
[wDevID
].volume_left
;
1638 right
= WOutDev
[wDevID
].volume_right
;
1640 TRACE("(%u, %p);\n", wDevID
, lpdwVol
);
1642 *lpdwVol
= ((left
* 0xFFFFl
) / 100) + (((right
* 0xFFFFl
) / 100) <<
1645 return MMSYSERR_NOERROR
;
1648 /**************************************************************************
1649 * wodSetVolume [internal]
1651 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1655 left
= (LOWORD(dwParam
) * 100) / 0xFFFFl
;
1656 right
= (HIWORD(dwParam
) * 100) / 0xFFFFl
;
1658 TRACE("(%u, %08lX);\n", wDevID
, dwParam
);
1660 EnterCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1662 WOutDev
[wDevID
].volume_left
= left
;
1663 WOutDev
[wDevID
].volume_right
= right
;
1665 LeaveCriticalSection(&(WOutDev
[wDevID
].access_crst
));
1667 return MMSYSERR_NOERROR
;
1670 /**************************************************************************
1671 * wodGetNumDevs [internal]
1673 static DWORD
wodGetNumDevs(void)
1675 return MAX_WAVEOUTDRV
;
1678 /**************************************************************************
1679 * wodDevInterfaceSize [internal]
1681 static DWORD
wodDevInterfaceSize(UINT wDevID
, LPDWORD dwParam1
)
1683 TRACE("(%u, %p)\n", wDevID
, dwParam1
);
1685 *dwParam1
= MultiByteToWideChar(CP_ACP
, 0, WOutDev
[wDevID
].interface_name
, -1,
1686 NULL
, 0 ) * sizeof(WCHAR
);
1687 return MMSYSERR_NOERROR
;
1690 /**************************************************************************
1691 * wodDevInterface [internal]
1693 static DWORD
wodDevInterface(UINT wDevID
, PWCHAR dwParam1
, DWORD dwParam2
)
1695 if (dwParam2
>= MultiByteToWideChar(CP_ACP
, 0, WOutDev
[wDevID
].interface_name
, -1,
1696 NULL
, 0 ) * sizeof(WCHAR
))
1698 MultiByteToWideChar(CP_ACP
, 0, WOutDev
[wDevID
].interface_name
, -1,
1699 dwParam1
, dwParam2
/ sizeof(WCHAR
));
1700 return MMSYSERR_NOERROR
;
1702 return MMSYSERR_INVALPARAM
;
1705 /**************************************************************************
1706 * wodMessage (WINEJACK.7)
1708 DWORD WINAPI
JACK_wodMessage(UINT wDevID
, UINT wMsg
, DWORD dwUser
,
1709 DWORD dwParam1
, DWORD dwParam2
)
1711 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
1712 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1716 TRACE("DRVM_INIT\n");
1717 return JACK_WaveInit();
1719 TRACE("DRVM_EXIT\n");
1720 return JACK_WaveRelease();
1722 /* FIXME: Pretend this is supported */
1723 TRACE("DRVM_ENABLE\n");
1726 /* FIXME: Pretend this is supported */
1727 TRACE("DRVM_DISABLE\n");
1729 case WODM_OPEN
: return wodOpen(wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
1730 case WODM_CLOSE
: return wodClose(wDevID
);
1731 case WODM_WRITE
: return wodWrite(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1732 case WODM_PAUSE
: return wodPause(wDevID
);
1733 case WODM_GETPOS
: return wodGetPosition(wDevID
, (LPMMTIME
)dwParam1
, dwParam2
);
1734 case WODM_BREAKLOOP
: return wodBreakLoop(wDevID
);
1735 case WODM_PREPARE
: return wodPrepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1736 case WODM_UNPREPARE
: return wodUnprepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1737 case WODM_GETDEVCAPS
: return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPSW
)dwParam1
, dwParam2
);
1738 case WODM_GETNUMDEVS
: return wodGetNumDevs();
1739 case WODM_GETPITCH
: return MMSYSERR_NOTSUPPORTED
;
1740 case WODM_SETPITCH
: return MMSYSERR_NOTSUPPORTED
;
1741 case WODM_GETPLAYBACKRATE
: return MMSYSERR_NOTSUPPORTED
;
1742 case WODM_SETPLAYBACKRATE
: return MMSYSERR_NOTSUPPORTED
;
1743 case WODM_GETVOLUME
: return wodGetVolume(wDevID
, (LPDWORD
)dwParam1
);
1744 case WODM_SETVOLUME
: return wodSetVolume(wDevID
, dwParam1
);
1745 case WODM_RESTART
: return wodRestart(wDevID
);
1746 case WODM_RESET
: return wodReset(wDevID
);
1748 case DRV_QUERYDEVICEINTERFACESIZE
: return wodDevInterfaceSize (wDevID
, (LPDWORD
)dwParam1
);
1749 case DRV_QUERYDEVICEINTERFACE
: return wodDevInterface (wDevID
, (PWCHAR
)dwParam1
, dwParam2
);
1750 case DRV_QUERYDSOUNDIFACE
: return wodDsCreate(wDevID
, (PIDSDRIVER
*)dwParam1
);
1751 case DRV_QUERYDSOUNDDESC
: return wodDsDesc(wDevID
, (PDSDRIVERDESC
)dwParam1
);
1753 FIXME("unknown message %d!\n", wMsg
);
1755 return MMSYSERR_NOTSUPPORTED
;
1758 /*======================================================================*
1759 * Low level DSOUND implementation *
1760 *======================================================================*/
1762 typedef struct IDsDriverImpl IDsDriverImpl
;
1763 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl
;
1765 struct IDsDriverImpl
1767 /* IUnknown fields */
1768 IDsDriverVtbl
*lpVtbl
;
1770 /* IDsDriverImpl fields */
1772 IDsDriverBufferImpl
*primary
;
1775 struct IDsDriverBufferImpl
1777 /* IUnknown fields */
1778 IDsDriverBufferVtbl
*lpVtbl
;
1780 /* IDsDriverBufferImpl fields */
1785 static DWORD
wodDsCreate(UINT wDevID
, PIDSDRIVER
* drv
)
1787 /* we can't perform memory mapping as we don't have a file stream
1788 interface with jack like we do with oss */
1789 MESSAGE("This sound card's driver does not support direct access\n");
1790 MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
1791 return MMSYSERR_NOTSUPPORTED
;
1794 static DWORD
wodDsDesc(UINT wDevID
, PDSDRIVERDESC desc
)
1796 memset(desc
, 0, sizeof(*desc
));
1797 strcpy(desc
->szDesc
, "Wine jack DirectSound Driver");
1798 strcpy(desc
->szDrvName
, "winejack.drv");
1799 return MMSYSERR_NOERROR
;
1802 /*======================================================================*
1803 * Low level WAVE IN implementation *
1804 *======================================================================*/
1806 /**************************************************************************
1807 * widNotifyClient [internal]
1809 static DWORD
widNotifyClient(WINE_WAVEIN
* wwi
, WORD wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1811 TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg
, dwParam1
, dwParam2
);
1817 if (wwi
->wFlags
!= DCB_NULL
&&
1818 !DriverCallback(wwi
->waveDesc
.dwCallback
, wwi
->wFlags
,
1819 (HDRVR
)wwi
->waveDesc
.hWave
, wMsg
, wwi
->waveDesc
.dwInstance
,
1820 dwParam1
, dwParam2
))
1822 WARN("can't notify client !\n");
1823 return MMSYSERR_ERROR
;
1827 FIXME("Unknown callback message %u\n", wMsg
);
1828 return MMSYSERR_INVALPARAM
;
1830 return MMSYSERR_NOERROR
;
1833 /******************************************************************
1836 /* everytime the jack server wants something from us it calls this
1838 int JACK_callback_wwi (nframes_t nframes
, void *arg
)
1842 WINE_WAVEIN
* wwi
= (WINE_WAVEIN
*)arg
;
1844 TRACE("wDevID: %u, nframes %u\n", wwi
->wDevID
, nframes
);
1847 ERR("client is closed, this is weird...\n");
1849 in_l
= (sample_t
*) fp_jack_port_get_buffer(wwi
->in_port_l
, nframes
);
1852 in_r
= (sample_t
*) fp_jack_port_get_buffer(wwi
->in_port_r
, nframes
);
1854 EnterCriticalSection(&wwi
->access_crst
);
1856 if((wwi
->lpQueuePtr
!= NULL
) && (wwi
->state
== WINE_WS_PLAYING
))
1858 LPWAVEHDR lpWaveHdr
= wwi
->lpQueuePtr
;
1859 nframes_t jackFramesLeft
= nframes
;
1862 if(wwi
->in_use
== FALSE
)
1864 /* do nothing if nothing is being recorded */
1869 TRACE("wwi.state == WINE_WS_PLAYING\n");
1871 while (lpWaveHdr
&& jackFramesLeft
)
1873 DWORD waveHdrFramesLeft
= (lpWaveHdr
->dwBufferLength
- lpWaveHdr
->dwBytesRecorded
) / (sizeof(short) * wwi
->format
.wf
.nChannels
);
1874 DWORD numFrames
= min (jackFramesLeft
, waveHdrFramesLeft
);
1876 TRACE ("dwBufferLength=(%lu) dwBytesRecorded=(%ld)\n", lpWaveHdr
->dwBufferLength
, lpWaveHdr
->dwBytesRecorded
);
1877 TRACE ("jackFramesLeft=(%u) waveHdrFramesLeft=(%lu)\n", jackFramesLeft
, waveHdrFramesLeft
);
1881 sample_move_s16_d16((short *)((char *)lpWaveHdr
->lpData
+ lpWaveHdr
->dwBytesRecorded
), in_l
+(nframes
-jackFramesLeft
), numFrames
, 1);
1884 sample_move_s16_d16((short *)((char *)lpWaveHdr
->lpData
+ lpWaveHdr
->dwBytesRecorded
),
1885 in_l
+(nframes
-jackFramesLeft
), numFrames
, 2);
1886 sample_move_s16_d16((short *)((char *)lpWaveHdr
->lpData
+ lpWaveHdr
->dwBytesRecorded
+ sizeof(short)),
1887 in_r
+(nframes
-jackFramesLeft
), numFrames
, 2);
1890 lpWaveHdr
->dwBytesRecorded
+= (numFrames
* sizeof(short) * wwi
->format
.wf
.nChannels
);
1891 jackFramesLeft
-= numFrames
;
1893 if (lpWaveHdr
->dwBytesRecorded
>= lpWaveHdr
->dwBufferLength
)
1895 /* must copy the value of next waveHdr, because we have no idea of what
1896 * will be done with the content of lpWaveHdr in callback
1898 LPWAVEHDR lpNext
= lpWaveHdr
->lpNext
;
1900 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1901 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1903 TRACE("WaveHdr full. dwBytesRecorded=(%lu) dwFlags=(0x%lx)\n",lpWaveHdr
->dwBytesRecorded
,lpWaveHdr
->dwFlags
);
1905 widNotifyClient(wwi
, WIM_DATA
, (DWORD
)lpWaveHdr
, 0);
1907 lpWaveHdr
= wwi
->lpQueuePtr
= lpNext
;
1910 TRACE ("jackFramesLeft=(%u) lpWaveHdr=(%p)\n", jackFramesLeft
, lpWaveHdr
);
1911 if (jackFramesLeft
> 0) { WARN("Record buffer ran out of WaveHdrs\n"); }
1914 LeaveCriticalSection(&wwi
->access_crst
);
1919 /******************************************************************
1920 * JACK_OpenWaveInDevice
1922 static int JACK_OpenWaveInDevice(WINE_WAVEIN
* wwi
, WORD nChannels
)
1926 char client_name
[64];
1927 jack_port_t
* in_port_l
;
1928 jack_port_t
* in_port_r
= 0;
1929 jack_client_t
* client
;
1932 TRACE("creating jack client and setting up callbacks\n");
1934 if ((nChannels
== 0) || (nChannels
> 2)) {
1935 ERR ("nChannels = (%d), but we only support mono or stereo.\n", nChannels
);
1940 /* see if this device is already open */
1943 /* if this device is already in use then it is bad for us to be in here */
1947 TRACE("using existing client\n");
1953 /* zero out the buffer pointer and the size of the buffer */
1954 wwi
->sound_buffer
= 0;
1955 wwi
->buffer_size
= 0;
1957 /* try to become a client of the JACK server */
1958 snprintf(client_name
, sizeof(client_name
), "wine_jack_in_%d", wwi
->wDevID
);
1959 TRACE("client name '%s'\n", client_name
);
1960 if ((client
= fp_jack_client_new (client_name
)) == 0)
1962 /* jack has problems with shutting down clients, so lets */
1963 /* wait a short while and try once more before we give up */
1965 if ((client
= fp_jack_client_new (client_name
)) == 0)
1967 ERR("jack server not running?\n");
1971 wwi
->client
= client
;
1973 /* tell the JACK server to call `JACK_wwi_callback()' whenever
1974 there is work to be done. */
1975 fp_jack_set_process_callback (client
, JACK_callback_wwi
, wwi
);
1977 /* tell the JACK server to call `JACK_bufsize_wwi()' whenever
1978 the maximum number of frames that will be passed
1979 to `JACK_Callback()' changes */
1980 fp_jack_set_buffer_size_callback (client
, JACK_bufsize_wwi
, wwi
);
1982 /* tell the JACK server to call `srate()' whenever
1983 the sample rate of the system changes. */
1984 fp_jack_set_sample_rate_callback (client
, JACK_srate
, wwi
);
1986 /* tell the JACK server to call `jack_shutdown()' if
1987 it ever shuts down, either entirely, or if it
1988 just decides to stop calling us. */
1989 fp_jack_on_shutdown (client
, JACK_shutdown_wwi
, wwi
);
1991 /* display the current sample rate. once the client is activated
1992 (see below), you should rely on your own sample rate
1993 callback (see above) for this value. */
1994 wwi
->sample_rate
= fp_jack_get_sample_rate(client
);
1995 TRACE("engine sample rate: %lu\n", wwi
->sample_rate
);
1997 /* create the left and right channel output ports */
1998 /* jack's ports are all mono so for stereo you need two */
1999 in_port_l
= fp_jack_port_register (client
, "in_l",
2000 JACK_DEFAULT_AUDIO_TYPE
, JackPortIsInput
, 0);
2001 wwi
->in_port_l
= in_port_l
;
2002 TRACE("Created port. (%p)\n", in_port_l
);
2006 in_port_r
= fp_jack_port_register (client
, "in_r",
2007 JACK_DEFAULT_AUDIO_TYPE
, JackPortIsInput
, 0);
2008 TRACE("Created port. (%p)\n", in_port_r
);
2010 wwi
->in_port_r
= in_port_r
;
2013 wwi
->in_use
= TRUE
; /* mark this device as in use since it now is ;-) */
2016 TRACE("activating client.\n");
2017 /* tell the JACK server that we are ready to roll */
2018 if (fp_jack_activate (client
))
2020 ERR( "cannot activate client\n");
2023 TRACE("activated client.\n");
2024 /* figure out what the ports that we want to output on are */
2025 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
2026 /* this way works if names are changed */
2027 ports
= fp_jack_get_ports(client
, NULL
, NULL
, JackPortIsPhysical
|JackPortIsOutput
);
2029 /* display a trace of the output ports we found */
2030 for(i
= 0; ports
[i
]; i
++)
2032 TRACE("ports[%d] = '%s'\n", i
, ports
[i
]);
2037 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsOutput'\n");
2040 /* connect the ports. Note: you can't do this before
2041 the client is activated (this may change in the future).
2043 /* we want to connect to two ports so we have stereo input ;-) */
2045 if(fp_jack_connect(client
, ports
[0], fp_jack_port_name(in_port_l
)))
2047 ERR ("cannot connect to input port %d('%s')\n", 0, ports
[0]);
2050 TRACE("Connected (%s)<->(%s)\n",ports
[0],fp_jack_port_name(in_port_l
));
2052 if ((nChannels
== 2) && in_port_r
) {
2053 if(fp_jack_connect(client
, ports
[1], fp_jack_port_name(in_port_r
)))
2055 ERR ("cannot connect to input port %d('%s')\n", 1, ports
[1]);
2058 TRACE("Connected (%s)<->(%s)\n",ports
[1],fp_jack_port_name(in_port_r
));
2060 free(ports
); /* free the returned array of ports */
2062 /* if something failed we need to shut the client down and return 0 */
2066 JACK_CloseWaveInDevice(wwi
, TRUE
);
2068 JACK_CloseWaveInDevice(wwi
);
2073 TRACE("return success.\n");
2074 return 1; /* return success */
2077 /**************************************************************************
2078 * widGetDevCaps [internal]
2080 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPSW lpCaps
, DWORD dwSize
)
2082 TRACE("(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
2084 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
2086 if (wDevID
>= MAX_WAVEINDRV
) {
2087 TRACE("MAX_WAVEINDRV reached !\n");
2088 return MMSYSERR_BADDEVICEID
;
2091 memcpy(lpCaps
, &WInDev
[wDevID
].caps
, min(dwSize
, sizeof(*lpCaps
)));
2092 return MMSYSERR_NOERROR
;
2095 /**************************************************************************
2096 * widOpen [internal]
2098 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
2103 TRACE("(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
2106 WARN("Invalid Parameter !\n");
2107 return MMSYSERR_INVALPARAM
;
2109 if (wDevID
>= MAX_WAVEINDRV
) {
2110 TRACE ("MAX_WAVEINDRV reached !\n");
2111 return MMSYSERR_BADDEVICEID
;
2115 if(WInDev
[wDevID
].client
&& WOutDev
[wDevID
].in_use
)
2117 if(WInDev
[wDevID
].client
)
2120 TRACE("device %d already allocated\n", wDevID
);
2121 return MMSYSERR_ALLOCATED
;
2124 /* Only the PCM format is supported so far...
2125 * Also we only support 16 bit mode.
2127 if (lpDesc
->lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
||
2128 lpDesc
->lpFormat
->nChannels
== 0 ||
2129 lpDesc
->lpFormat
->nSamplesPerSec
== 0 ||
2130 lpDesc
->lpFormat
->wBitsPerSample
!=16)
2132 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
2133 lpDesc
->lpFormat
->wFormatTag
, lpDesc
->lpFormat
->nChannels
,
2134 lpDesc
->lpFormat
->nSamplesPerSec
, lpDesc
->lpFormat
->wBitsPerSample
);
2135 return WAVERR_BADFORMAT
;
2138 if (dwFlags
& WAVE_FORMAT_QUERY
)
2140 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
2141 lpDesc
->lpFormat
->wFormatTag
, lpDesc
->lpFormat
->nChannels
,
2142 lpDesc
->lpFormat
->nSamplesPerSec
);
2143 return MMSYSERR_NOERROR
;
2146 wwi
= &WInDev
[wDevID
];
2147 wwi
->wDevID
= wDevID
;
2149 /* Set things up before we call JACK_OpenWaveOutDevice because */
2150 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
2151 /* even returns and we want to be initialized before then */
2152 wwi
->state
= WINE_WS_STOPPED
; /* start in a stopped state */
2154 InitializeCriticalSection(&wwi
->access_crst
); /* initialize the critical section */
2155 EnterCriticalSection(&wwi
->access_crst
);
2157 /* open up jack ports for this device */
2158 if (!JACK_OpenWaveInDevice(&WInDev
[wDevID
], lpDesc
->lpFormat
->nChannels
))
2160 ERR("JACK_OpenWaveInDevice(%d) failed\n", wDevID
);
2161 LeaveCriticalSection(&wwi
->access_crst
);
2162 DeleteCriticalSection(&wwi
->access_crst
);
2163 return MMSYSERR_ERROR
; /* return unspecified error */
2166 dwFlags
&= ~WAVE_DIRECTSOUND
; /* direct sound not supported, ignore the flag */
2168 wwi
->wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
2170 memcpy(&wwi
->waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
2171 memcpy(&wwi
->format
, lpDesc
->lpFormat
, sizeof(PCMWAVEFORMAT
));
2173 LeaveCriticalSection(&wwi
->access_crst
);
2175 /* display the current wave format */
2176 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
2177 wwi
->format
.wBitsPerSample
, wwi
->format
.wf
.nAvgBytesPerSec
,
2178 wwi
->format
.wf
.nSamplesPerSec
, wwi
->format
.wf
.nChannels
,
2179 wwi
->format
.wf
.nBlockAlign
);
2181 /* make sure that we have the same sample rate in our audio stream */
2182 /* as we do in the jack server */
2183 if(wwi
->format
.wf
.nSamplesPerSec
!= wwi
->sample_rate
)
2185 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
2186 wwi
->sample_rate
, wwi
->format
.wf
.nSamplesPerSec
);
2189 JACK_CloseWaveInDevice(wwi
, FALSE
); /* close this device, don't force the client to close */
2191 JACK_CloseWaveInDevice(wwi
); /* close this device */
2193 DeleteCriticalSection(&wwi
->access_crst
);
2194 return WAVERR_BADFORMAT
;
2197 /* check for an invalid number of bits per sample */
2198 if (wwi
->format
.wBitsPerSample
== 0)
2200 WARN("Resetting zeroed wBitsPerSample\n");
2201 wwi
->format
.wBitsPerSample
= 8 *
2202 (wwi
->format
.wf
.nAvgBytesPerSec
/
2203 wwi
->format
.wf
.nSamplesPerSec
) /
2204 wwi
->format
.wf
.nChannels
;
2207 TRACE("notify client.\n");
2208 EnterCriticalSection(&wwi
->access_crst
);
2209 retval
= widNotifyClient(wwi
, WIM_OPEN
, 0L, 0L);
2210 LeaveCriticalSection(&wwi
->access_crst
);
2214 /**************************************************************************
2215 * widClose [internal]
2217 static DWORD
widClose(WORD wDevID
)
2219 DWORD ret
= MMSYSERR_NOERROR
;
2222 TRACE("(%u);\n", wDevID
);
2224 if (wDevID
>= MAX_WAVEINDRV
|| !WInDev
[wDevID
].client
)
2226 WARN("bad device ID !\n");
2227 return MMSYSERR_BADDEVICEID
;
2230 wwi
= &WInDev
[wDevID
];
2231 if (wwi
->lpQueuePtr
)
2233 WARN("buffers still playing !\n");
2234 ret
= WAVERR_STILLPLAYING
;
2237 /* sanity check: this should not happen since the device must have been reset before */
2238 if (wwi
->lpQueuePtr
) ERR("out of sync\n");
2240 wwi
->state
= WINE_WS_CLOSED
; /* mark the device as closed */
2243 JACK_CloseWaveInDevice(wwi
, FALSE
); /* close the jack device, DO NOT force the client to close */
2245 JACK_CloseWaveInDevice(wwi
); /* close the jack device */
2247 DeleteCriticalSection(&wwi
->access_crst
); /* delete the critical section so we can initialize it again from wodOpen() */
2249 ret
= widNotifyClient(wwi
, WIM_CLOSE
, 0L, 0L);
2255 /**************************************************************************
2256 * widAddBuffer [internal]
2258 static DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
2260 WINE_WAVEIN
* wwi
= &WInDev
[wDevID
];
2262 TRACE("(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
2264 if (wDevID
>= MAX_WAVEINDRV
|| WInDev
[wDevID
].state
== WINE_WS_CLOSED
) {
2265 WARN("can't do it !\n");
2266 return MMSYSERR_INVALHANDLE
;
2268 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
2269 TRACE("never been prepared !\n");
2270 return WAVERR_UNPREPARED
;
2272 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
2273 TRACE("header already in use !\n");
2274 return WAVERR_STILLPLAYING
;
2277 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
2278 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
2279 lpWaveHdr
->dwBytesRecorded
= 0;
2280 lpWaveHdr
->lpNext
= NULL
;
2282 EnterCriticalSection(&wwi
->access_crst
);
2283 /* insert buffer at end of queue */
2286 for (wh
= &(wwi
->lpQueuePtr
); *wh
; wh
= &((*wh
)->lpNext
));
2289 LeaveCriticalSection(&wwi
->access_crst
);
2291 return MMSYSERR_NOERROR
;
2294 /**************************************************************************
2295 * widPrepare [internal]
2297 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
2299 TRACE("(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
2301 if (wDevID
>= MAX_WAVEINDRV
) return MMSYSERR_INVALHANDLE
;
2303 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
2304 return WAVERR_STILLPLAYING
;
2306 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
2307 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
2308 lpWaveHdr
->dwBytesRecorded
= 0;
2309 lpWaveHdr
->lpNext
= NULL
;
2311 return MMSYSERR_NOERROR
;
2314 /**************************************************************************
2315 * widUnprepare [internal]
2317 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
2319 TRACE("(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
2320 if (wDevID
>= MAX_WAVEINDRV
) {
2321 WARN("bad device ID !\n");
2322 return MMSYSERR_INVALHANDLE
;
2325 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
2326 TRACE("Still playing...\n");
2327 return WAVERR_STILLPLAYING
;
2330 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
2331 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
2333 return MMSYSERR_NOERROR
;
2336 /**************************************************************************
2337 * widStart [internal]
2339 static DWORD
widStart(WORD wDevID
)
2341 TRACE("(%u);\n", wDevID
);
2342 if (wDevID
>= MAX_WAVEINDRV
|| WInDev
[wDevID
].state
== WINE_WS_CLOSED
) {
2343 WARN("can't start recording !\n");
2344 return MMSYSERR_INVALHANDLE
;
2347 WInDev
[wDevID
].state
= WINE_WS_PLAYING
;
2348 return MMSYSERR_NOERROR
;
2351 /**************************************************************************
2352 * widStop [internal]
2354 static DWORD
widStop(WORD wDevID
)
2356 WINE_WAVEIN
* wwi
= &WInDev
[wDevID
];
2358 TRACE("(%u);\n", wDevID
);
2359 if (wDevID
>= MAX_WAVEINDRV
|| WInDev
[wDevID
].state
== WINE_WS_CLOSED
) {
2360 WARN("can't stop !\n");
2361 return MMSYSERR_INVALHANDLE
;
2364 if (wwi
->state
!= WINE_WS_STOPPED
)
2367 /* do something here to stop recording ??? */
2369 /* return current buffer to app */
2370 lpWaveHdr
= wwi
->lpQueuePtr
;
2373 LPWAVEHDR lpNext
= lpWaveHdr
->lpNext
;
2374 TRACE("stop %p %p\n", lpWaveHdr
, lpWaveHdr
->lpNext
);
2375 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
2376 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
2377 widNotifyClient(wwi
, WIM_DATA
, (DWORD
)lpWaveHdr
, 0);
2378 wwi
->lpQueuePtr
= lpNext
;
2381 wwi
->state
= WINE_WS_STOPPED
;
2383 return MMSYSERR_NOERROR
;
2386 /**************************************************************************
2387 * widReset [internal]
2389 static DWORD
widReset(WORD wDevID
)
2391 WINE_WAVEIN
* wwi
= &WInDev
[wDevID
];
2394 TRACE("(%u);\n", wDevID
);
2395 if (wDevID
>= MAX_WAVEINDRV
|| WInDev
[wDevID
].state
== WINE_WS_CLOSED
) {
2396 WARN("can't reset !\n");
2397 return MMSYSERR_INVALHANDLE
;
2400 wwi
->state
= WINE_WS_STOPPED
;
2402 /* return all buffers to the app */
2403 for (lpWaveHdr
= wwi
->lpQueuePtr
; lpWaveHdr
; lpWaveHdr
= lpWaveHdr
->lpNext
) {
2404 TRACE("reset %p %p\n", lpWaveHdr
, lpWaveHdr
->lpNext
);
2405 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
2406 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
2408 widNotifyClient(wwi
, WIM_DATA
, (DWORD
)lpWaveHdr
, 0);
2410 wwi
->lpQueuePtr
= NULL
;
2412 return MMSYSERR_NOERROR
;
2415 /**************************************************************************
2416 * widGetNumDevs [internal]
2418 static DWORD
widGetNumDevs(void)
2420 return MAX_WAVEINDRV
;
2423 /**************************************************************************
2424 * widDevInterfaceSize [internal]
2426 static DWORD
widDevInterfaceSize(UINT wDevID
, LPDWORD dwParam1
)
2428 TRACE("(%u, %p)\n", wDevID
, dwParam1
);
2431 *dwParam1
= MultiByteToWideChar(CP_ACP
, 0, WInDev
[wDevID
].interface_name
, -1,
2432 NULL
, 0 ) * sizeof(WCHAR
);
2433 return MMSYSERR_NOERROR
;
2436 /**************************************************************************
2437 * widDevInterface [internal]
2439 static DWORD
widDevInterface(UINT wDevID
, PWCHAR dwParam1
, DWORD dwParam2
)
2441 if (dwParam2
>= MultiByteToWideChar(CP_ACP
, 0, WInDev
[wDevID
].interface_name
, -1,
2442 NULL
, 0 ) * sizeof(WCHAR
))
2444 MultiByteToWideChar(CP_ACP
, 0, WInDev
[wDevID
].interface_name
, -1,
2445 dwParam1
, dwParam2
/ sizeof(WCHAR
));
2446 return MMSYSERR_NOERROR
;
2448 return MMSYSERR_INVALPARAM
;
2451 /**************************************************************************
2452 * widMessage (WINEJACK.6)
2454 DWORD WINAPI
JACK_widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
2455 DWORD dwParam1
, DWORD dwParam2
)
2457 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
2458 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
2465 /* FIXME: Pretend this is supported */
2467 case WIDM_OPEN
: return widOpen (wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
2468 case WIDM_CLOSE
: return widClose (wDevID
);
2469 case WIDM_ADDBUFFER
: return widAddBuffer (wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
2470 case WIDM_PREPARE
: return widPrepare (wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
2471 case WIDM_UNPREPARE
: return widUnprepare (wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
2472 case WIDM_GETDEVCAPS
: return widGetDevCaps (wDevID
, (LPWAVEINCAPSW
)dwParam1
, dwParam2
);
2473 case WIDM_GETNUMDEVS
: return widGetNumDevs();
2474 case WIDM_RESET
: return widReset (wDevID
);
2475 case WIDM_START
: return widStart (wDevID
);
2476 case WIDM_STOP
: return widStop (wDevID
);
2477 case DRV_QUERYDEVICEINTERFACESIZE
: return widDevInterfaceSize (wDevID
, (LPDWORD
)dwParam1
);
2478 case DRV_QUERYDEVICEINTERFACE
: return widDevInterface (wDevID
, (PWCHAR
)dwParam1
, dwParam2
);
2480 FIXME("unknown message %d!\n", wMsg
);
2483 return MMSYSERR_NOTSUPPORTED
;
2486 #else /* !HAVE_JACK_JACK_H */
2488 /**************************************************************************
2489 * widMessage (WINEJACK.6)
2491 DWORD WINAPI
JACK_widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
2492 DWORD dwParam1
, DWORD dwParam2
)
2494 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
2495 return MMSYSERR_NOTENABLED
;
2498 /**************************************************************************
2499 * wodMessage (WINEJACK.7)
2501 DWORD WINAPI
JACK_wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
2502 DWORD dwParam1
, DWORD dwParam2
)
2504 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
2505 return MMSYSERR_NOTENABLED
;
2508 #endif /* HAVE_JACK_JACK_H */