1 /* -*- tab-width: 8; c-basic-offset: 2 -*- */
3 * Wine Driver for jack Sound Server
4 * http://jackit.sourceforge.net
6 * Copyright 1994 Martin Ayotte
7 * Copyright 1999 Eric Pouech (async playing in waveOut/waveIn)
8 * Copyright 2000 Eric Pouech (loops in waveOut)
9 * Copyright 2002 Chris Morgan (jack version of this file)
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * implement audio stream resampling for any arbitrary frequenty
29 * right now we use the winmm layer to do resampling although it would
30 * be nice to have a full set of algorithms to choose from based on cpu
34 * pause in waveOut during loop is not handled correctly
51 #include "wine/winuser16.h"
56 #include "wine/debug.h"
58 #ifdef HAVE_JACK_JACK_H
59 #include <jack/jack.h>
63 WINE_DEFAULT_DEBUG_CHANNEL(wave);
65 #ifdef HAVE_JACK_JACK_H
67 #define MAKE_FUNCPTR(f) static typeof(f) * fp_##f = NULL;
69 /* Function pointers for dynamic loading of libjack */
70 /* these are prefixed with "fp_", ie. "fp_jack_client_new" */
71 MAKE_FUNCPTR(jack_activate);
72 MAKE_FUNCPTR(jack_connect);
73 MAKE_FUNCPTR(jack_client_new);
74 MAKE_FUNCPTR(jack_client_close);
75 MAKE_FUNCPTR(jack_deactivate);
76 MAKE_FUNCPTR(jack_set_process_callback);
77 MAKE_FUNCPTR(jack_set_buffer_size_callback);
78 MAKE_FUNCPTR(jack_set_sample_rate_callback);
79 MAKE_FUNCPTR(jack_on_shutdown);
80 MAKE_FUNCPTR(jack_get_sample_rate);
81 MAKE_FUNCPTR(jack_port_register);
82 MAKE_FUNCPTR(jack_port_get_buffer);
83 MAKE_FUNCPTR(jack_get_ports);
84 MAKE_FUNCPTR(jack_port_name);
85 MAKE_FUNCPTR(jack_get_buffer_size);
88 /* define the below to work around a bug in jack where closing a port */
89 /* takes a very long time, so to get around this we actually don't */
90 /* close the port when the device is closed but instead mark the */
91 /* corresponding device as unused */
92 #define JACK_CLOSE_HACK 1
94 typedef jack_default_audio_sample_t sample_t;
95 typedef jack_nframes_t nframes_t;
97 /* only allow 10 output devices through this driver, this ought to be adequate */
98 #define MAX_WAVEOUTDRV (10)
99 #define MAX_WAVEINDRV (10)
101 /* state diagram for waveOut writing:
103 * +---------+-------------+---------------+---------------------------------+
104 * | state | function | event | new state |
105 * +---------+-------------+---------------+---------------------------------+
106 * | | open() | | STOPPED |
107 * | PAUSED | write() | | PAUSED |
108 * | STOPPED | write() | <thrd create> | PLAYING |
109 * | PLAYING | write() | HEADER | PLAYING |
110 * | (other) | write() | <error> | |
111 * | (any) | pause() | PAUSING | PAUSED |
112 * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
113 * | (any) | reset() | RESETTING | STOPPED |
114 * | (any) | close() | CLOSING | CLOSED |
115 * +---------+-------------+---------------+---------------------------------+
118 /* states of the playing device */
119 #define WINE_WS_PLAYING 0
120 #define WINE_WS_PAUSED 1
121 #define WINE_WS_STOPPED 2
122 #define WINE_WS_CLOSED 3
125 volatile int state; /* one of the WINE_WS_ manifest constants */
126 WAVEOPENDESC waveDesc;
128 PCMWAVEFORMAT format;
131 char interface_name[32];
133 jack_port_t* out_port_l; /* ports for left and right channels */
134 jack_port_t* out_port_r;
135 jack_client_t* client;
136 long sample_rate; /* jack server sample rate */
139 BOOL in_use; /* TRUE if this device is in use */
143 unsigned long buffer_size;
148 LPWAVEHDR lpQueuePtr; /* start of queued WAVEHDRs (waiting to be notified) */
149 LPWAVEHDR lpPlayPtr; /* start of not yet fully played buffers */
150 DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
152 LPWAVEHDR lpLoopPtr; /* pointer of first buffer in loop, if any */
153 DWORD dwLoops; /* private copy of loop counter */
155 DWORD dwPlayedTotal; /* number of bytes actually played since opening */
156 DWORD dwWrittenTotal; /* number of bytes written to jack since opening */
158 DWORD bytesInJack; /* bytes that we wrote during the previous JACK_Callback() */
159 DWORD tickCountMS; /* time in MS of last JACK_Callback() */
161 /* synchronization stuff */
162 CRITICAL_SECTION access_crst;
167 WAVEOPENDESC waveDesc;
169 PCMWAVEFORMAT format;
170 LPWAVEHDR lpQueuePtr;
171 DWORD dwTotalRecorded;
173 BOOL bTriggerSupport;
175 char interface_name[32];
177 jack_port_t* in_port_l; /* ports for left and right channels */
178 jack_port_t* in_port_r;
179 jack_client_t* client;
180 long sample_rate; /* jack server sample rate */
183 BOOL in_use; /* TRUE if this device is in use */
187 unsigned long buffer_size;
189 /* synchronization stuff */
190 CRITICAL_SECTION access_crst;
193 static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV];
194 static WINE_WAVEIN WInDev [MAX_WAVEINDRV ];
196 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
197 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
198 static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid);
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 FIXME("Format %d not supported ! use 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)
900 /* setup function pointers */
901 #define LOAD_FUNCPTR(f) if((fp_##f = wine_dlsym(jackhandle, #f, NULL, 0)) == NULL) goto sym_not_found;
902 LOAD_FUNCPTR(jack_activate);
903 LOAD_FUNCPTR(jack_connect);
904 LOAD_FUNCPTR(jack_client_new);
905 LOAD_FUNCPTR(jack_client_close);
906 LOAD_FUNCPTR(jack_deactivate);
907 LOAD_FUNCPTR(jack_set_process_callback);
908 LOAD_FUNCPTR(jack_set_buffer_size_callback);
909 LOAD_FUNCPTR(jack_set_sample_rate_callback);
910 LOAD_FUNCPTR(jack_on_shutdown);
911 LOAD_FUNCPTR(jack_get_sample_rate);
912 LOAD_FUNCPTR(jack_port_register);
913 LOAD_FUNCPTR(jack_port_get_buffer);
914 LOAD_FUNCPTR(jack_get_ports);
915 LOAD_FUNCPTR(jack_port_name);
916 LOAD_FUNCPTR(jack_get_buffer_size);
919 /* start with output device */
921 for (i = 0; i < MAX_WAVEOUTDRV; ++i)
923 WOutDev[i].client = 0; /* initialize the client to 0 */
926 WOutDev[i].in_use = FALSE;
927 WInDev[i].in_use = FALSE;
930 memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps));
932 /* FIXME: some programs compare this string against the content of the registry
933 * for MM drivers. The names have to match in order for the program to work
934 * (e.g. MS win9x mplayer.exe)
937 WOutDev[i].caps.wMid = 0x0002;
938 WOutDev[i].caps.wPid = 0x0104;
939 strcpy(WOutDev[i].caps.szPname, "SB16 Wave Out");
941 WOutDev[i].caps.wMid = 0x00FF; /* Manufac ID */
942 WOutDev[i].caps.wPid = 0x0001; /* Product ID */
943 /* strcpy(WOutDev[i].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/
944 strcpy(WOutDev[i].caps.szPname, "CS4236/37/38");
947 snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "winejack: %d", i);
949 WOutDev[i].caps.vDriverVersion = 0x0100;
950 WOutDev[i].caps.dwFormats = 0x00000000;
951 WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
953 WOutDev[i].caps.wChannels = 2;
954 WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;
956 /* NOTE: we don't support any 8 bit modes so note that */
957 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
958 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
959 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
960 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
961 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
962 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
963 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
964 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
965 /* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
966 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
967 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
968 WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
971 /* then do input device */
972 for (i = 0; i < MAX_WAVEINDRV; ++i)
974 /* TODO: we should initialize read stuff here */
975 memset(&WInDev[0].caps, 0, sizeof(WInDev[0].caps));
977 /* FIXME: some programs compare this string against the content of the registry
978 * for MM drivers. The names have to match in order for the program to work
979 * (e.g. MS win9x mplayer.exe)
982 WInDev[i].caps.wMid = 0x0002;
983 WInDev[i].caps.wPid = 0x0104;
984 strcpy(WInDev[i].caps.szPname, "SB16 Wave In");
986 WInDev[i].caps.wMid = 0x00FF;
987 WInDev[i].caps.wPid = 0x0001;
988 strcpy(WInDev[i].caps.szPname,"CS4236/37/38");
990 snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "winejack: %d", i);
992 WInDev[i].caps.vDriverVersion = 0x0100;
994 WInDev[i].caps.wChannels = 0x2;
995 /* NOTE: we don't support any 8 bit modes so note that */
996 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
997 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */
998 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
999 WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
1000 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
1001 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */
1002 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
1003 WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
1004 /* WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
1005 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/
1006 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
1007 WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
1008 WInDev[i].caps.wReserved1 = 0;
1011 return 1; /* return success */
1013 /* error path for function pointer loading errors */
1016 "Wine cannot find certain functions that it needs inside the jack"
1017 "library. To enable Wine to use the jack audio server please "
1018 "install libjack\n");
1019 wine_dlclose(jackhandle, NULL, 0);
1024 /*======================================================================*
1025 * Low level WAVE OUT implementation *
1026 *======================================================================*/
1028 /**************************************************************************
1029 * wodNotifyClient [internal]
1031 static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1033 TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
1039 if (wwo->wFlags != DCB_NULL &&
1040 !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags,
1041 (HDRVR)wwo->waveDesc.hWave, wMsg, wwo->waveDesc.dwInstance,
1042 dwParam1, dwParam2))
1044 WARN("can't notify client !\n");
1045 return MMSYSERR_ERROR;
1049 FIXME("Unknown callback message %u\n", wMsg);
1050 return MMSYSERR_INVALPARAM;
1052 return MMSYSERR_NOERROR;
1055 /**************************************************************************
1056 * wodHelper_BeginWaveHdr [internal]
1058 * Makes the specified lpWaveHdr the currently playing wave header.
1059 * If the specified wave header is a begin loop and we're not already in
1060 * a loop, setup the loop.
1062 static void wodHelper_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
1064 EnterCriticalSection(&wwo->access_crst);
1066 wwo->lpPlayPtr = lpWaveHdr;
1070 LeaveCriticalSection(&wwo->access_crst);
1074 if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)
1078 WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1079 TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
1082 TRACE("Starting loop (%ldx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
1083 wwo->lpLoopPtr = lpWaveHdr;
1084 /* Windows does not touch WAVEHDR.dwLoops,
1085 * so we need to make an internal copy */
1086 wwo->dwLoops = lpWaveHdr->dwLoops;
1089 wwo->dwPartialOffset = 0;
1091 LeaveCriticalSection(&wwo->access_crst);
1095 /**************************************************************************
1096 * wodHelper_PlayPtrNext [internal]
1098 * Advance the play pointer to the next waveheader, looping if required.
1100 static LPWAVEHDR wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
1102 LPWAVEHDR lpWaveHdr;
1104 EnterCriticalSection(&wwo->access_crst);
1106 lpWaveHdr = wwo->lpPlayPtr;
1108 wwo->dwPartialOffset = 0;
1109 if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr)
1111 /* We're at the end of a loop, loop if required */
1112 if (--wwo->dwLoops > 0)
1114 wwo->lpPlayPtr = wwo->lpLoopPtr;
1117 /* Handle overlapping loops correctly */
1118 if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
1119 FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
1120 /* shall we consider the END flag for the closing loop or for
1121 * the opening one or for both ???
1122 * code assumes for closing loop only
1126 lpWaveHdr = lpWaveHdr->lpNext;
1128 wwo->lpLoopPtr = NULL;
1129 wodHelper_BeginWaveHdr(wwo, lpWaveHdr);
1133 /* We're not in a loop. Advance to the next wave header */
1134 TRACE("not inside of a loop, advancing to next wave header\n");
1135 wodHelper_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
1138 LeaveCriticalSection(&wwo->access_crst);
1143 /* if force is TRUE then notify the client that all the headers were completed */
1144 static DWORD wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
1146 LPWAVEHDR lpWaveHdr;
1151 EnterCriticalSection(&wwo->access_crst);
1153 /* Start from lpQueuePtr and keep notifying until:
1154 * - we hit an unwritten wavehdr
1155 * - we hit the beginning of a running loop
1156 * - we hit a wavehdr which hasn't finished playing
1158 while ((lpWaveHdr = wwo->lpQueuePtr) &&
1160 (lpWaveHdr != wwo->lpPlayPtr &&
1161 lpWaveHdr != wwo->lpLoopPtr)))
1163 wwo->lpQueuePtr = lpWaveHdr->lpNext;
1165 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1166 lpWaveHdr->dwFlags |= WHDR_DONE;
1167 TRACE("notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) dwFlags=(%ld)\n",
1168 lpWaveHdr, wwo->lpPlayPtr, lpWaveHdr->dwFlags);
1170 wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
1172 TRACE("Not notifying client: lpWaveHdr=(%p) lpPlayPtr=(%p) lpLoopPtr=(%p)\n",
1173 lpWaveHdr, wwo->lpPlayPtr, wwo->lpLoopPtr);
1174 retval = (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr !=
1175 wwo->lpLoopPtr) ? 0 : INFINITE;
1177 LeaveCriticalSection(&wwo->access_crst);
1182 /**************************************************************************
1183 * wodHelper_Reset [internal]
1185 * Resets current output stream.
1187 static void wodHelper_Reset(WINE_WAVEOUT* wwo, BOOL reset)
1189 EnterCriticalSection(&wwo->access_crst);
1191 /* updates current notify list */
1192 wodHelper_NotifyCompletions(wwo, FALSE);
1196 /* remove all wave headers and notify client that all headers were completed */
1197 wodHelper_NotifyCompletions(wwo, TRUE);
1199 wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
1200 wwo->state = WINE_WS_STOPPED;
1201 wwo->dwPlayedTotal = wwo->dwWrittenTotal = wwo->bytesInJack = 0;
1203 wwo->dwPartialOffset = 0; /* Clear partial wavehdr */
1208 /* complicated case, not handled yet (could imply modifying the loop counter) */
1209 FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
1210 wwo->lpPlayPtr = wwo->lpLoopPtr;
1211 wwo->dwPartialOffset = 0;
1212 wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
1216 DWORD sz = wwo->dwPartialOffset;
1218 /* reset all the data as if we had written only up to lpPlayedTotal bytes */
1219 /* compute the max size playable from lpQueuePtr */
1220 for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext)
1222 sz += ptr->dwBufferLength;
1225 /* because the reset lpPlayPtr will be lpQueuePtr */
1226 if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("doh\n");
1227 wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal);
1228 wwo->dwWrittenTotal = wwo->dwPlayedTotal;
1229 wwo->lpPlayPtr = wwo->lpQueuePtr;
1232 wwo->state = WINE_WS_PAUSED;
1235 LeaveCriticalSection(&wwo->access_crst);
1238 /**************************************************************************
1239 * wodGetDevCaps [internal]
1241 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSA lpCaps, DWORD dwSize)
1243 TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1245 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1247 if (wDevID >= MAX_WAVEOUTDRV)
1249 TRACE("MAX_WAVOUTDRV reached !\n");
1250 return MMSYSERR_BADDEVICEID;
1253 TRACE("dwSupport=(0x%lx), dwFormats=(0x%lx)\n", WOutDev[wDevID].caps.dwSupport, WOutDev[wDevID].caps.dwFormats);
1254 memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
1255 return MMSYSERR_NOERROR;
1258 /**************************************************************************
1259 * wodOpen [internal]
1261 * NOTE: doesn't it seem like there is a race condition if you try to open
1262 * the same device twice?
1264 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1269 TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1272 WARN("Invalid Parameter !\n");
1273 return MMSYSERR_INVALPARAM;
1275 if (wDevID >= MAX_WAVEOUTDRV) {
1276 TRACE("MAX_WAVOUTDRV reached !\n");
1277 return MMSYSERR_BADDEVICEID;
1281 if(WOutDev[wDevID].client && WOutDev[wDevID].in_use)
1283 if(WOutDev[wDevID].client)
1286 TRACE("device %d already allocated\n", wDevID);
1287 return MMSYSERR_ALLOCATED;
1290 /* Only the PCM format is supported so far...
1291 * Also we only support 16 bit mode.
1293 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1294 lpDesc->lpFormat->nChannels == 0 ||
1295 lpDesc->lpFormat->nSamplesPerSec == 0 ||
1296 lpDesc->lpFormat->wBitsPerSample != 16)
1298 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
1299 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1300 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
1301 return WAVERR_BADFORMAT;
1304 if (dwFlags & WAVE_FORMAT_QUERY)
1306 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1307 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1308 lpDesc->lpFormat->nSamplesPerSec);
1309 return MMSYSERR_NOERROR;
1312 wwo = &WOutDev[wDevID];
1313 wwo->wDevID = wDevID;
1315 /* Set things up before we call JACK_OpenWaveOutDevice because */
1316 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
1317 /* even returns and we want to be initialized before then */
1318 wwo->state = WINE_WS_STOPPED; /* start in a stopped state */
1319 wwo->dwPlayedTotal = 0; /* zero out these totals */
1320 wwo->dwWrittenTotal = 0;
1321 wwo->bytesInJack = 0;
1322 wwo->tickCountMS = 0;
1324 /* Initialize volume to full level */
1325 wwo->volume_left = 100;
1326 wwo->volume_right = 100;
1328 InitializeCriticalSection(&wwo->access_crst); /* initialize the critical section */
1329 EnterCriticalSection(&wwo->access_crst);
1331 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
1333 wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1335 memcpy(&wwo->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1336 memcpy(&wwo->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1338 /* open up jack ports for this device */
1339 if (!JACK_OpenWaveOutDevice(&WOutDev[wDevID]))
1341 ERR("JACK_OpenWaveOutDevice(%d) failed\n", wDevID);
1342 LeaveCriticalSection(&wwo->access_crst);
1343 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1344 return MMSYSERR_ERROR; /* return unspecified error */
1347 LeaveCriticalSection(&wwo->access_crst);
1349 /* display the current wave format */
1350 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
1351 wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
1352 wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1353 wwo->format.wf.nBlockAlign);
1355 /* make sure that we have the same sample rate in our audio stream */
1356 /* as we do in the jack server */
1357 if(wwo->format.wf.nSamplesPerSec != wwo->sample_rate)
1359 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
1360 wwo->sample_rate, wwo->format.wf.nSamplesPerSec);
1363 JACK_CloseWaveOutDevice(wwo, FALSE); /* close this device, don't force the client to close */
1365 JACK_CloseWaveOutDevice(wwo); /* close this device */
1367 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1368 return WAVERR_BADFORMAT;
1371 /* check for an invalid number of bits per sample */
1372 if (wwo->format.wBitsPerSample == 0)
1374 WARN("Resetting zeroed wBitsPerSample\n");
1375 wwo->format.wBitsPerSample = 8 *
1376 (wwo->format.wf.nAvgBytesPerSec /
1377 wwo->format.wf.nSamplesPerSec) /
1378 wwo->format.wf.nChannels;
1381 EnterCriticalSection(&wwo->access_crst);
1382 retval = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
1383 LeaveCriticalSection(&wwo->access_crst);
1388 /**************************************************************************
1389 * wodClose [internal]
1391 static DWORD wodClose(WORD wDevID)
1393 DWORD ret = MMSYSERR_NOERROR;
1396 TRACE("(%u);\n", wDevID);
1398 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1400 WARN("bad device ID !\n");
1401 return MMSYSERR_BADDEVICEID;
1404 wwo = &WOutDev[wDevID];
1405 if (wwo->lpQueuePtr)
1407 WARN("buffers still playing !\n");
1408 ret = WAVERR_STILLPLAYING;
1411 /* sanity check: this should not happen since the device must have been reset before */
1412 if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
1414 wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
1417 JACK_CloseWaveOutDevice(wwo, FALSE); /* close the jack device, DO NOT force the client to close */
1419 JACK_CloseWaveOutDevice(wwo); /* close the jack device */
1421 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1423 ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
1430 /**************************************************************************
1431 * wodWrite [internal]
1434 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1439 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1441 /* first, do the sanity checks... */
1442 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1444 WARN("bad dev ID !\n");
1445 return MMSYSERR_BADDEVICEID;
1448 wwo = &WOutDev[wDevID];
1450 if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1452 TRACE("unprepared\n");
1453 return WAVERR_UNPREPARED;
1456 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1458 TRACE("still playing\n");
1459 return WAVERR_STILLPLAYING;
1462 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1463 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1464 lpWaveHdr->lpNext = 0;
1466 EnterCriticalSection(&wwo->access_crst);
1468 /* insert buffer at the end of queue */
1469 for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
1472 if (!wwo->lpPlayPtr)
1473 wodHelper_BeginWaveHdr(wwo,lpWaveHdr);
1474 if (wwo->state == WINE_WS_STOPPED)
1475 wwo->state = WINE_WS_PLAYING;
1476 LeaveCriticalSection(&wwo->access_crst);
1478 return MMSYSERR_NOERROR;
1481 /**************************************************************************
1482 * wodPrepare [internal]
1484 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1486 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1488 if (wDevID >= MAX_WAVEOUTDRV)
1490 WARN("bad device ID !\n");
1491 return MMSYSERR_BADDEVICEID;
1494 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1495 return WAVERR_STILLPLAYING;
1497 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1498 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1499 return MMSYSERR_NOERROR;
1502 /**************************************************************************
1503 * wodUnprepare [internal]
1505 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1507 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1509 if (wDevID >= MAX_WAVEOUTDRV)
1511 WARN("bad device ID !\n");
1512 return MMSYSERR_BADDEVICEID;
1515 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1516 return WAVERR_STILLPLAYING;
1518 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1519 lpWaveHdr->dwFlags |= WHDR_DONE;
1521 return MMSYSERR_NOERROR;
1524 /**************************************************************************
1525 * wodPause [internal]
1527 static DWORD wodPause(WORD wDevID)
1529 TRACE("(%u);!\n", wDevID);
1531 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1533 WARN("bad device ID !\n");
1534 return MMSYSERR_BADDEVICEID;
1537 TRACE("[3-PAUSING]\n");
1539 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1540 wodHelper_Reset(&WOutDev[wDevID], FALSE);
1541 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1543 return MMSYSERR_NOERROR;
1546 /**************************************************************************
1547 * wodRestart [internal]
1549 static DWORD wodRestart(WORD wDevID)
1551 TRACE("(%u);\n", wDevID);
1553 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1555 WARN("bad device ID !\n");
1556 return MMSYSERR_BADDEVICEID;
1559 if (WOutDev[wDevID].state == WINE_WS_PAUSED)
1561 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1562 WOutDev[wDevID].state = WINE_WS_PLAYING;
1563 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1566 return MMSYSERR_NOERROR;
1569 /**************************************************************************
1570 * wodReset [internal]
1572 static DWORD wodReset(WORD wDevID)
1574 TRACE("(%u);\n", wDevID);
1576 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1578 WARN("bad device ID !\n");
1579 return MMSYSERR_BADDEVICEID;
1582 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1583 wodHelper_Reset(&WOutDev[wDevID], TRUE);
1584 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1586 return MMSYSERR_NOERROR;
1589 /**************************************************************************
1590 * wodGetPosition [internal]
1592 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1598 TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1600 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1602 WARN("bad device ID !\n");
1603 return MMSYSERR_BADDEVICEID;
1606 /* if null pointer to time structure return error */
1607 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1609 wwo = &WOutDev[wDevID];
1611 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1612 val = wwo->dwPlayedTotal;
1613 elapsedMS = GetTickCount() - wwo->tickCountMS;
1614 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1616 /* account for the bytes played since the last JACK_Callback() */
1617 val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
1619 return bytes_to_mmtime(lpTime, val, &wwo->format);
1622 /**************************************************************************
1623 * wodBreakLoop [internal]
1625 static DWORD wodBreakLoop(WORD wDevID)
1627 TRACE("(%u);\n", wDevID);
1629 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1631 WARN("bad device ID !\n");
1632 return MMSYSERR_BADDEVICEID;
1635 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1637 if (WOutDev[wDevID].state == WINE_WS_PLAYING && WOutDev[wDevID].lpLoopPtr != NULL)
1639 /* ensure exit at end of current loop */
1640 WOutDev[wDevID].dwLoops = 1;
1643 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1645 return MMSYSERR_NOERROR;
1648 /**************************************************************************
1649 * wodGetVolume [internal]
1651 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1655 left = WOutDev[wDevID].volume_left;
1656 right = WOutDev[wDevID].volume_right;
1658 TRACE("(%u, %p);\n", wDevID, lpdwVol);
1660 *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
1663 return MMSYSERR_NOERROR;
1666 /**************************************************************************
1667 * wodSetVolume [internal]
1669 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1673 left = (LOWORD(dwParam) * 100) / 0xFFFFl;
1674 right = (HIWORD(dwParam) * 100) / 0xFFFFl;
1676 TRACE("(%u, %08lX);\n", wDevID, dwParam);
1678 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1680 WOutDev[wDevID].volume_left = left;
1681 WOutDev[wDevID].volume_right = right;
1683 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1685 return MMSYSERR_NOERROR;
1688 /**************************************************************************
1689 * wodGetNumDevs [internal]
1691 static DWORD wodGetNumDevs(void)
1693 return MAX_WAVEOUTDRV;
1696 /**************************************************************************
1697 * wodDevInterfaceSize [internal]
1699 static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
1701 TRACE("(%u, %p)\n", wDevID, dwParam1);
1703 *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1704 NULL, 0 ) * sizeof(WCHAR);
1705 return MMSYSERR_NOERROR;
1708 /**************************************************************************
1709 * wodDevInterface [internal]
1711 static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
1713 if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1714 NULL, 0 ) * sizeof(WCHAR))
1716 MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
1717 dwParam1, dwParam2 / sizeof(WCHAR));
1718 return MMSYSERR_NOERROR;
1720 return MMSYSERR_INVALPARAM;
1723 /**************************************************************************
1724 * wodMessage (WINEJACK.7)
1726 DWORD WINAPI JACK_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
1727 DWORD dwParam1, DWORD dwParam2)
1729 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
1730 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1734 TRACE("DRVM_INIT\n");
1735 return JACK_WaveInit();
1737 TRACE("DRVM_EXIT\n");
1738 return JACK_WaveRelease();
1740 /* FIXME: Pretend this is supported */
1741 TRACE("DRVM_ENABLE\n");
1744 /* FIXME: Pretend this is supported */
1745 TRACE("DRVM_DISABLE\n");
1747 case WODM_OPEN: return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1748 case WODM_CLOSE: return wodClose(wDevID);
1749 case WODM_WRITE: return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1750 case WODM_PAUSE: return wodPause(wDevID);
1751 case WODM_GETPOS: return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1752 case WODM_BREAKLOOP: return wodBreakLoop(wDevID);
1753 case WODM_PREPARE: return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1754 case WODM_UNPREPARE: return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1755 case WODM_GETDEVCAPS: return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSA)dwParam1, dwParam2);
1756 case WODM_GETNUMDEVS: return wodGetNumDevs();
1757 case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED;
1758 case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED;
1759 case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1760 case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1761 case WODM_GETVOLUME: return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1762 case WODM_SETVOLUME: return wodSetVolume(wDevID, dwParam1);
1763 case WODM_RESTART: return wodRestart(wDevID);
1764 case WODM_RESET: return wodReset(wDevID);
1766 case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
1767 case DRV_QUERYDEVICEINTERFACE: return wodDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
1768 case DRV_QUERYDSOUNDIFACE: return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1);
1769 case DRV_QUERYDSOUNDDESC: return wodDsDesc(wDevID, (PDSDRIVERDESC)dwParam1);
1770 case DRV_QUERYDSOUNDGUID: return wodDsGuid(wDevID, (LPGUID)dwParam1);
1772 FIXME("unknown message %d!\n", wMsg);
1774 return MMSYSERR_NOTSUPPORTED;
1777 /*======================================================================*
1778 * Low level DSOUND implementation *
1779 *======================================================================*/
1781 typedef struct IDsDriverImpl IDsDriverImpl;
1782 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;
1784 struct IDsDriverImpl
1786 /* IUnknown fields */
1787 ICOM_VFIELD(IDsDriver);
1789 /* IDsDriverImpl fields */
1791 IDsDriverBufferImpl*primary;
1794 struct IDsDriverBufferImpl
1796 /* IUnknown fields */
1797 ICOM_VFIELD(IDsDriverBuffer);
1799 /* IDsDriverBufferImpl fields */
1804 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
1806 /* we can't perform memory mapping as we don't have a file stream
1807 interface with jack like we do with oss */
1808 MESSAGE("This sound card's driver does not support direct access\n");
1809 MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
1810 return MMSYSERR_NOTSUPPORTED;
1813 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
1815 memset(desc, 0, sizeof(*desc));
1816 strcpy(desc->szDesc, "Wine jack DirectSound Driver");
1817 strcpy(desc->szDrvName, "winejack.drv");
1818 return MMSYSERR_NOERROR;
1821 static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid)
1823 memcpy(pGuid, &DSDEVID_DefaultPlayback, sizeof(GUID));
1824 return MMSYSERR_NOERROR;
1827 /*======================================================================*
1828 * Low level WAVE IN implementation *
1829 *======================================================================*/
1831 /**************************************************************************
1832 * widNotifyClient [internal]
1834 static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1836 TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
1842 if (wwi->wFlags != DCB_NULL &&
1843 !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
1844 (HDRVR)wwi->waveDesc.hWave, wMsg, wwi->waveDesc.dwInstance,
1845 dwParam1, dwParam2))
1847 WARN("can't notify client !\n");
1848 return MMSYSERR_ERROR;
1852 FIXME("Unknown callback message %u\n", wMsg);
1853 return MMSYSERR_INVALPARAM;
1855 return MMSYSERR_NOERROR;
1858 /******************************************************************
1861 /* everytime the jack server wants something from us it calls this
1863 int JACK_callback_wwi (nframes_t nframes, void *arg)
1867 WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
1869 TRACE("wDevID: %u, nframes %u\n", wwi->wDevID, nframes);
1872 ERR("client is closed, this is weird...\n");
1874 in_l = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_l, nframes);
1877 in_r = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_r, nframes);
1879 EnterCriticalSection(&wwi->access_crst);
1881 if((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
1883 LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
1884 nframes_t jackFramesLeft = nframes;
1887 if(wwi->in_use == FALSE)
1889 /* do nothing if nothing is being recorded */
1894 TRACE("wwi.state == WINE_WS_PLAYING\n");
1896 while (lpWaveHdr && jackFramesLeft)
1898 DWORD waveHdrFramesLeft = (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded) / (sizeof(short) * wwi->format.wf.nChannels);
1899 DWORD numFrames = min (jackFramesLeft, waveHdrFramesLeft);
1901 TRACE ("dwBufferLength=(%lu) dwBytesRecorded=(%ld)\n", lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
1902 TRACE ("jackFramesLeft=(%u) waveHdrFramesLeft=(%lu)\n", jackFramesLeft, waveHdrFramesLeft);
1906 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded), in_l+(nframes-jackFramesLeft), numFrames, 1);
1909 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded),
1910 in_l+(nframes-jackFramesLeft), numFrames, 2);
1911 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded + sizeof(short)),
1912 in_r+(nframes-jackFramesLeft), numFrames, 2);
1915 lpWaveHdr->dwBytesRecorded += (numFrames * sizeof(short) * wwi->format.wf.nChannels );
1916 jackFramesLeft -= numFrames;
1918 if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
1920 /* must copy the value of next waveHdr, because we have no idea of what
1921 * will be done with the content of lpWaveHdr in callback
1923 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
1925 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1926 lpWaveHdr->dwFlags |= WHDR_DONE;
1928 TRACE("WaveHdr full. dwBytesRecorded=(%lu) dwFlags=(0x%lx)\n",lpWaveHdr->dwBytesRecorded,lpWaveHdr->dwFlags);
1930 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1932 lpWaveHdr = wwi->lpQueuePtr = lpNext;
1935 TRACE ("jackFramesLeft=(%u) lpWaveHdr=(%p)\n", jackFramesLeft, lpWaveHdr);
1936 if (jackFramesLeft > 0) { WARN("Record buffer ran out of WaveHdrs\n"); }
1939 LeaveCriticalSection(&wwi->access_crst);
1944 /******************************************************************
1945 * JACK_OpenWaveInDevice
1947 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels)
1951 char client_name[64];
1952 jack_port_t* in_port_l;
1953 jack_port_t* in_port_r = 0;
1954 jack_client_t* client;
1957 TRACE("creating jack client and setting up callbacks\n");
1959 if ((nChannels == 0) || (nChannels > 2)) {
1960 ERR ("nChannels = (%d), but we only support mono or stereo.\n", nChannels);
1965 /* see if this device is already open */
1968 /* if this device is already in use then it is bad for us to be in here */
1972 TRACE("using existing client\n");
1978 /* zero out the buffer pointer and the size of the buffer */
1979 wwi->sound_buffer = 0;
1980 wwi->buffer_size = 0;
1982 /* try to become a client of the JACK server */
1983 snprintf(client_name, sizeof(client_name), "wine_jack_in_%d", wwi->wDevID);
1984 TRACE("client name '%s'\n", client_name);
1985 if ((client = fp_jack_client_new (client_name)) == 0)
1987 /* jack has problems with shutting down clients, so lets */
1988 /* wait a short while and try once more before we give up */
1990 if ((client = fp_jack_client_new (client_name)) == 0)
1992 ERR("jack server not running?\n");
1996 wwi->client = client;
1998 /* tell the JACK server to call `JACK_wwi_callback()' whenever
1999 there is work to be done. */
2000 fp_jack_set_process_callback (client, JACK_callback_wwi, wwi);
2002 /* tell the JACK server to call `JACK_bufsize_wwi()' whenever
2003 the maximum number of frames that will be passed
2004 to `JACK_Callback()' changes */
2005 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwi, wwi);
2007 /* tell the JACK server to call `srate()' whenever
2008 the sample rate of the system changes. */
2009 fp_jack_set_sample_rate_callback (client, JACK_srate, wwi);
2011 /* tell the JACK server to call `jack_shutdown()' if
2012 it ever shuts down, either entirely, or if it
2013 just decides to stop calling us. */
2014 fp_jack_on_shutdown (client, JACK_shutdown_wwi, wwi);
2016 /* display the current sample rate. once the client is activated
2017 (see below), you should rely on your own sample rate
2018 callback (see above) for this value. */
2019 wwi->sample_rate = fp_jack_get_sample_rate(client);
2020 TRACE("engine sample rate: %lu\n", wwi->sample_rate);
2022 /* create the left and right channel output ports */
2023 /* jack's ports are all mono so for stereo you need two */
2024 in_port_l = fp_jack_port_register (client, "in_l",
2025 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
2026 wwi->in_port_l = in_port_l;
2027 TRACE("Created port. (%p)\n", in_port_l);
2031 in_port_r = fp_jack_port_register (client, "in_r",
2032 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
2033 TRACE("Created port. (%p)\n", in_port_r);
2035 wwi->in_port_r = in_port_r;
2038 wwi->in_use = TRUE; /* mark this device as in use since it now is ;-) */
2041 TRACE("activating client.\n");
2042 /* tell the JACK server that we are ready to roll */
2043 if (fp_jack_activate (client))
2045 ERR( "cannot activate client\n");
2048 TRACE("activated client.\n");
2049 /* figure out what the ports that we want to output on are */
2050 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
2051 /* this way works if names are changed */
2052 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
2054 /* display a trace of the output ports we found */
2055 for(i = 0; ports[i]; i++)
2057 TRACE("ports[%d] = '%s'\n", i, ports[i]);
2062 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsOutput'\n");
2065 /* connect the ports. Note: you can't do this before
2066 the client is activated (this may change in the future).
2068 /* we want to connect to two ports so we have stereo input ;-) */
2070 if(fp_jack_connect(client, ports[0], fp_jack_port_name(in_port_l)))
2072 ERR ("cannot connect to input port %d('%s')\n", 0, ports[0]);
2075 TRACE("Connected (%s)<->(%s)\n",ports[0],fp_jack_port_name(in_port_l));
2077 if ((nChannels == 2) && in_port_r) {
2078 if(fp_jack_connect(client, ports[1], fp_jack_port_name(in_port_r)))
2080 ERR ("cannot connect to input port %d('%s')\n", 1, ports[1]);
2083 TRACE("Connected (%s)<->(%s)\n",ports[1],fp_jack_port_name(in_port_r));
2085 free(ports); /* free the returned array of ports */
2087 /* if something failed we need to shut the client down and return 0 */
2091 JACK_CloseWaveInDevice(wwi, TRUE);
2093 JACK_CloseWaveInDevice(wwi);
2098 TRACE("return success.\n");
2099 return 1; /* return success */
2102 /**************************************************************************
2103 * widGetDevCaps [internal]
2105 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSA lpCaps, DWORD dwSize)
2107 TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
2109 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
2111 if (wDevID >= MAX_WAVEINDRV) {
2112 TRACE("MAX_WAVEINDRV reached !\n");
2113 return MMSYSERR_BADDEVICEID;
2116 memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
2117 return MMSYSERR_NOERROR;
2120 /**************************************************************************
2121 * widOpen [internal]
2123 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
2128 TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
2131 WARN("Invalid Parameter !\n");
2132 return MMSYSERR_INVALPARAM;
2134 if (wDevID >= MAX_WAVEINDRV) {
2135 TRACE ("MAX_WAVEINDRV reached !\n");
2136 return MMSYSERR_BADDEVICEID;
2140 if(WInDev[wDevID].client && WOutDev[wDevID].in_use)
2142 if(WInDev[wDevID].client)
2145 TRACE("device %d already allocated\n", wDevID);
2146 return MMSYSERR_ALLOCATED;
2149 /* Only the PCM format is supported so far...
2150 * Also we only support 16 bit mode.
2152 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
2153 lpDesc->lpFormat->nChannels == 0 ||
2154 lpDesc->lpFormat->nSamplesPerSec == 0 ||
2155 lpDesc->lpFormat->wBitsPerSample!=16)
2157 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
2158 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2159 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
2160 return WAVERR_BADFORMAT;
2163 if (dwFlags & WAVE_FORMAT_QUERY)
2165 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
2166 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2167 lpDesc->lpFormat->nSamplesPerSec);
2168 return MMSYSERR_NOERROR;
2171 wwi = &WInDev[wDevID];
2172 wwi->wDevID = wDevID;
2174 /* Set things up before we call JACK_OpenWaveOutDevice because */
2175 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
2176 /* even returns and we want to be initialized before then */
2177 wwi->state = WINE_WS_STOPPED; /* start in a stopped state */
2179 InitializeCriticalSection(&wwi->access_crst); /* initialize the critical section */
2180 EnterCriticalSection(&wwi->access_crst);
2182 /* open up jack ports for this device */
2183 if (!JACK_OpenWaveInDevice(&WInDev[wDevID], lpDesc->lpFormat->nChannels))
2185 ERR("JACK_OpenWaveInDevice(%d) failed\n", wDevID);
2186 LeaveCriticalSection(&wwi->access_crst);
2187 DeleteCriticalSection(&wwi->access_crst);
2188 return MMSYSERR_ERROR; /* return unspecified error */
2191 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
2193 wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
2195 memcpy(&wwi->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
2196 memcpy(&wwi->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
2198 LeaveCriticalSection(&wwi->access_crst);
2200 /* display the current wave format */
2201 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
2202 wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
2203 wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
2204 wwi->format.wf.nBlockAlign);
2206 /* make sure that we have the same sample rate in our audio stream */
2207 /* as we do in the jack server */
2208 if(wwi->format.wf.nSamplesPerSec != wwi->sample_rate)
2210 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
2211 wwi->sample_rate, wwi->format.wf.nSamplesPerSec);
2214 JACK_CloseWaveInDevice(wwi, FALSE); /* close this device, don't force the client to close */
2216 JACK_CloseWaveInDevice(wwi); /* close this device */
2218 DeleteCriticalSection(&wwi->access_crst);
2219 return WAVERR_BADFORMAT;
2222 /* check for an invalid number of bits per sample */
2223 if (wwi->format.wBitsPerSample == 0)
2225 WARN("Resetting zeroed wBitsPerSample\n");
2226 wwi->format.wBitsPerSample = 8 *
2227 (wwi->format.wf.nAvgBytesPerSec /
2228 wwi->format.wf.nSamplesPerSec) /
2229 wwi->format.wf.nChannels;
2232 TRACE("notify client.\n");
2233 EnterCriticalSection(&wwi->access_crst);
2234 retval = widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
2235 LeaveCriticalSection(&wwi->access_crst);
2239 /**************************************************************************
2240 * widClose [internal]
2242 static DWORD widClose(WORD wDevID)
2244 DWORD ret = MMSYSERR_NOERROR;
2247 TRACE("(%u);\n", wDevID);
2249 if (wDevID >= MAX_WAVEINDRV || !WInDev[wDevID].client)
2251 WARN("bad device ID !\n");
2252 return MMSYSERR_BADDEVICEID;
2255 wwi = &WInDev[wDevID];
2256 if (wwi->lpQueuePtr)
2258 WARN("buffers still playing !\n");
2259 ret = WAVERR_STILLPLAYING;
2262 /* sanity check: this should not happen since the device must have been reset before */
2263 if (wwi->lpQueuePtr) ERR("out of sync\n");
2265 wwi->state = WINE_WS_CLOSED; /* mark the device as closed */
2268 JACK_CloseWaveInDevice(wwi, FALSE); /* close the jack device, DO NOT force the client to close */
2270 JACK_CloseWaveInDevice(wwi); /* close the jack device */
2272 DeleteCriticalSection(&wwi->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
2274 ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
2280 /**************************************************************************
2281 * widAddBuffer [internal]
2283 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2285 WINE_WAVEIN* wwi = &WInDev[wDevID];
2287 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2289 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2290 WARN("can't do it !\n");
2291 return MMSYSERR_INVALHANDLE;
2293 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
2294 TRACE("never been prepared !\n");
2295 return WAVERR_UNPREPARED;
2297 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2298 TRACE("header already in use !\n");
2299 return WAVERR_STILLPLAYING;
2302 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
2303 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2304 lpWaveHdr->dwBytesRecorded = 0;
2305 lpWaveHdr->lpNext = NULL;
2307 EnterCriticalSection(&wwi->access_crst);
2308 /* insert buffer at end of queue */
2311 for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
2314 LeaveCriticalSection(&wwi->access_crst);
2316 return MMSYSERR_NOERROR;
2319 /**************************************************************************
2320 * widPrepare [internal]
2322 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2324 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2326 if (wDevID >= MAX_WAVEINDRV) return MMSYSERR_INVALHANDLE;
2328 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
2329 return WAVERR_STILLPLAYING;
2331 lpWaveHdr->dwFlags |= WHDR_PREPARED;
2332 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2333 lpWaveHdr->dwBytesRecorded = 0;
2334 lpWaveHdr->lpNext = NULL;
2336 return MMSYSERR_NOERROR;
2339 /**************************************************************************
2340 * widUnprepare [internal]
2342 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2344 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2345 if (wDevID >= MAX_WAVEINDRV) {
2346 WARN("bad device ID !\n");
2347 return MMSYSERR_INVALHANDLE;
2350 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2351 TRACE("Still playing...\n");
2352 return WAVERR_STILLPLAYING;
2355 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
2356 lpWaveHdr->dwFlags |= WHDR_DONE;
2358 return MMSYSERR_NOERROR;
2361 /**************************************************************************
2362 * widStart [internal]
2364 static DWORD widStart(WORD wDevID)
2366 TRACE("(%u);\n", wDevID);
2367 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2368 WARN("can't start recording !\n");
2369 return MMSYSERR_INVALHANDLE;
2372 WInDev[wDevID].state = WINE_WS_PLAYING;
2373 return MMSYSERR_NOERROR;
2376 /**************************************************************************
2377 * widStop [internal]
2379 static DWORD widStop(WORD wDevID)
2381 WINE_WAVEIN* wwi = &WInDev[wDevID];
2383 TRACE("(%u);\n", wDevID);
2384 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2385 WARN("can't stop !\n");
2386 return MMSYSERR_INVALHANDLE;
2389 if (wwi->state != WINE_WS_STOPPED)
2392 /* do something here to stop recording ??? */
2394 /* return current buffer to app */
2395 lpWaveHdr = wwi->lpQueuePtr;
2398 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
2399 TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2400 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2401 lpWaveHdr->dwFlags |= WHDR_DONE;
2402 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2403 wwi->lpQueuePtr = lpNext;
2406 wwi->state = WINE_WS_STOPPED;
2408 return MMSYSERR_NOERROR;
2411 /**************************************************************************
2412 * widReset [internal]
2414 static DWORD widReset(WORD wDevID)
2416 WINE_WAVEIN* wwi = &WInDev[wDevID];
2419 TRACE("(%u);\n", wDevID);
2420 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2421 WARN("can't reset !\n");
2422 return MMSYSERR_INVALHANDLE;
2425 wwi->state = WINE_WS_STOPPED;
2427 /* return all buffers to the app */
2428 for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
2429 TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2430 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2431 lpWaveHdr->dwFlags |= WHDR_DONE;
2433 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2435 wwi->lpQueuePtr = NULL;
2437 return MMSYSERR_NOERROR;
2440 /**************************************************************************
2441 * widGetNumDevs [internal]
2443 static DWORD widGetNumDevs(void)
2445 return MAX_WAVEINDRV;
2448 /**************************************************************************
2449 * widDevInterfaceSize [internal]
2451 static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
2453 TRACE("(%u, %p)\n", wDevID, dwParam1);
2456 *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2457 NULL, 0 ) * sizeof(WCHAR);
2458 return MMSYSERR_NOERROR;
2461 /**************************************************************************
2462 * widDevInterface [internal]
2464 static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
2466 if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2467 NULL, 0 ) * sizeof(WCHAR))
2469 MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
2470 dwParam1, dwParam2 / sizeof(WCHAR));
2471 return MMSYSERR_NOERROR;
2473 return MMSYSERR_INVALPARAM;
2476 /**************************************************************************
2477 * widMessage (WINEJACK.6)
2479 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2480 DWORD dwParam1, DWORD dwParam2)
2482 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
2483 wDevID, wMsg, dwUser, dwParam1, dwParam2);
2490 /* FIXME: Pretend this is supported */
2492 case WIDM_OPEN: return widOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
2493 case WIDM_CLOSE: return widClose (wDevID);
2494 case WIDM_ADDBUFFER: return widAddBuffer (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2495 case WIDM_PREPARE: return widPrepare (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2496 case WIDM_UNPREPARE: return widUnprepare (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2497 case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (LPWAVEINCAPSA)dwParam1, dwParam2);
2498 case WIDM_GETNUMDEVS: return widGetNumDevs();
2499 case WIDM_RESET: return widReset (wDevID);
2500 case WIDM_START: return widStart (wDevID);
2501 case WIDM_STOP: return widStop (wDevID);
2502 case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
2503 case DRV_QUERYDEVICEINTERFACE: return widDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
2505 FIXME("unknown message %d!\n", wMsg);
2508 return MMSYSERR_NOTSUPPORTED;
2511 #else /* !HAVE_JACK_JACK_H */
2513 /**************************************************************************
2514 * widMessage (WINEJACK.6)
2516 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2517 DWORD dwParam1, DWORD dwParam2)
2519 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2520 return MMSYSERR_NOTENABLED;
2523 /**************************************************************************
2524 * wodMessage (WINEJACK.7)
2526 DWORD WINAPI JACK_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2527 DWORD dwParam1, DWORD dwParam2)
2529 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2530 return MMSYSERR_NOTENABLED;
2533 #endif /* HAVE_JACK_JACK_H */