Added wave-in support and fixed a few bugs in the wave-out code.
[wine/testsucceed.git] / dlls / winmm / winejack / audio.c
blob9988ac19f59215d063150bcec50886b96a50abae
1 /* -*- tab-width: 8; c-basic-offset: 2 -*- */
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
27 * TODO:
28 * implement audio stream resampling for any arbitrary frequenty
29 * right now we use the winmm layer to do resampling although it would
30 * be nice to have a full set of algorithms to choose from based on cpu
31 * time
33 * FIXME:
34 * pause in waveOut during loop is not handled correctly
37 #include "config.h"
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <string.h>
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46 #include <fcntl.h>
47 #include "windef.h"
48 #include "winbase.h"
49 #include "wingdi.h"
50 #include "winerror.h"
51 #include "wine/winuser16.h"
52 #include "mmddk.h"
53 #include "dsound.h"
54 #include "dsdriver.h"
55 #include "jack.h"
56 #include "wine/debug.h"
58 #ifdef HAVE_JACK_JACK_H
59 #include <jack/jack.h>
60 #endif
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);
86 #undef MAKE_FUNCPTR
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
124 typedef struct {
125 volatile int state; /* one of the WINE_WS_ manifest constants */
126 WAVEOPENDESC waveDesc;
127 WORD wFlags;
128 PCMWAVEFORMAT format;
129 WAVEOUTCAPSA caps;
130 WORD wDevID;
132 jack_port_t* out_port_l; /* ports for left and right channels */
133 jack_port_t* out_port_r;
134 jack_client_t* client;
135 long sample_rate; /* jack server sample rate */
137 #if JACK_CLOSE_HACK
138 BOOL in_use; /* TRUE if this device is in use */
139 #endif
141 char* sound_buffer;
142 unsigned long buffer_size;
144 DWORD volume_left;
145 DWORD volume_right;
147 LPWAVEHDR lpQueuePtr; /* start of queued WAVEHDRs (waiting to be notified) */
148 LPWAVEHDR lpPlayPtr; /* start of not yet fully played buffers */
149 DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
151 LPWAVEHDR lpLoopPtr; /* pointer of first buffer in loop, if any */
152 DWORD dwLoops; /* private copy of loop counter */
154 DWORD dwPlayedTotal; /* number of bytes actually played since opening */
155 DWORD dwWrittenTotal; /* number of bytes written to jack since opening */
157 DWORD bytesInJack; /* bytes that we wrote during the previous JACK_Callback() */
158 DWORD tickCountMS; /* time in MS of last JACK_Callback() */
160 /* synchronization stuff */
161 CRITICAL_SECTION access_crst;
162 } WINE_WAVEOUT;
164 typedef struct {
165 volatile int state;
166 WAVEOPENDESC waveDesc;
167 WORD wFlags;
168 PCMWAVEFORMAT format;
169 LPWAVEHDR lpQueuePtr;
170 DWORD dwTotalRecorded;
171 WAVEINCAPSA caps;
172 BOOL bTriggerSupport;
173 WORD wDevID;
175 jack_port_t* in_port_l; /* ports for left and right channels */
176 jack_port_t* in_port_r;
177 jack_client_t* client;
178 long sample_rate; /* jack server sample rate */
180 #if JACK_CLOSE_HACK
181 BOOL in_use; /* TRUE if this device is in use */
182 #endif
184 char* sound_buffer;
185 unsigned long buffer_size;
187 /* synchronization stuff */
188 CRITICAL_SECTION access_crst;
189 } WINE_WAVEIN;
191 static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV];
192 static WINE_WAVEIN WInDev [MAX_WAVEINDRV ];
194 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
195 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
196 static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid);
198 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo);
199 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force);
201 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo);
202 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels);
204 #if JACK_CLOSE_HACK
205 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client);
206 #else
207 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo);
208 #endif
210 #if JACK_CLOSE_HACK
211 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client);
212 #else
213 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi);
214 #endif
217 /*======================================================================*
218 * Low level WAVE implementation *
219 *======================================================================*/
221 #define SAMPLE_MAX_16BIT 32767.0f
223 /* Alsaplayer function that applies volume changes to a buffer */
224 /* (C) Andy Lo A Foe */
225 /* Length is in terms of 32 bit samples */
226 void volume_effect32(void *buffer, int length, int left, int right)
228 short *data = (short *)buffer;
229 int i, v;
231 if (right == -1) right = left;
233 for(i = 0; i < length; i++) {
234 v = (int) ((*(data) * left) / 100);
235 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
236 v = (int) ((*(data) * right) / 100);
237 *(data++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
241 /* move 16 bit mono/stereo to 16 bit stereo */
242 void sample_move_d16_d16(short *dst, short *src,
243 unsigned long nsamples, int nChannels)
245 while(nsamples--)
247 *dst = *src;
248 dst++;
250 if(nChannels == 2) src++;
252 *dst = *src;
253 dst++;
255 src++;
259 /* convert from 16 bit to floating point */
260 /* allow for copying of stereo data with alternating left/right */
261 /* channels to a buffer that will hold a single channel stream */
262 /* nsamples is in terms of 16bit samples */
263 /* src_skip is in terms of 16bit samples */
264 void sample_move_d16_s16 (sample_t *dst, short *src,
265 unsigned long nsamples, unsigned long src_skip)
267 /* ALERT: signed sign-extension portability !!! */
268 while (nsamples--)
270 *dst = (*src) / SAMPLE_MAX_16BIT;
271 dst++;
272 src += src_skip;
276 /* convert from floating point to 16 bit */
277 /* allow for copying of a buffer that will hold a single channel stream */
278 /* to stereo data with alternating left/right channels */
279 /* nsamples is in terms of float samples */
280 /* dst_skip is in terms of 16bit samples */
281 void sample_move_s16_d16 (short *dst, sample_t *src,
282 unsigned long nsamples, unsigned long dst_skip)
284 /* ALERT: signed sign-extension portability !!! */
285 while (nsamples--)
287 *dst = (*src) * SAMPLE_MAX_16BIT;
288 /* TRACE("src=(%.8f,%p) dst=(%d,%p)\n",*src,src,*dst,dst); */
289 dst += dst_skip;
290 src++;
295 /* fill dst buffer with nsamples worth of silence */
296 void sample_silence_dS (sample_t *dst, unsigned long nsamples)
298 /* ALERT: signed sign-extension portability !!! */
299 while (nsamples--)
301 *dst = 0;
302 dst++;
306 /******************************************************************
307 * JACK_callback_wwo
309 /* everytime the jack server wants something from us it calls this
310 function, so we either deliver it some sound to play or deliver it nothing
311 to play */
312 int JACK_callback_wwo (nframes_t nframes, void *arg)
314 sample_t* out_l;
315 sample_t* out_r;
316 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
318 TRACE("wDevID: %u, nframes %u state=%u\n", wwo->wDevID, nframes,wwo->state);
320 if(!wwo->client)
321 ERR("client is closed, this is weird...\n");
323 out_l = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_l, nframes);
324 out_r = (sample_t *) fp_jack_port_get_buffer(wwo->out_port_r, nframes);
326 if(wwo->state == WINE_WS_PLAYING)
328 DWORD jackFramesAvailable = nframes;
329 DWORD outputFramesAvailable;
330 DWORD numFramesToWrite;
332 long written = 0;
333 char* buffer;
335 #if JACK_CLOSE_HACK
336 if(wwo->in_use == FALSE)
338 /* output silence if nothing is being outputted */
339 sample_silence_dS(out_l, nframes);
340 sample_silence_dS(out_r, nframes);
342 return 0;
344 #endif
346 TRACE("wwo.state == WINE_WS_PLAYING\n");
348 /* see if our sound_buffer is large enough to hold the number of frames jack requested */
349 /* Note: sound_buffer is always filled with 16-bit stereo data, even for mono mode */
350 if(wwo->buffer_size < (nframes * sizeof(short) * 2))
352 ERR("for some reason JACK_BufSize() didn't allocate enough memory\n");
353 ERR("allocated %ld bytes, need %d bytes\n", wwo->buffer_size, (nframes * sizeof(short) * 2));
354 return 0;
357 /* while we have jackFramesAvailable and a wave header to be played */
358 while(jackFramesAvailable && wwo->lpPlayPtr)
360 /* find the amount of audio to be played at this time */
361 outputFramesAvailable = (wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset) / wwo->format.wf.nBlockAlign;
363 numFramesToWrite = min(jackFramesAvailable, outputFramesAvailable);
364 TRACE("dwBufferLength=(%ld) dwPartialOffset=(%ld)\n",wwo->lpPlayPtr->dwBufferLength,wwo->dwPartialOffset);
365 TRACE("outputFramesAvailable == %ld, jackFramesAvailable == %ld\n", outputFramesAvailable, jackFramesAvailable);
367 buffer = wwo->lpPlayPtr->lpData + wwo->dwPartialOffset;
369 /* convert from mono to stereo if necessary */
370 /* otherwise just memcpy to the output buffer */
372 if(wwo->format.wf.nChannels == 1)
374 sample_move_d16_d16((short*)wwo->sound_buffer + ((nframes - jackFramesAvailable) * sizeof(short)),
375 (short*)buffer, numFramesToWrite, wwo->format.wf.nChannels);
376 } else /* just copy the memory over */
378 memcpy(wwo->sound_buffer + ((nframes - jackFramesAvailable) * wwo->format.wf.nBlockAlign),
379 buffer, numFramesToWrite * wwo->format.wf.nBlockAlign);
382 /* advance to the next wave header if possible, or advance pointer */
383 /* inside of the current header if we haven't completed it */
384 if(numFramesToWrite == outputFramesAvailable)
386 wodHelper_PlayPtrNext(wwo); /* we wrote the whole waveheader, skip to the next one*/
388 else
390 wwo->dwPartialOffset+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* else advance by the bytes we took in to write */
393 written+=(numFramesToWrite * wwo->format.wf.nBlockAlign); /* add on what we wrote */
394 jackFramesAvailable-=numFramesToWrite; /* take away what was written in terms of output bytes */
397 wwo->tickCountMS = GetTickCount(); /* record the current time */
398 wwo->dwWrittenTotal+=written; /* update states on wave device */
399 wwo->dwPlayedTotal+=wwo->bytesInJack; /* we must have finished with the last bytes or we wouldn't be back inside of this callback again... */
400 wwo->bytesInJack = written; /* record the bytes inside of jack */
402 /* Now that we have finished filling the buffer either until it is full or until */
403 /* we have run out of application sound data to process, apply volume and output */
404 /* the audio to the jack server */
406 /* apply volume to the buffer */
407 volume_effect32(wwo->sound_buffer, (nframes - jackFramesAvailable), wwo->volume_left, wwo->volume_right);
409 /* convert from stereo 16 bit to single channel 32 bit float */
410 /* for each jack server channel */
411 /* NOTE: we skip over two sample since we want to only get either the left or right channel */
412 sample_move_d16_s16(out_l, (short*)wwo->sound_buffer, (nframes - jackFramesAvailable), 2);
413 sample_move_d16_s16(out_r, (short*)wwo->sound_buffer + 1, (nframes - jackFramesAvailable), 2);
415 /* see if we still have jackBytesLeft here, if we do that means that we
416 ran out of wave data to play and had a buffer underrun, fill in
417 the rest of the space with zero bytes */
418 if(jackFramesAvailable)
420 ERR("buffer underrun of %ld frames\n", jackFramesAvailable);
421 sample_silence_dS(out_l + (nframes - jackFramesAvailable), jackFramesAvailable);
422 sample_silence_dS(out_r + (nframes - jackFramesAvailable), jackFramesAvailable);
425 else if(wwo->state == WINE_WS_PAUSED ||
426 wwo->state == WINE_WS_STOPPED ||
427 wwo->state == WINE_WS_CLOSED)
429 /* output silence if nothing is being outputted */
430 sample_silence_dS(out_l, nframes);
431 sample_silence_dS(out_r, nframes);
434 /* notify the client of completed wave headers */
435 EnterCriticalSection(&wwo->access_crst);
436 wodHelper_NotifyCompletions(wwo, FALSE);
437 LeaveCriticalSection(&wwo->access_crst);
439 return 0;
442 /******************************************************************
443 * JACK_bufsize_wwo
445 * Called whenever the jack server changes the the max number
446 * of frames passed to JACK_callback
448 int JACK_bufsize_wwo (nframes_t nframes, void *arg)
450 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
451 DWORD buffer_required;
452 TRACE("wDevID=%d\n",wwo->wDevID);
453 TRACE("the maximum buffer size is now %u frames\n", nframes);
455 /* make sure the callback routine has adequate memory */
456 /* see if our buffer is large enough for the data we are writing */
457 /* ie. Buffer_size < (bytes we already wrote + bytes we are going to write in this loop) */
458 EnterCriticalSection(&wwo->access_crst);
460 /* wwo->sound_buffer is always filled with 16-bit stereo data, even for mono streams */
461 buffer_required = nframes * sizeof(short) * 2;
462 TRACE("wwo->buffer_size (%ld) buffer_required (%ld).\n", wwo->buffer_size,buffer_required);
463 if(wwo->buffer_size < buffer_required)
465 TRACE("expanding buffer from wwo->buffer_size == %ld, to %ld\n",
466 wwo->buffer_size, buffer_required);
467 TRACE("GetProcessHeap() == %p\n", GetProcessHeap());
468 wwo->buffer_size = buffer_required;
470 if (wwo->sound_buffer)
471 wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, wwo->buffer_size);
472 else
473 wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, wwo->buffer_size);
475 /* if we don't have a buffer then error out */
476 if(!wwo->sound_buffer)
478 ERR("error allocating sound_buffer memory\n");
479 LeaveCriticalSection(&wwo->access_crst);
480 return 0;
484 LeaveCriticalSection(&wwo->access_crst);
486 TRACE("ending\n");
488 return 0;
490 /******************************************************************
491 * JACK_bufsize_wwi
493 * Called whenever the jack server changes the the max number
494 * of frames passed to JACK_callback
496 int JACK_bufsize_wwi (nframes_t nframes, void *arg)
498 TRACE("the maximum buffer size is now %u frames\n", nframes);
499 return 0;
502 /******************************************************************
503 * JACK_srate
505 int JACK_srate (nframes_t nframes, void *arg)
507 TRACE("the sample rate is now %u/sec\n", nframes);
508 return 0;
512 /******************************************************************
513 * JACK_shutdown_wwo
515 /* if this is called then jack shut down... handle this appropriately */
516 void JACK_shutdown_wwo(void* arg)
518 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
520 wwo->client = 0; /* reset client */
522 TRACE("trying to reconnect after sleeping for a short while...\n");
524 /* lets see if we can't reestablish the connection */
525 Sleep(750); /* pause for a short period of time */
526 if(!JACK_OpenWaveOutDevice(wwo))
528 ERR("unable to reconnect with jack...\n");
532 /******************************************************************
533 * JACK_shutdown_wwi
535 /* if this is called then jack shut down... handle this appropriately */
536 void JACK_shutdown_wwi(void* arg)
538 WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
540 wwi->client = 0; /* reset client */
542 TRACE("trying to reconnect after sleeping for a short while...\n");
544 /* lets see if we can't reestablish the connection */
545 Sleep(750); /* pause for a short period of time */
546 if(!JACK_OpenWaveInDevice(wwi,wwi->format.wf.nChannels))
548 ERR("unable to reconnect with jack...\n");
553 /******************************************************************
554 * JACK_OpenWaveOutDevice
556 static int JACK_OpenWaveOutDevice(WINE_WAVEOUT* wwo)
558 const char** ports;
559 int i;
560 char client_name[64];
561 jack_port_t* out_port_l;
562 jack_port_t* out_port_r;
563 jack_client_t* client;
564 int failed = 0;
566 TRACE("creating jack client and setting up callbacks\n");
568 #if JACK_CLOSE_HACK
569 /* see if this device is already open */
570 if(wwo->client)
572 /* if this device is already in use then it is bad for us to be in here */
573 if(wwo->in_use)
574 return 0;
576 TRACE("using existing client\n");
577 wwo->in_use = TRUE;
578 return 1;
580 #endif
582 /* zero out the buffer pointer and the size of the buffer */
583 wwo->sound_buffer = 0;
584 wwo->buffer_size = 0;
586 /* try to become a client of the JACK server */
587 snprintf(client_name, sizeof(client_name), "wine_jack_out_%d", wwo->wDevID);
588 TRACE("client name '%s'\n", client_name);
589 if ((client = fp_jack_client_new (client_name)) == 0)
591 /* jack has problems with shutting down clients, so lets */
592 /* wait a short while and try once more before we give up */
593 Sleep(250);
594 if ((client = fp_jack_client_new (client_name)) == 0)
596 ERR("jack server not running?\n");
597 return 0;
601 /* tell the JACK server to call `JACK_callback_wwo()' whenever
602 there is work to be done. */
603 fp_jack_set_process_callback (client, JACK_callback_wwo, wwo);
605 /* tell the JACK server to call `JACK_bufsize_wwo()' whenever
606 the maximum number of frames that will be passed
607 to `JACK_Callback()' changes */
608 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwo, wwo);
610 /* tell the JACK server to call `srate()' whenever
611 the sample rate of the system changes. */
612 fp_jack_set_sample_rate_callback (client, JACK_srate, wwo);
614 /* tell the JACK server to call `jack_shutdown()' if
615 it ever shuts down, either entirely, or if it
616 just decides to stop calling us. */
617 fp_jack_on_shutdown (client, JACK_shutdown_wwo, wwo);
619 /* display the current sample rate. once the client is activated
620 (see below), you should rely on your own sample rate
621 callback (see above) for this value. */
622 wwo->sample_rate = fp_jack_get_sample_rate(client);
623 TRACE("engine sample rate: %lu\n", wwo->sample_rate);
625 /* create the left and right channel output ports */
626 /* jack's ports are all mono so for stereo you need two */
627 out_port_l = fp_jack_port_register (client, "out_l",
628 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
630 out_port_r = fp_jack_port_register (client, "out_r",
631 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
633 TRACE("Created ports. (%p) (%p)\n",out_port_l, out_port_r);
635 /* save away important values to the WINE_WAVEOUT struct */
636 wwo->client = client;
637 wwo->out_port_l = out_port_l;
638 wwo->out_port_r = out_port_r;
640 #if JACK_CLOSE_HACK
641 wwo->in_use = TRUE; /* mark this device as in use since it now is ;-) */
642 #endif
644 /* set initial buffer size */
645 JACK_bufsize_wwo (fp_jack_get_buffer_size(client),wwo);
647 /* tell the JACK server that we are ready to roll */
648 if (fp_jack_activate (client))
650 ERR( "cannot activate client\n");
651 return 0;
654 TRACE("jack activate.\n");
655 /* figure out what the ports that we want to output on are */
656 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
657 /* this way works if names are changed */
658 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
660 /* display a trace of the output ports we found */
661 for(i = 0; ports[i]; i++)
663 TRACE("ports[%d] = '%s'\n", i, ports[i]);
666 if(!ports)
668 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsInput'\n");
671 /* connect the ports. Note: you can't do this before
672 the client is activated (this may change in the future).
674 /* we want to connect to two ports so we have stereo output ;-) */
676 if(fp_jack_connect(client, fp_jack_port_name(out_port_l), ports[0]))
678 ERR ("cannot connect to output port %d('%s')\n", 0, ports[0]);
679 failed = 1;
682 if(fp_jack_connect(client, fp_jack_port_name(out_port_r), ports[1]))
684 ERR ("cannot connect to output port %d('%s')\n", 1, ports[1]);
685 failed = 1;
688 free(ports); /* free the returned array of ports */
690 /* if something failed we need to shut the client down and return 0 */
691 if(failed)
693 #if JACK_CLOSE_HACK
694 JACK_CloseWaveOutDevice(wwo, TRUE);
695 #else
696 JACK_CloseWaveOutDevice(wwo);
697 #endif
698 return 0;
701 return 1; /* return success */
704 /******************************************************************
705 * JACK_CloseWaveOutDevice
707 * Close the connection to the server cleanly.
708 * If close_client is TRUE we close the client for this device instead of
709 * just marking the device as in_use(JACK_CLOSE_HACK only)
711 #if JACK_CLOSE_HACK
712 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client)
713 #else
714 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
715 #endif
717 #if JACK_CLOSE_HACK
718 TRACE("wDevID: %d, close_client (wwo): %d\n", wwo->wDevID, close_client);
719 #else
720 TRACE("wDevID: %d\n", wwo->wDevID);
721 #endif
723 #if JACK_CLOSE_HACK
724 if(close_client)
726 #endif
727 fp_jack_deactivate(wwo->client); /* supposed to help the jack_client_close() to succeed */
728 fp_jack_client_close (wwo->client);
730 EnterCriticalSection(&wwo->access_crst);
731 wwo->client = 0; /* reset client */
732 HeapFree(GetProcessHeap(), 0, wwo->sound_buffer); /* free buffer memory */
733 wwo->sound_buffer = 0;
734 wwo->buffer_size = 0; /* zero out size of the buffer */
735 LeaveCriticalSection(&wwo->access_crst);
736 #if JACK_CLOSE_HACK
737 } else
739 EnterCriticalSection(&wwo->access_crst);
740 TRACE("setting in_use to FALSE\n");
741 wwo->in_use = FALSE;
742 LeaveCriticalSection(&wwo->access_crst);
744 #endif
747 /******************************************************************
748 * JACK_CloseWaveInDevice
750 * Close the connection to the server cleanly.
751 * If close_client is TRUE we close the client for this device instead of
752 * just marking the device as in_use(JACK_CLOSE_HACK only)
754 #if JACK_CLOSE_HACK
755 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client)
756 #else
757 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi)
758 #endif
760 #if JACK_CLOSE_HACK
761 TRACE("wDevID: %d, close_client (wwi): %d\n", wwi->wDevID, close_client);
762 #else
763 TRACE("wDevID: %d\n", wwi->wDevID);
764 #endif
766 #if JACK_CLOSE_HACK
767 if(close_client)
769 #endif
770 fp_jack_deactivate(wwi->client); /* supposed to help the jack_client_close() to succeed */
771 fp_jack_client_close (wwi->client);
773 EnterCriticalSection(&wwi->access_crst);
774 wwi->client = 0; /* reset client */
775 HeapFree(GetProcessHeap(), 0, wwi->sound_buffer); /* free buffer memory */
776 wwi->sound_buffer = 0;
777 wwi->buffer_size = 0; /* zero out size of the buffer */
778 LeaveCriticalSection(&wwi->access_crst);
779 #if JACK_CLOSE_HACK
780 } else
782 EnterCriticalSection(&wwi->access_crst);
783 TRACE("setting in_use to FALSE\n");
784 wwi->in_use = FALSE;
785 LeaveCriticalSection(&wwi->access_crst);
787 #endif
790 /******************************************************************
791 * JACK_WaveRelease
795 LONG JACK_WaveRelease(void)
797 int iDevice;
799 TRACE("closing all open waveout devices\n");
801 /* close all open output devices */
802 for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
804 TRACE("iDevice == %d\n", iDevice);
805 if(WOutDev[iDevice].client)
807 #if JACK_CLOSE_HACK
808 JACK_CloseWaveOutDevice(&WOutDev[iDevice], TRUE); /* close the device, FORCE the client to close */
809 #else
810 JACK_CloseWaveOutDevice(&WOutDev[iDevice]); /* close the device, FORCE the client to close */
811 #endif
812 DeleteCriticalSection(&(WOutDev[iDevice].access_crst)); /* delete the critical section */
816 TRACE("closing all open wavein devices\n");
818 /* close all open input devices */
819 for(iDevice = 0; iDevice < MAX_WAVEINDRV; iDevice++)
821 TRACE("iDevice == %d\n", iDevice);
822 if(WInDev[iDevice].client)
824 #if JACK_CLOSE_HACK
825 JACK_CloseWaveInDevice(&WInDev[iDevice], TRUE); /* close the device, FORCE the client to close */
826 #else
827 JACK_CloseWaveInDevice(&WInDev[iDevice]); /* close the device, FORCE the client to close */
828 #endif
829 DeleteCriticalSection(&(WInDev[iDevice].access_crst)); /* delete the critical section */
833 TRACE("returning 1\n");
835 return 1;
838 /******************************************************************
839 * JACK_WaveInit
841 * Initialize internal structures from JACK server info
843 LONG JACK_WaveInit(void)
845 int i;
847 TRACE("called\n");
849 /* setup function pointers */
850 #define LOAD_FUNCPTR(f) if((fp_##f = wine_dlsym(jackhandle, #f, NULL, 0)) == NULL) goto sym_not_found;
851 LOAD_FUNCPTR(jack_activate);
852 LOAD_FUNCPTR(jack_connect);
853 LOAD_FUNCPTR(jack_client_new);
854 LOAD_FUNCPTR(jack_client_close);
855 LOAD_FUNCPTR(jack_deactivate);
856 LOAD_FUNCPTR(jack_set_process_callback);
857 LOAD_FUNCPTR(jack_set_buffer_size_callback);
858 LOAD_FUNCPTR(jack_set_sample_rate_callback);
859 LOAD_FUNCPTR(jack_on_shutdown);
860 LOAD_FUNCPTR(jack_get_sample_rate);
861 LOAD_FUNCPTR(jack_port_register);
862 LOAD_FUNCPTR(jack_port_get_buffer);
863 LOAD_FUNCPTR(jack_get_ports);
864 LOAD_FUNCPTR(jack_port_name);
865 LOAD_FUNCPTR(jack_get_buffer_size);
866 #undef LOAD_FUNCPTR
868 /* start with output device */
870 for (i = 0; i < MAX_WAVEOUTDRV; ++i)
872 WOutDev[i].client = 0; /* initialize the client to 0 */
874 #if JACK_CLOSE_HACK
875 WOutDev[i].in_use = FALSE;
876 WInDev[i].in_use = FALSE;
877 #endif
879 memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps));
881 /* FIXME: some programs compare this string against the content of the registry
882 * for MM drivers. The names have to match in order for the program to work
883 * (e.g. MS win9x mplayer.exe)
885 #ifdef EMULATE_SB16
886 WOutDev[i].caps.wMid = 0x0002;
887 WOutDev[i].caps.wPid = 0x0104;
888 strcpy(WOutDev[i].caps.szPname, "SB16 Wave Out");
889 #else
890 WOutDev[i].caps.wMid = 0x00FF; /* Manufac ID */
891 WOutDev[i].caps.wPid = 0x0001; /* Product ID */
892 /* strcpy(WOutDev[i].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/
893 strcpy(WOutDev[i].caps.szPname, "CS4236/37/38");
894 #endif
895 WOutDev[i].caps.vDriverVersion = 0x0100;
896 WOutDev[i].caps.dwFormats = 0x00000000;
897 WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
899 WOutDev[i].caps.wChannels = 2;
900 WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;
902 /* NOTE: we don't support any 8 bit modes so note that */
903 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
904 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
905 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
906 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
907 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
908 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
909 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
910 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
911 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
912 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
913 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
914 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
917 /* then do input device */
918 for (i = 0; i < MAX_WAVEINDRV; ++i)
920 /* TODO: we should initialize read stuff here */
921 memset(&WInDev[0].caps, 0, sizeof(WInDev[0].caps));
923 /* FIXME: some programs compare this string against the content of the registry
924 * for MM drivers. The names have to match in order for the program to work
925 * (e.g. MS win9x mplayer.exe)
927 #ifdef EMULATE_SB16
928 WInDev[i].caps.wMid = 0x0002;
929 WInDev[i].caps.wPid = 0x0104;
930 strcpy(WInDev[i].caps.szPname, "SB16 Wave In");
931 #else
932 WInDev[i].caps.wMid = 0x00FF;
933 WInDev[i].caps.wPid = 0x0001;
934 strcpy(WInDev[i].caps.szPname,"CS4236/37/38");
935 #endif
936 WInDev[i].caps.vDriverVersion = 0x0100;
938 WInDev[i].caps.wChannels = 0x2;
939 /* NOTE: we don't support any 8 bit modes so note that */
940 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
941 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
942 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
943 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
944 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
945 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
946 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
947 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
948 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
949 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
950 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
951 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
952 WInDev[i].caps.wReserved1 = 0;
955 return 1; /* return success */
957 /* error path for function pointer loading errors */
958 sym_not_found:
959 WINE_MESSAGE(
960 "Wine cannot find certain functions that it needs inside the jack"
961 "library. To enable Wine to use the jack audio server please "
962 "install libjack\n");
963 wine_dlclose(jackhandle, NULL, 0);
964 jackhandle = NULL;
965 return FALSE;
968 /*======================================================================*
969 * Low level WAVE OUT implementation *
970 *======================================================================*/
972 /**************************************************************************
973 * wodNotifyClient [internal]
975 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
977 TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
979 switch (wMsg) {
980 case WOM_OPEN:
981 case WOM_CLOSE:
982 case WOM_DONE:
983 if (wwo->wFlags != DCB_NULL &&
984 !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags,
985 (HDRVR)wwo->waveDesc.hWave, wMsg, wwo->waveDesc.dwInstance,
986 dwParam1, dwParam2))
988 WARN("can't notify client !\n");
989 return MMSYSERR_ERROR;
991 break;
992 default:
993 FIXME("Unknown callback message %u\n", wMsg);
994 return MMSYSERR_INVALPARAM;
996 return MMSYSERR_NOERROR;
999 /**************************************************************************
1000 * wodHelper_BeginWaveHdr [internal]
1002 * Makes the specified lpWaveHdr the currently playing wave header.
1003 * If the specified wave header is a begin loop and we're not already in
1004 * a loop, setup the loop.
1006 static void wodHelper_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
1008 EnterCriticalSection(&wwo->access_crst);
1010 wwo->lpPlayPtr = lpWaveHdr;
1012 if (!lpWaveHdr)
1014 LeaveCriticalSection(&wwo->access_crst);
1015 return;
1018 if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)
1020 if (wwo->lpLoopPtr)
1022 WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1023 TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1024 } else
1026 TRACE("Starting loop (%ldx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
1027 wwo->lpLoopPtr = lpWaveHdr;
1028 /* Windows does not touch WAVEHDR.dwLoops,
1029 * so we need to make an internal copy */
1030 wwo->dwLoops = lpWaveHdr->dwLoops;
1033 wwo->dwPartialOffset = 0;
1035 LeaveCriticalSection(&wwo->access_crst);
1039 /**************************************************************************
1040 * wodHelper_PlayPtrNext [internal]
1042 * Advance the play pointer to the next waveheader, looping if required.
1044 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
1046 LPWAVEHDR lpWaveHdr;
1048 EnterCriticalSection(&wwo->access_crst);
1050 lpWaveHdr = wwo->lpPlayPtr;
1052 wwo->dwPartialOffset = 0;
1053 if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr)
1055 /* We're at the end of a loop, loop if required */
1056 if (--wwo->dwLoops > 0)
1058 wwo->lpPlayPtr = wwo->lpLoopPtr;
1059 } else
1061 /* Handle overlapping loops correctly */
1062 if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
1063 FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
1064 /* shall we consider the END flag for the closing loop or for
1065 * the opening one or for both ???
1066 * code assumes for closing loop only
1068 } else
1070 lpWaveHdr = lpWaveHdr->lpNext;
1072 wwo->lpLoopPtr = NULL;
1073 wodHelper_BeginWaveHdr(wwo, lpWaveHdr);
1075 } else
1077 /* We're not in a loop. Advance to the next wave header */
1078 TRACE("not inside of a loop, advancing to next wave header\n");
1079 wodHelper_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
1082 LeaveCriticalSection(&wwo->access_crst);
1084 return lpWaveHdr;
1087 /* if force is TRUE then notify the client that all the headers were completed */
1088 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
1090 LPWAVEHDR lpWaveHdr;
1091 DWORD retval;
1093 TRACE("called\n");
1095 EnterCriticalSection(&wwo->access_crst);
1097 /* Start from lpQueuePtr and keep notifying until:
1098 * - we hit an unwritten wavehdr
1099 * - we hit the beginning of a running loop
1100 * - we hit a wavehdr which hasn't finished playing
1102 while ((lpWaveHdr = wwo->lpQueuePtr) &&
1103 (force ||
1104 (lpWaveHdr != wwo->lpPlayPtr &&
1105 lpWaveHdr != wwo->lpLoopPtr)))
1107 wwo->lpQueuePtr = lpWaveHdr->lpNext;
1109 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1110 lpWaveHdr->dwFlags |= WHDR_DONE;
1111 TRACE("notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) dwFlags=(%ld)\n",
1112 lpWaveHdr, wwo->lpPlayPtr, lpWaveHdr->dwFlags);
1114 wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
1116 TRACE("Not notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) lpLoopPtr=(%p)\n",
1117 lpWaveHdr, wwo->lpPlayPtr, wwo->lpLoopPtr);
1118 retval = (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr !=
1119 wwo->lpLoopPtr) ? 0 : INFINITE;
1121 LeaveCriticalSection(&wwo->access_crst);
1123 return retval;
1126 /**************************************************************************
1127 * wodHelper_Reset [internal]
1129 * Resets current output stream.
1131 static void wodHelper_Reset(WINE_WAVEOUT* wwo, BOOL reset)
1133 EnterCriticalSection(&wwo->access_crst);
1135 /* updates current notify list */
1136 wodHelper_NotifyCompletions(wwo, FALSE);
1138 if (reset)
1140 /* remove all wave headers and notify client that all headers were completed */
1141 wodHelper_NotifyCompletions(wwo, TRUE);
1143 wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
1144 wwo->state = WINE_WS_STOPPED;
1145 wwo->dwPlayedTotal = wwo->dwWrittenTotal = wwo->bytesInJack = 0;
1147 wwo->dwPartialOffset = 0; /* Clear partial wavehdr */
1148 } else
1150 if (wwo->lpLoopPtr)
1152 /* complicated case, not handled yet (could imply modifying the loop counter) */
1153 FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
1154 wwo->lpPlayPtr = wwo->lpLoopPtr;
1155 wwo->dwPartialOffset = 0;
1156 wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
1157 } else
1159 LPWAVEHDR ptr;
1160 DWORD sz = wwo->dwPartialOffset;
1162 /* reset all the data as if we had written only up to lpPlayedTotal bytes */
1163 /* compute the max size playable from lpQueuePtr */
1164 for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext)
1166 sz += ptr->dwBufferLength;
1169 /* because the reset lpPlayPtr will be lpQueuePtr */
1170 if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("doh\n");
1171 wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal);
1172 wwo->dwWrittenTotal = wwo->dwPlayedTotal;
1173 wwo->lpPlayPtr = wwo->lpQueuePtr;
1176 wwo->state = WINE_WS_PAUSED;
1179 LeaveCriticalSection(&wwo->access_crst);
1182 /**************************************************************************
1183 * wodGetDevCaps [internal]
1185 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSA lpCaps, DWORD dwSize)
1187 TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1189 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1191 if (wDevID >= MAX_WAVEOUTDRV)
1193 TRACE("MAX_WAVOUTDRV reached !\n");
1194 return MMSYSERR_BADDEVICEID;
1197 TRACE("dwSupport=(0x%lx), dwFormats=(0x%lx)\n", WOutDev[wDevID].caps.dwSupport, WOutDev[wDevID].caps.dwFormats);
1198 memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1199 return MMSYSERR_NOERROR;
1202 /**************************************************************************
1203 * wodOpen [internal]
1205 * NOTE: doesn't it seem like there is a race condition if you try to open
1206 * the same device twice?
1208 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1210 WINE_WAVEOUT* wwo;
1211 DWORD retval;
1213 TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1214 if (lpDesc == NULL)
1216 WARN("Invalid Parameter !\n");
1217 return MMSYSERR_INVALPARAM;
1219 if (wDevID >= MAX_WAVEOUTDRV) {
1220 TRACE("MAX_WAVOUTDRV reached !\n");
1221 return MMSYSERR_BADDEVICEID;
1224 #if JACK_CLOSE_HACK
1225 if(WOutDev[wDevID].client && WOutDev[wDevID].in_use)
1226 #else
1227 if(WOutDev[wDevID].client)
1228 #endif
1230 TRACE("device %d already allocated\n", wDevID);
1231 return MMSYSERR_ALLOCATED;
1234 /* make sure we aren't being opened in 8 bit mode */
1235 if(lpDesc->lpFormat->wBitsPerSample == 8)
1237 TRACE("8bits per sample unsupported, returning WAVERR_BADFORMAT\n");
1238 return WAVERR_BADFORMAT;
1241 /* only PCM format is supported so far... */
1242 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1243 lpDesc->lpFormat->nChannels == 0 ||
1244 lpDesc->lpFormat->nSamplesPerSec == 0)
1246 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1247 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1248 lpDesc->lpFormat->nSamplesPerSec);
1249 return WAVERR_BADFORMAT;
1252 if (dwFlags & WAVE_FORMAT_QUERY)
1254 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1255 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1256 lpDesc->lpFormat->nSamplesPerSec);
1257 return MMSYSERR_NOERROR;
1260 wwo = &WOutDev[wDevID];
1261 wwo->wDevID = wDevID;
1263 /* Set things up before we call JACK_OpenWaveOutDevice because */
1264 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
1265 /* even returns and we want to be initialized before then */
1266 wwo->state = WINE_WS_STOPPED; /* start in a stopped state */
1267 wwo->dwPlayedTotal = 0; /* zero out these totals */
1268 wwo->dwWrittenTotal = 0;
1269 wwo->bytesInJack = 0;
1270 wwo->tickCountMS = 0;
1272 /* Initialize volume to full level */
1273 wwo->volume_left = 100;
1274 wwo->volume_right = 100;
1276 InitializeCriticalSection(&wwo->access_crst); /* initialize the critical section */
1277 EnterCriticalSection(&wwo->access_crst);
1279 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
1281 wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1283 memcpy(&wwo->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1284 memcpy(&wwo->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1286 /* open up jack ports for this device */
1287 if (!JACK_OpenWaveOutDevice(&WOutDev[wDevID]))
1289 ERR("JACK_OpenWaveOutDevice(%d) failed\n", wDevID);
1290 LeaveCriticalSection(&wwo->access_crst);
1291 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1292 return MMSYSERR_ERROR; /* return unspecified error */
1295 LeaveCriticalSection(&wwo->access_crst);
1297 /* display the current wave format */
1298 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
1299 wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
1300 wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1301 wwo->format.wf.nBlockAlign);
1303 /* make sure that we have the same sample rate in our audio stream */
1304 /* as we do in the jack server */
1305 if(wwo->format.wf.nSamplesPerSec != wwo->sample_rate)
1307 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
1308 wwo->sample_rate, wwo->format.wf.nSamplesPerSec);
1310 #if JACK_CLOSE_HACK
1311 JACK_CloseWaveOutDevice(wwo, FALSE); /* close this device, don't force the client to close */
1312 #else
1313 JACK_CloseWaveOutDevice(wwo); /* close this device */
1314 #endif
1315 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1316 return WAVERR_BADFORMAT;
1319 /* check for an invalid number of bits per sample */
1320 if (wwo->format.wBitsPerSample == 0)
1322 WARN("Resetting zeroed wBitsPerSample to 16\n");
1323 wwo->format.wBitsPerSample = 16 *
1324 (wwo->format.wf.nAvgBytesPerSec /
1325 wwo->format.wf.nSamplesPerSec) /
1326 wwo->format.wf.nChannels;
1329 EnterCriticalSection(&wwo->access_crst);
1330 retval = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
1331 LeaveCriticalSection(&wwo->access_crst);
1333 return retval;
1336 /**************************************************************************
1337 * wodClose [internal]
1339 static DWORD wodClose(WORD wDevID)
1341 DWORD ret = MMSYSERR_NOERROR;
1342 WINE_WAVEOUT* wwo;
1344 TRACE("(%u);\n", wDevID);
1346 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1348 WARN("bad device ID !\n");
1349 return MMSYSERR_BADDEVICEID;
1352 wwo = &WOutDev[wDevID];
1353 if (wwo->lpQueuePtr)
1355 WARN("buffers still playing !\n");
1356 ret = WAVERR_STILLPLAYING;
1357 } else
1359 /* sanity check: this should not happen since the device must have been reset before */
1360 if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
1362 wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
1364 #if JACK_CLOSE_HACK
1365 JACK_CloseWaveOutDevice(wwo, FALSE); /* close the jack device, DO NOT force the client to close */
1366 #else
1367 JACK_CloseWaveOutDevice(wwo); /* close the jack device */
1368 #endif
1369 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1371 ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
1374 return ret;
1378 /**************************************************************************
1379 * wodWrite [internal]
1382 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1384 LPWAVEHDR*wh;
1385 WINE_WAVEOUT *wwo;
1387 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1389 /* first, do the sanity checks... */
1390 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1392 WARN("bad dev ID !\n");
1393 return MMSYSERR_BADDEVICEID;
1396 wwo = &WOutDev[wDevID];
1398 if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1400 TRACE("unprepared\n");
1401 return WAVERR_UNPREPARED;
1404 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1406 TRACE("still playing\n");
1407 return WAVERR_STILLPLAYING;
1410 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1411 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1412 lpWaveHdr->lpNext = 0;
1414 EnterCriticalSection(&wwo->access_crst);
1416 /* insert buffer at the end of queue */
1417 for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
1418 *wh = lpWaveHdr;
1420 if (!wwo->lpPlayPtr)
1421 wodHelper_BeginWaveHdr(wwo,lpWaveHdr);
1422 if (wwo->state == WINE_WS_STOPPED)
1423 wwo->state = WINE_WS_PLAYING;
1424 LeaveCriticalSection(&wwo->access_crst);
1426 return MMSYSERR_NOERROR;
1429 /**************************************************************************
1430 * wodPrepare [internal]
1432 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1434 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1436 if (wDevID >= MAX_WAVEOUTDRV)
1438 WARN("bad device ID !\n");
1439 return MMSYSERR_BADDEVICEID;
1442 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1443 return WAVERR_STILLPLAYING;
1445 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1446 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1447 return MMSYSERR_NOERROR;
1450 /**************************************************************************
1451 * wodUnprepare [internal]
1453 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1455 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1457 if (wDevID >= MAX_WAVEOUTDRV)
1459 WARN("bad device ID !\n");
1460 return MMSYSERR_BADDEVICEID;
1463 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1464 return WAVERR_STILLPLAYING;
1466 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1467 lpWaveHdr->dwFlags |= WHDR_DONE;
1469 return MMSYSERR_NOERROR;
1472 /**************************************************************************
1473 * wodPause [internal]
1475 static DWORD wodPause(WORD wDevID)
1477 TRACE("(%u);!\n", wDevID);
1479 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1481 WARN("bad device ID !\n");
1482 return MMSYSERR_BADDEVICEID;
1485 TRACE("[3-PAUSING]\n");
1487 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1488 wodHelper_Reset(&WOutDev[wDevID], FALSE);
1489 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1491 return MMSYSERR_NOERROR;
1494 /**************************************************************************
1495 * wodRestart [internal]
1497 static DWORD wodRestart(WORD wDevID)
1499 TRACE("(%u);\n", wDevID);
1501 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1503 WARN("bad device ID !\n");
1504 return MMSYSERR_BADDEVICEID;
1507 if (WOutDev[wDevID].state == WINE_WS_PAUSED)
1509 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1510 WOutDev[wDevID].state = WINE_WS_PLAYING;
1511 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1514 return MMSYSERR_NOERROR;
1517 /**************************************************************************
1518 * wodReset [internal]
1520 static DWORD wodReset(WORD wDevID)
1522 TRACE("(%u);\n", wDevID);
1524 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1526 WARN("bad device ID !\n");
1527 return MMSYSERR_BADDEVICEID;
1530 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1531 wodHelper_Reset(&WOutDev[wDevID], TRUE);
1532 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1534 return MMSYSERR_NOERROR;
1537 /**************************************************************************
1538 * wodGetPosition [internal]
1540 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1542 int time;
1543 DWORD val;
1544 WINE_WAVEOUT* wwo;
1545 DWORD elapsedMS;
1547 TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1549 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1551 WARN("bad device ID !\n");
1552 return MMSYSERR_BADDEVICEID;
1555 /* if null pointer to time structure return error */
1556 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1558 wwo = &WOutDev[wDevID];
1560 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1561 val = wwo->dwPlayedTotal;
1562 elapsedMS = GetTickCount() - wwo->tickCountMS;
1563 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1565 /* account for the bytes played since the last JACK_Callback() */
1566 val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
1568 TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
1569 lpTime->wType, wwo->format.wBitsPerSample,
1570 wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1571 wwo->format.wf.nAvgBytesPerSec);
1572 TRACE("dwPlayedTotal=%lu\n", val);
1574 switch (lpTime->wType) {
1575 case TIME_BYTES:
1576 lpTime->u.cb = val;
1577 TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
1578 break;
1579 case TIME_SAMPLES:
1580 lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
1581 TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
1582 break;
1583 case TIME_SMPTE:
1584 time = val / (wwo->format.wf.nAvgBytesPerSec / 1000);
1585 lpTime->u.smpte.hour = time / 108000;
1586 time -= lpTime->u.smpte.hour * 108000;
1587 lpTime->u.smpte.min = time / 1800;
1588 time -= lpTime->u.smpte.min * 1800;
1589 lpTime->u.smpte.sec = time / 30;
1590 time -= lpTime->u.smpte.sec * 30;
1591 lpTime->u.smpte.frame = time;
1592 lpTime->u.smpte.fps = 30;
1593 TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1594 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1595 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1596 break;
1597 default:
1598 FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
1599 lpTime->wType = TIME_MS;
1600 case TIME_MS:
1601 lpTime->u.ms = val / (wwo->format.wf.nAvgBytesPerSec / 1000);
1602 TRACE("TIME_MS=%lu\n", lpTime->u.ms);
1603 break;
1605 return MMSYSERR_NOERROR;
1608 /**************************************************************************
1609 * wodBreakLoop [internal]
1611 static DWORD wodBreakLoop(WORD wDevID)
1613 TRACE("(%u);\n", wDevID);
1615 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1617 WARN("bad device ID !\n");
1618 return MMSYSERR_BADDEVICEID;
1621 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1623 if (WOutDev[wDevID].state == WINE_WS_PLAYING && WOutDev[wDevID].lpLoopPtr != NULL)
1625 /* ensure exit at end of current loop */
1626 WOutDev[wDevID].dwLoops = 1;
1629 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1631 return MMSYSERR_NOERROR;
1634 /**************************************************************************
1635 * wodGetVolume [internal]
1637 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1639 DWORD left, right;
1641 left = WOutDev[wDevID].volume_left;
1642 right = WOutDev[wDevID].volume_right;
1644 TRACE("(%u, %p);\n", wDevID, lpdwVol);
1646 *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
1647 16);
1649 return MMSYSERR_NOERROR;
1652 /**************************************************************************
1653 * wodSetVolume [internal]
1655 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1657 DWORD left, right;
1659 left = (LOWORD(dwParam) * 100) / 0xFFFFl;
1660 right = (HIWORD(dwParam) * 100) / 0xFFFFl;
1662 TRACE("(%u, %08lX);\n", wDevID, dwParam);
1664 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1666 WOutDev[wDevID].volume_left = left;
1667 WOutDev[wDevID].volume_right = right;
1669 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1671 return MMSYSERR_NOERROR;
1674 /**************************************************************************
1675 * wodGetNumDevs [internal]
1677 static DWORD wodGetNumDevs(void)
1679 return MAX_WAVEOUTDRV;
1682 /**************************************************************************
1683 * wodMessage (WINEJACK.7)
1685 DWORD WINAPI JACK_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
1686 DWORD dwParam1, DWORD dwParam2)
1688 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
1689 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1691 switch (wMsg) {
1692 case DRVM_INIT:
1693 TRACE("DRVM_INIT\n");
1694 return JACK_WaveInit();
1695 case DRVM_EXIT:
1696 TRACE("DRVM_EXIT\n");
1697 return JACK_WaveRelease();
1698 case DRVM_ENABLE:
1699 /* FIXME: Pretend this is supported */
1700 TRACE("DRVM_ENABLE\n");
1701 return 0;
1702 case DRVM_DISABLE:
1703 /* FIXME: Pretend this is supported */
1704 TRACE("DRVM_DISABLE\n");
1705 return 0;
1706 case WODM_OPEN: return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1707 case WODM_CLOSE: return wodClose(wDevID);
1708 case WODM_WRITE: return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1709 case WODM_PAUSE: return wodPause(wDevID);
1710 case WODM_GETPOS: return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1711 case WODM_BREAKLOOP: return wodBreakLoop(wDevID);
1712 case WODM_PREPARE: return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1713 case WODM_UNPREPARE: return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1714 case WODM_GETDEVCAPS: return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSA)dwParam1, dwParam2);
1715 case WODM_GETNUMDEVS: return wodGetNumDevs();
1716 case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED;
1717 case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED;
1718 case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1719 case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1720 case WODM_GETVOLUME: return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1721 case WODM_SETVOLUME: return wodSetVolume(wDevID, dwParam1);
1722 case WODM_RESTART: return wodRestart(wDevID);
1723 case WODM_RESET: return wodReset(wDevID);
1725 case DRV_QUERYDSOUNDIFACE: return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1);
1726 case DRV_QUERYDSOUNDDESC: return wodDsDesc(wDevID, (PDSDRIVERDESC)dwParam1);
1727 case DRV_QUERYDSOUNDGUID: return wodDsGuid(wDevID, (LPGUID)dwParam1);
1728 default:
1729 FIXME("unknown message %d!\n", wMsg);
1731 return MMSYSERR_NOTSUPPORTED;
1734 /*======================================================================*
1735 * Low level DSOUND implementation *
1736 *======================================================================*/
1738 typedef struct IDsDriverImpl IDsDriverImpl;
1739 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;
1741 struct IDsDriverImpl
1743 /* IUnknown fields */
1744 ICOM_VFIELD(IDsDriver);
1745 DWORD ref;
1746 /* IDsDriverImpl fields */
1747 UINT wDevID;
1748 IDsDriverBufferImpl*primary;
1751 struct IDsDriverBufferImpl
1753 /* IUnknown fields */
1754 ICOM_VFIELD(IDsDriverBuffer);
1755 DWORD ref;
1756 /* IDsDriverBufferImpl fields */
1757 IDsDriverImpl* drv;
1758 DWORD buflen;
1761 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
1763 /* we can't perform memory mapping as we don't have a file stream
1764 interface with jack like we do with oss */
1765 MESSAGE("This sound card's driver does not support direct access\n");
1766 MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
1767 return MMSYSERR_NOTSUPPORTED;
1770 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
1772 memset(desc, 0, sizeof(*desc));
1773 strcpy(desc->szDesc, "Wine jack DirectSound Driver");
1774 strcpy(desc->szDrvName, "winejack.drv");
1775 return MMSYSERR_NOERROR;
1778 static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid)
1780 memcpy(pGuid, &DSDEVID_DefaultPlayback, sizeof(GUID));
1781 return MMSYSERR_NOERROR;
1784 /*======================================================================*
1785 * Low level WAVE IN implementation *
1786 *======================================================================*/
1788 /**************************************************************************
1789 * widNotifyClient [internal]
1791 static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1793 TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
1795 switch (wMsg) {
1796 case WIM_OPEN:
1797 case WIM_CLOSE:
1798 case WIM_DATA:
1799 if (wwi->wFlags != DCB_NULL &&
1800 !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
1801 (HDRVR)wwi->waveDesc.hWave, wMsg, wwi->waveDesc.dwInstance,
1802 dwParam1, dwParam2))
1804 WARN("can't notify client !\n");
1805 return MMSYSERR_ERROR;
1807 break;
1808 default:
1809 FIXME("Unknown callback message %u\n", wMsg);
1810 return MMSYSERR_INVALPARAM;
1812 return MMSYSERR_NOERROR;
1815 /******************************************************************
1816 * JACK_callback_wwi
1818 /* everytime the jack server wants something from us it calls this
1819 function */
1820 int JACK_callback_wwi (nframes_t nframes, void *arg)
1822 sample_t* in_l;
1823 sample_t* in_r = 0;
1824 WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
1826 TRACE("wDevID: %u, nframes %u\n", wwi->wDevID, nframes);
1828 if(!wwi->client)
1829 ERR("client is closed, this is weird...\n");
1831 in_l = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_l, nframes);
1833 if (wwi->in_port_r)
1834 in_r = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_r, nframes);
1836 EnterCriticalSection(&wwi->access_crst);
1838 if((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
1840 LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
1841 nframes_t jackFramesLeft = nframes;
1843 #if JACK_CLOSE_HACK
1844 if(wwi->in_use == FALSE)
1846 /* do nothing if nothing is being recorded */
1847 return 0;
1849 #endif
1851 TRACE("wwi.state == WINE_WS_PLAYING\n");
1853 while (lpWaveHdr && jackFramesLeft)
1855 DWORD waveHdrFramesLeft = (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded) / (sizeof(short) * wwi->format.wf.nChannels);
1856 DWORD numFrames = min (jackFramesLeft, waveHdrFramesLeft);
1858 TRACE ("dwBufferLength=(%lu) dwBytesRecorded=(%ld)\n", lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
1859 TRACE ("jackFramesLeft=(%u) waveHdrFramesLeft=(%lu)\n", jackFramesLeft, waveHdrFramesLeft);
1861 if (!in_r) {
1862 /* mono */
1863 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded), in_l+(nframes-jackFramesLeft), numFrames, 1);
1864 } else {
1865 /* stereo */
1866 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded),
1867 in_l+(nframes-jackFramesLeft), numFrames, 2);
1868 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded + sizeof(short)),
1869 in_r+(nframes-jackFramesLeft), numFrames, 2);
1872 lpWaveHdr->dwBytesRecorded += (numFrames * sizeof(short) * wwi->format.wf.nChannels );
1873 jackFramesLeft -= numFrames;
1875 if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
1877 /* must copy the value of next waveHdr, because we have no idea of what
1878 * will be done with the content of lpWaveHdr in callback
1880 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
1882 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1883 lpWaveHdr->dwFlags |= WHDR_DONE;
1885 TRACE("WaveHdr full. dwBytesRecorded=(%lu) dwFlags=(0x%lx)\n",lpWaveHdr->dwBytesRecorded,lpWaveHdr->dwFlags);
1887 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1889 lpWaveHdr = wwi->lpQueuePtr = lpNext;
1892 TRACE ("jackFramesLeft=(%u) lpWaveHdr=(%p)\n", jackFramesLeft, lpWaveHdr);
1893 if (jackFramesLeft > 0) { WARN("Record buffer ran out of WaveHdrs\n"); }
1896 LeaveCriticalSection(&wwi->access_crst);
1898 return 0;
1901 /******************************************************************
1902 * JACK_OpenWaveInDevice
1904 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels)
1906 const char** ports;
1907 int i;
1908 char client_name[64];
1909 jack_port_t* in_port_l;
1910 jack_port_t* in_port_r = 0;
1911 jack_client_t* client;
1912 int failed = 0;
1914 TRACE("creating jack client and setting up callbacks\n");
1916 if ((nChannels == 0) || (nChannels > 2)) {
1917 ERR ("nChannels = (%d), but we only support mono or stereo.\n", nChannels);
1918 return 0;
1921 #if JACK_CLOSE_HACK
1922 /* see if this device is already open */
1923 if(wwi->client)
1925 /* if this device is already in use then it is bad for us to be in here */
1926 if(wwi->in_use)
1927 return 0;
1929 TRACE("using existing client\n");
1930 wwi->in_use = TRUE;
1931 return 1;
1933 #endif
1935 /* zero out the buffer pointer and the size of the buffer */
1936 wwi->sound_buffer = 0;
1937 wwi->buffer_size = 0;
1939 /* try to become a client of the JACK server */
1940 snprintf(client_name, sizeof(client_name), "wine_jack_in_%d", wwi->wDevID);
1941 TRACE("client name '%s'\n", client_name);
1942 if ((client = fp_jack_client_new (client_name)) == 0)
1944 /* jack has problems with shutting down clients, so lets */
1945 /* wait a short while and try once more before we give up */
1946 Sleep(250);
1947 if ((client = fp_jack_client_new (client_name)) == 0)
1949 ERR("jack server not running?\n");
1950 return 0;
1953 wwi->client = client;
1955 /* tell the JACK server to call `JACK_wwi_callback()' whenever
1956 there is work to be done. */
1957 fp_jack_set_process_callback (client, JACK_callback_wwi, wwi);
1959 /* tell the JACK server to call `JACK_bufsize_wwi()' whenever
1960 the maximum number of frames that will be passed
1961 to `JACK_Callback()' changes */
1962 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwi, wwi);
1964 /* tell the JACK server to call `srate()' whenever
1965 the sample rate of the system changes. */
1966 fp_jack_set_sample_rate_callback (client, JACK_srate, wwi);
1968 /* tell the JACK server to call `jack_shutdown()' if
1969 it ever shuts down, either entirely, or if it
1970 just decides to stop calling us. */
1971 fp_jack_on_shutdown (client, JACK_shutdown_wwi, wwi);
1973 /* display the current sample rate. once the client is activated
1974 (see below), you should rely on your own sample rate
1975 callback (see above) for this value. */
1976 wwi->sample_rate = fp_jack_get_sample_rate(client);
1977 TRACE("engine sample rate: %lu\n", wwi->sample_rate);
1979 /* create the left and right channel output ports */
1980 /* jack's ports are all mono so for stereo you need two */
1981 in_port_l = fp_jack_port_register (client, "in_l",
1982 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
1983 wwi->in_port_l = in_port_l;
1984 TRACE("Created port. (%p)\n", in_port_l);
1986 if (nChannels == 2)
1988 in_port_r = fp_jack_port_register (client, "in_r",
1989 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
1990 TRACE("Created port. (%p)\n", in_port_r);
1992 wwi->in_port_r = in_port_r;
1994 #if JACK_CLOSE_HACK
1995 wwi->in_use = TRUE; /* mark this device as in use since it now is ;-) */
1996 #endif
1998 TRACE("activating client.\n");
1999 /* tell the JACK server that we are ready to roll */
2000 if (fp_jack_activate (client))
2002 ERR( "cannot activate client\n");
2003 return 0;
2005 TRACE("activated client.\n");
2006 /* figure out what the ports that we want to output on are */
2007 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
2008 /* this way works if names are changed */
2009 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
2011 /* display a trace of the output ports we found */
2012 for(i = 0; ports[i]; i++)
2014 TRACE("ports[%d] = '%s'\n", i, ports[i]);
2017 if(!ports)
2019 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsOutput'\n");
2022 /* connect the ports. Note: you can't do this before
2023 the client is activated (this may change in the future).
2025 /* we want to connect to two ports so we have stereo input ;-) */
2027 if(fp_jack_connect(client, ports[0], fp_jack_port_name(in_port_l)))
2029 ERR ("cannot connect to input port %d('%s')\n", 0, ports[0]);
2030 failed = 1;
2032 TRACE("Connected (%s)<->(%s)\n",ports[0],fp_jack_port_name(in_port_l));
2034 if ((nChannels == 2) && in_port_r) {
2035 if(fp_jack_connect(client, ports[1], fp_jack_port_name(in_port_r)))
2037 ERR ("cannot connect to input port %d('%s')\n", 1, ports[1]);
2038 failed = 1;
2040 TRACE("Connected (%s)<->(%s)\n",ports[1],fp_jack_port_name(in_port_r));
2042 free(ports); /* free the returned array of ports */
2044 /* if something failed we need to shut the client down and return 0 */
2045 if(failed)
2047 #if JACK_CLOSE_HACK
2048 JACK_CloseWaveInDevice(wwi, TRUE);
2049 #else
2050 JACK_CloseWaveInDevice(wwi);
2051 #endif
2052 return 0;
2055 TRACE("return success.\n");
2056 return 1; /* return success */
2059 /**************************************************************************
2060 * widGetDevCaps [internal]
2062 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSA lpCaps, DWORD dwSize)
2064 TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
2066 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
2068 if (wDevID >= MAX_WAVEINDRV) {
2069 TRACE("MAX_WAVEINDRV reached !\n");
2070 return MMSYSERR_BADDEVICEID;
2073 memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
2074 return MMSYSERR_NOERROR;
2077 /**************************************************************************
2078 * widOpen [internal]
2080 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
2082 WINE_WAVEIN* wwi;
2083 DWORD retval;
2085 TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
2086 if (lpDesc == NULL)
2088 WARN("Invalid Parameter !\n");
2089 return MMSYSERR_INVALPARAM;
2091 if (wDevID >= MAX_WAVEINDRV) {
2092 TRACE ("MAX_WAVEINDRV reached !\n");
2093 return MMSYSERR_BADDEVICEID;
2096 #if JACK_CLOSE_HACK
2097 if(WInDev[wDevID].client && WOutDev[wDevID].in_use)
2098 #else
2099 if(WInDev[wDevID].client)
2100 #endif
2102 TRACE("device %d already allocated\n", wDevID);
2103 return MMSYSERR_ALLOCATED;
2106 /* make sure we aren't being opened in 8 bit mode */
2107 if(lpDesc->lpFormat->wBitsPerSample == 8)
2109 TRACE("8bits per sample unsupported, returning WAVERR_BADFORMAT\n");
2110 return WAVERR_BADFORMAT;
2113 /* only PCM format is supported so far... */
2114 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
2115 lpDesc->lpFormat->nChannels == 0 ||
2116 lpDesc->lpFormat->nSamplesPerSec == 0)
2118 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
2119 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2120 lpDesc->lpFormat->nSamplesPerSec);
2121 return WAVERR_BADFORMAT;
2124 if (dwFlags & WAVE_FORMAT_QUERY)
2126 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
2127 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2128 lpDesc->lpFormat->nSamplesPerSec);
2129 return MMSYSERR_NOERROR;
2132 wwi = &WInDev[wDevID];
2133 wwi->wDevID = wDevID;
2135 /* Set things up before we call JACK_OpenWaveOutDevice because */
2136 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
2137 /* even returns and we want to be initialized before then */
2138 wwi->state = WINE_WS_STOPPED; /* start in a stopped state */
2140 InitializeCriticalSection(&wwi->access_crst); /* initialize the critical section */
2141 EnterCriticalSection(&wwi->access_crst);
2143 /* open up jack ports for this device */
2144 if (!JACK_OpenWaveInDevice(&WInDev[wDevID], lpDesc->lpFormat->nChannels))
2146 ERR("JACK_OpenWaveInDevice(%d) failed\n", wDevID);
2147 LeaveCriticalSection(&wwi->access_crst);
2148 DeleteCriticalSection(&wwi->access_crst);
2149 return MMSYSERR_ERROR; /* return unspecified error */
2152 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
2154 wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
2156 memcpy(&wwi->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
2157 memcpy(&wwi->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
2159 LeaveCriticalSection(&wwi->access_crst);
2161 /* display the current wave format */
2162 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
2163 wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
2164 wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
2165 wwi->format.wf.nBlockAlign);
2167 /* make sure that we have the same sample rate in our audio stream */
2168 /* as we do in the jack server */
2169 if(wwi->format.wf.nSamplesPerSec != wwi->sample_rate)
2171 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
2172 wwi->sample_rate, wwi->format.wf.nSamplesPerSec);
2174 #if JACK_CLOSE_HACK
2175 JACK_CloseWaveInDevice(wwi, FALSE); /* close this device, don't force the client to close */
2176 #else
2177 JACK_CloseWaveInDevice(wwi); /* close this device */
2178 #endif
2179 DeleteCriticalSection(&wwi->access_crst);
2180 return WAVERR_BADFORMAT;
2183 /* check for an invalid number of bits per sample */
2184 if (wwi->format.wBitsPerSample == 0)
2186 WARN("Resetting zeroed wBitsPerSample to 16\n");
2187 wwi->format.wBitsPerSample = 16 *
2188 (wwi->format.wf.nAvgBytesPerSec /
2189 wwi->format.wf.nSamplesPerSec) /
2190 wwi->format.wf.nChannels;
2193 TRACE("notify client.\n");
2194 EnterCriticalSection(&wwi->access_crst);
2195 retval = widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
2196 LeaveCriticalSection(&wwi->access_crst);
2198 return retval;
2200 /**************************************************************************
2201 * widClose [internal]
2203 static DWORD widClose(WORD wDevID)
2205 DWORD ret = MMSYSERR_NOERROR;
2206 WINE_WAVEIN* wwi;
2208 TRACE("(%u);\n", wDevID);
2210 if (wDevID >= MAX_WAVEINDRV || !WInDev[wDevID].client)
2212 WARN("bad device ID !\n");
2213 return MMSYSERR_BADDEVICEID;
2216 wwi = &WInDev[wDevID];
2217 if (wwi->lpQueuePtr)
2219 WARN("buffers still playing !\n");
2220 ret = WAVERR_STILLPLAYING;
2221 } else
2223 /* sanity check: this should not happen since the device must have been reset before */
2224 if (wwi->lpQueuePtr) ERR("out of sync\n");
2226 wwi->state = WINE_WS_CLOSED; /* mark the device as closed */
2228 #if JACK_CLOSE_HACK
2229 JACK_CloseWaveInDevice(wwi, FALSE); /* close the jack device, DO NOT force the client to close */
2230 #else
2231 JACK_CloseWaveInDevice(wwi); /* close the jack device */
2232 #endif
2233 DeleteCriticalSection(&wwi->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
2235 ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
2238 return ret;
2241 /**************************************************************************
2242 * widAddBuffer [internal]
2244 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2246 WINE_WAVEIN* wwi = &WInDev[wDevID];
2248 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2250 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2251 WARN("can't do it !\n");
2252 return MMSYSERR_INVALHANDLE;
2254 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
2255 TRACE("never been prepared !\n");
2256 return WAVERR_UNPREPARED;
2258 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2259 TRACE("header already in use !\n");
2260 return WAVERR_STILLPLAYING;
2263 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
2264 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2265 lpWaveHdr->dwBytesRecorded = 0;
2266 lpWaveHdr->lpNext = NULL;
2268 EnterCriticalSection(&wwi->access_crst);
2269 /* insert buffer at end of queue */
2271 LPWAVEHDR* wh;
2272 for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
2273 *wh=lpWaveHdr;
2275 LeaveCriticalSection(&wwi->access_crst);
2277 return MMSYSERR_NOERROR;
2280 /**************************************************************************
2281 * widPrepare [internal]
2283 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2285 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2287 if (wDevID >= MAX_WAVEINDRV) return MMSYSERR_INVALHANDLE;
2289 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
2290 return WAVERR_STILLPLAYING;
2292 lpWaveHdr->dwFlags |= WHDR_PREPARED;
2293 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2294 lpWaveHdr->dwBytesRecorded = 0;
2295 lpWaveHdr->lpNext = NULL;
2297 return MMSYSERR_NOERROR;
2300 /**************************************************************************
2301 * widUnprepare [internal]
2303 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2305 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2306 if (wDevID >= MAX_WAVEINDRV) {
2307 WARN("bad device ID !\n");
2308 return MMSYSERR_INVALHANDLE;
2311 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2312 TRACE("Still playing...\n");
2313 return WAVERR_STILLPLAYING;
2316 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
2317 lpWaveHdr->dwFlags |= WHDR_DONE;
2319 return MMSYSERR_NOERROR;
2322 /**************************************************************************
2323 * widStart [internal]
2325 static DWORD widStart(WORD wDevID)
2327 TRACE("(%u);\n", wDevID);
2328 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2329 WARN("can't start recording !\n");
2330 return MMSYSERR_INVALHANDLE;
2333 WInDev[wDevID].state = WINE_WS_PLAYING;
2334 return MMSYSERR_NOERROR;
2337 /**************************************************************************
2338 * widStop [internal]
2340 static DWORD widStop(WORD wDevID)
2342 WINE_WAVEIN* wwi = &WInDev[wDevID];
2344 TRACE("(%u);\n", wDevID);
2345 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2346 WARN("can't stop !\n");
2347 return MMSYSERR_INVALHANDLE;
2350 if (wwi->state != WINE_WS_STOPPED)
2352 WAVEHDR* lpWaveHdr;
2353 /* do something here to stop recording ??? */
2355 /* return current buffer to app */
2356 lpWaveHdr = wwi->lpQueuePtr;
2357 if (lpWaveHdr)
2359 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
2360 TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2361 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2362 lpWaveHdr->dwFlags |= WHDR_DONE;
2363 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2364 wwi->lpQueuePtr = lpNext;
2367 wwi->state = WINE_WS_STOPPED;
2369 return MMSYSERR_NOERROR;
2372 /**************************************************************************
2373 * widReset [internal]
2375 static DWORD widReset(WORD wDevID)
2377 WINE_WAVEIN* wwi = &WInDev[wDevID];
2378 WAVEHDR* lpWaveHdr;
2380 TRACE("(%u);\n", wDevID);
2381 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2382 WARN("can't reset !\n");
2383 return MMSYSERR_INVALHANDLE;
2386 wwi->state = WINE_WS_STOPPED;
2388 /* return all buffers to the app */
2389 for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
2390 TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2391 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2392 lpWaveHdr->dwFlags |= WHDR_DONE;
2394 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2396 wwi->lpQueuePtr = NULL;
2398 return MMSYSERR_NOERROR;
2401 /**************************************************************************
2402 * widMessage (WINEJACK.6)
2404 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2405 DWORD dwParam1, DWORD dwParam2)
2407 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
2408 wDevID, wMsg, dwUser, dwParam1, dwParam2);
2410 switch (wMsg) {
2411 case DRVM_INIT:
2412 case DRVM_EXIT:
2413 case DRVM_ENABLE:
2414 case DRVM_DISABLE:
2415 /* FIXME: Pretend this is supported */
2416 return 0;
2417 case WIDM_OPEN: return widOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
2418 case WIDM_CLOSE: return widClose (wDevID);
2419 case WIDM_ADDBUFFER: return widAddBuffer (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2420 case WIDM_PREPARE: return widPrepare (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2421 case WIDM_UNPREPARE: return widUnprepare (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2422 case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (LPWAVEINCAPSA)dwParam1, dwParam2);
2423 case WIDM_GETNUMDEVS: return MAX_WAVEINDRV;
2424 case WIDM_RESET: return widReset (wDevID);
2425 case WIDM_START: return widStart (wDevID);
2426 case WIDM_STOP: return widStop (wDevID);
2427 default:
2428 FIXME("unknown message %d!\n", wMsg);
2431 return MMSYSERR_NOTSUPPORTED;
2434 #else /* !HAVE_JACK_JACK_H */
2436 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2437 DWORD dwParam1, DWORD dwParam2)
2439 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2440 return MMSYSERR_NOTENABLED;
2443 /**************************************************************************
2444 * wodMessage (WINEJACK.7)
2446 DWORD WINAPI JACK_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2447 DWORD dwParam1, DWORD dwParam2)
2449 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2450 return MMSYSERR_NOTENABLED;
2453 #endif /* HAVE_JACK_JACK_H */