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;
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 */
138 BOOL in_use; /* TRUE if this device is in use */
142 unsigned long buffer_size;
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;
166 WAVEOPENDESC waveDesc;
168 PCMWAVEFORMAT format;
169 LPWAVEHDR lpQueuePtr;
170 DWORD dwTotalRecorded;
172 BOOL bTriggerSupport;
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 */
181 BOOL in_use; /* TRUE if this device is in use */
185 unsigned long buffer_size;
187 /* synchronization stuff */
188 CRITICAL_SECTION access_crst;
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);
205 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client);
207 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo);
211 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client);
213 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi);
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;
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)
250 if(nChannels == 2) 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 !!! */
270 *dst = (*src) / SAMPLE_MAX_16BIT;
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 !!! */
287 *dst = (*src) * SAMPLE_MAX_16BIT;
288 /* TRACE("src=(%.8f,%p) dst=(%d,%p)\n",*src,src,*dst,dst); */
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 !!! */
306 /******************************************************************
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
312 int JACK_callback_wwo (nframes_t nframes, void *arg)
316 WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg;
318 TRACE("wDevID: %u, nframes %u state=%u\n", wwo->wDevID, nframes,wwo->state);
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;
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);
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));
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*/
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);
442 /******************************************************************
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);
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);
484 LeaveCriticalSection(&wwo->access_crst);
490 /******************************************************************
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);
502 /******************************************************************
505 int JACK_srate (nframes_t nframes, void *arg)
507 TRACE("the sample rate is now %u/sec\n", nframes);
512 /******************************************************************
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 /******************************************************************
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)
560 char client_name[64];
561 jack_port_t* out_port_l;
562 jack_port_t* out_port_r;
563 jack_client_t* client;
566 TRACE("creating jack client and setting up callbacks\n");
569 /* see if this device is already open */
572 /* if this device is already in use then it is bad for us to be in here */
576 TRACE("using existing client\n");
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 */
594 if ((client = fp_jack_client_new (client_name)) == 0)
596 ERR("jack server not running?\n");
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;
641 wwo->in_use = TRUE; /* mark this device as in use since it now is ;-) */
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");
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]);
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]);
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]);
688 free(ports); /* free the returned array of ports */
690 /* if something failed we need to shut the client down and return 0 */
694 JACK_CloseWaveOutDevice(wwo, TRUE);
696 JACK_CloseWaveOutDevice(wwo);
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)
712 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo, BOOL close_client)
714 static void JACK_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
718 TRACE("wDevID: %d, close_client (wwo): %d\n", wwo->wDevID, close_client);
720 TRACE("wDevID: %d\n", wwo->wDevID);
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);
739 EnterCriticalSection(&wwo->access_crst);
740 TRACE("setting in_use to FALSE\n");
742 LeaveCriticalSection(&wwo->access_crst);
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)
755 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client)
757 static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi)
761 TRACE("wDevID: %d, close_client (wwi): %d\n", wwi->wDevID, close_client);
763 TRACE("wDevID: %d\n", wwi->wDevID);
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);
782 EnterCriticalSection(&wwi->access_crst);
783 TRACE("setting in_use to FALSE\n");
785 LeaveCriticalSection(&wwi->access_crst);
790 /******************************************************************
795 LONG JACK_WaveRelease(void)
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)
808 JACK_CloseWaveOutDevice(&WOutDev[iDevice], TRUE); /* close the device, FORCE the client to close */
810 JACK_CloseWaveOutDevice(&WOutDev[iDevice]); /* close the device, FORCE the client to close */
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)
825 JACK_CloseWaveInDevice(&WInDev[iDevice], TRUE); /* close the device, FORCE the client to close */
827 JACK_CloseWaveInDevice(&WInDev[iDevice]); /* close the device, FORCE the client to close */
829 DeleteCriticalSection(&(WInDev[iDevice].access_crst)); /* delete the critical section */
833 TRACE("returning 1\n");
838 /******************************************************************
841 * Initialize internal structures from JACK server info
843 LONG JACK_WaveInit(void)
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);
868 /* start with output device */
870 for (i = 0; i < MAX_WAVEOUTDRV; ++i)
872 WOutDev[i].client = 0; /* initialize the client to 0 */
875 WOutDev[i].in_use = FALSE;
876 WInDev[i].in_use = FALSE;
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)
886 WOutDev[i].caps.wMid = 0x0002;
887 WOutDev[i].caps.wPid = 0x0104;
888 strcpy(WOutDev[i].caps.szPname, "SB16 Wave Out");
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");
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)
928 WInDev[i].caps.wMid = 0x0002;
929 WInDev[i].caps.wPid = 0x0104;
930 strcpy(WInDev[i].caps.szPname, "SB16 Wave In");
932 WInDev[i].caps.wMid = 0x00FF;
933 WInDev[i].caps.wPid = 0x0001;
934 strcpy(WInDev[i].caps.szPname,"CS4236/37/38");
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 */
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);
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);
983 if (wwo->wFlags != DCB_NULL &&
984 !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags,
985 (HDRVR)wwo->waveDesc.hWave, wMsg, wwo->waveDesc.dwInstance,
988 WARN("can't notify client !\n");
989 return MMSYSERR_ERROR;
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;
1014 LeaveCriticalSection(&wwo->access_crst);
1018 if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)
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);
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;
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
1070 lpWaveHdr = lpWaveHdr->lpNext;
1072 wwo->lpLoopPtr = NULL;
1073 wodHelper_BeginWaveHdr(wwo, lpWaveHdr);
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);
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;
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) &&
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);
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);
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 */
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 !!! */
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)
1213 TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1216 WARN("Invalid Parameter !\n");
1217 return MMSYSERR_INVALPARAM;
1219 if (wDevID >= MAX_WAVEOUTDRV) {
1220 TRACE("MAX_WAVOUTDRV reached !\n");
1221 return MMSYSERR_BADDEVICEID;
1225 if(WOutDev[wDevID].client && WOutDev[wDevID].in_use)
1227 if(WOutDev[wDevID].client)
1230 TRACE("device %d already allocated\n", wDevID);
1231 return MMSYSERR_ALLOCATED;
1234 /* Only the PCM format is supported so far...
1235 * Also we only support 16 bit mode.
1237 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
1238 lpDesc->lpFormat->nChannels == 0 ||
1239 lpDesc->lpFormat->nSamplesPerSec == 0 ||
1240 lpDesc->lpFormat->wBitsPerSample != 16)
1242 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
1243 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1244 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
1245 return WAVERR_BADFORMAT;
1248 if (dwFlags & WAVE_FORMAT_QUERY)
1250 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
1251 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
1252 lpDesc->lpFormat->nSamplesPerSec);
1253 return MMSYSERR_NOERROR;
1256 wwo = &WOutDev[wDevID];
1257 wwo->wDevID = wDevID;
1259 /* Set things up before we call JACK_OpenWaveOutDevice because */
1260 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
1261 /* even returns and we want to be initialized before then */
1262 wwo->state = WINE_WS_STOPPED; /* start in a stopped state */
1263 wwo->dwPlayedTotal = 0; /* zero out these totals */
1264 wwo->dwWrittenTotal = 0;
1265 wwo->bytesInJack = 0;
1266 wwo->tickCountMS = 0;
1268 /* Initialize volume to full level */
1269 wwo->volume_left = 100;
1270 wwo->volume_right = 100;
1272 InitializeCriticalSection(&wwo->access_crst); /* initialize the critical section */
1273 EnterCriticalSection(&wwo->access_crst);
1275 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
1277 wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1279 memcpy(&wwo->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1280 memcpy(&wwo->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1282 /* open up jack ports for this device */
1283 if (!JACK_OpenWaveOutDevice(&WOutDev[wDevID]))
1285 ERR("JACK_OpenWaveOutDevice(%d) failed\n", wDevID);
1286 LeaveCriticalSection(&wwo->access_crst);
1287 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1288 return MMSYSERR_ERROR; /* return unspecified error */
1291 LeaveCriticalSection(&wwo->access_crst);
1293 /* display the current wave format */
1294 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
1295 wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
1296 wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1297 wwo->format.wf.nBlockAlign);
1299 /* make sure that we have the same sample rate in our audio stream */
1300 /* as we do in the jack server */
1301 if(wwo->format.wf.nSamplesPerSec != wwo->sample_rate)
1303 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
1304 wwo->sample_rate, wwo->format.wf.nSamplesPerSec);
1307 JACK_CloseWaveOutDevice(wwo, FALSE); /* close this device, don't force the client to close */
1309 JACK_CloseWaveOutDevice(wwo); /* close this device */
1311 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1312 return WAVERR_BADFORMAT;
1315 /* check for an invalid number of bits per sample */
1316 if (wwo->format.wBitsPerSample == 0)
1318 WARN("Resetting zeroed wBitsPerSample\n");
1319 wwo->format.wBitsPerSample = 8 *
1320 (wwo->format.wf.nAvgBytesPerSec /
1321 wwo->format.wf.nSamplesPerSec) /
1322 wwo->format.wf.nChannels;
1325 EnterCriticalSection(&wwo->access_crst);
1326 retval = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
1327 LeaveCriticalSection(&wwo->access_crst);
1332 /**************************************************************************
1333 * wodClose [internal]
1335 static DWORD wodClose(WORD wDevID)
1337 DWORD ret = MMSYSERR_NOERROR;
1340 TRACE("(%u);\n", wDevID);
1342 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1344 WARN("bad device ID !\n");
1345 return MMSYSERR_BADDEVICEID;
1348 wwo = &WOutDev[wDevID];
1349 if (wwo->lpQueuePtr)
1351 WARN("buffers still playing !\n");
1352 ret = WAVERR_STILLPLAYING;
1355 /* sanity check: this should not happen since the device must have been reset before */
1356 if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
1358 wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
1361 JACK_CloseWaveOutDevice(wwo, FALSE); /* close the jack device, DO NOT force the client to close */
1363 JACK_CloseWaveOutDevice(wwo); /* close the jack device */
1365 DeleteCriticalSection(&wwo->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
1367 ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
1374 /**************************************************************************
1375 * wodWrite [internal]
1378 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1383 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1385 /* first, do the sanity checks... */
1386 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1388 WARN("bad dev ID !\n");
1389 return MMSYSERR_BADDEVICEID;
1392 wwo = &WOutDev[wDevID];
1394 if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
1396 TRACE("unprepared\n");
1397 return WAVERR_UNPREPARED;
1400 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1402 TRACE("still playing\n");
1403 return WAVERR_STILLPLAYING;
1406 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1407 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1408 lpWaveHdr->lpNext = 0;
1410 EnterCriticalSection(&wwo->access_crst);
1412 /* insert buffer at the end of queue */
1413 for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
1416 if (!wwo->lpPlayPtr)
1417 wodHelper_BeginWaveHdr(wwo,lpWaveHdr);
1418 if (wwo->state == WINE_WS_STOPPED)
1419 wwo->state = WINE_WS_PLAYING;
1420 LeaveCriticalSection(&wwo->access_crst);
1422 return MMSYSERR_NOERROR;
1425 /**************************************************************************
1426 * wodPrepare [internal]
1428 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1430 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1432 if (wDevID >= MAX_WAVEOUTDRV)
1434 WARN("bad device ID !\n");
1435 return MMSYSERR_BADDEVICEID;
1438 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1439 return WAVERR_STILLPLAYING;
1441 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1442 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1443 return MMSYSERR_NOERROR;
1446 /**************************************************************************
1447 * wodUnprepare [internal]
1449 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1451 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1453 if (wDevID >= MAX_WAVEOUTDRV)
1455 WARN("bad device ID !\n");
1456 return MMSYSERR_BADDEVICEID;
1459 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1460 return WAVERR_STILLPLAYING;
1462 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1463 lpWaveHdr->dwFlags |= WHDR_DONE;
1465 return MMSYSERR_NOERROR;
1468 /**************************************************************************
1469 * wodPause [internal]
1471 static DWORD wodPause(WORD wDevID)
1473 TRACE("(%u);!\n", wDevID);
1475 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1477 WARN("bad device ID !\n");
1478 return MMSYSERR_BADDEVICEID;
1481 TRACE("[3-PAUSING]\n");
1483 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1484 wodHelper_Reset(&WOutDev[wDevID], FALSE);
1485 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1487 return MMSYSERR_NOERROR;
1490 /**************************************************************************
1491 * wodRestart [internal]
1493 static DWORD wodRestart(WORD wDevID)
1495 TRACE("(%u);\n", wDevID);
1497 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1499 WARN("bad device ID !\n");
1500 return MMSYSERR_BADDEVICEID;
1503 if (WOutDev[wDevID].state == WINE_WS_PAUSED)
1505 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1506 WOutDev[wDevID].state = WINE_WS_PLAYING;
1507 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1510 return MMSYSERR_NOERROR;
1513 /**************************************************************************
1514 * wodReset [internal]
1516 static DWORD wodReset(WORD wDevID)
1518 TRACE("(%u);\n", wDevID);
1520 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1522 WARN("bad device ID !\n");
1523 return MMSYSERR_BADDEVICEID;
1526 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1527 wodHelper_Reset(&WOutDev[wDevID], TRUE);
1528 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1530 return MMSYSERR_NOERROR;
1533 /**************************************************************************
1534 * wodGetPosition [internal]
1536 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1543 TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1545 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1547 WARN("bad device ID !\n");
1548 return MMSYSERR_BADDEVICEID;
1551 /* if null pointer to time structure return error */
1552 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1554 wwo = &WOutDev[wDevID];
1556 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1557 val = wwo->dwPlayedTotal;
1558 elapsedMS = GetTickCount() - wwo->tickCountMS;
1559 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1561 /* account for the bytes played since the last JACK_Callback() */
1562 val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
1564 TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
1565 lpTime->wType, wwo->format.wBitsPerSample,
1566 wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
1567 wwo->format.wf.nAvgBytesPerSec);
1568 TRACE("dwPlayedTotal=%lu\n", val);
1570 switch (lpTime->wType) {
1573 TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
1576 lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
1577 TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
1580 time = val / (wwo->format.wf.nAvgBytesPerSec / 1000);
1581 lpTime->u.smpte.hour = time / 108000;
1582 time -= lpTime->u.smpte.hour * 108000;
1583 lpTime->u.smpte.min = time / 1800;
1584 time -= lpTime->u.smpte.min * 1800;
1585 lpTime->u.smpte.sec = time / 30;
1586 time -= lpTime->u.smpte.sec * 30;
1587 lpTime->u.smpte.frame = time;
1588 lpTime->u.smpte.fps = 30;
1589 TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1590 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1591 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1594 FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
1595 lpTime->wType = TIME_MS;
1597 lpTime->u.ms = val / (wwo->format.wf.nAvgBytesPerSec / 1000);
1598 TRACE("TIME_MS=%lu\n", lpTime->u.ms);
1601 return MMSYSERR_NOERROR;
1604 /**************************************************************************
1605 * wodBreakLoop [internal]
1607 static DWORD wodBreakLoop(WORD wDevID)
1609 TRACE("(%u);\n", wDevID);
1611 if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
1613 WARN("bad device ID !\n");
1614 return MMSYSERR_BADDEVICEID;
1617 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1619 if (WOutDev[wDevID].state == WINE_WS_PLAYING && WOutDev[wDevID].lpLoopPtr != NULL)
1621 /* ensure exit at end of current loop */
1622 WOutDev[wDevID].dwLoops = 1;
1625 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1627 return MMSYSERR_NOERROR;
1630 /**************************************************************************
1631 * wodGetVolume [internal]
1633 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1637 left = WOutDev[wDevID].volume_left;
1638 right = WOutDev[wDevID].volume_right;
1640 TRACE("(%u, %p);\n", wDevID, lpdwVol);
1642 *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
1645 return MMSYSERR_NOERROR;
1648 /**************************************************************************
1649 * wodSetVolume [internal]
1651 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1655 left = (LOWORD(dwParam) * 100) / 0xFFFFl;
1656 right = (HIWORD(dwParam) * 100) / 0xFFFFl;
1658 TRACE("(%u, %08lX);\n", wDevID, dwParam);
1660 EnterCriticalSection(&(WOutDev[wDevID].access_crst));
1662 WOutDev[wDevID].volume_left = left;
1663 WOutDev[wDevID].volume_right = right;
1665 LeaveCriticalSection(&(WOutDev[wDevID].access_crst));
1667 return MMSYSERR_NOERROR;
1670 /**************************************************************************
1671 * wodGetNumDevs [internal]
1673 static DWORD wodGetNumDevs(void)
1675 return MAX_WAVEOUTDRV;
1678 /**************************************************************************
1679 * wodMessage (WINEJACK.7)
1681 DWORD WINAPI JACK_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
1682 DWORD dwParam1, DWORD dwParam2)
1684 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
1685 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1689 TRACE("DRVM_INIT\n");
1690 return JACK_WaveInit();
1692 TRACE("DRVM_EXIT\n");
1693 return JACK_WaveRelease();
1695 /* FIXME: Pretend this is supported */
1696 TRACE("DRVM_ENABLE\n");
1699 /* FIXME: Pretend this is supported */
1700 TRACE("DRVM_DISABLE\n");
1702 case WODM_OPEN: return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1703 case WODM_CLOSE: return wodClose(wDevID);
1704 case WODM_WRITE: return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1705 case WODM_PAUSE: return wodPause(wDevID);
1706 case WODM_GETPOS: return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1707 case WODM_BREAKLOOP: return wodBreakLoop(wDevID);
1708 case WODM_PREPARE: return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1709 case WODM_UNPREPARE: return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1710 case WODM_GETDEVCAPS: return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSA)dwParam1, dwParam2);
1711 case WODM_GETNUMDEVS: return wodGetNumDevs();
1712 case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED;
1713 case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED;
1714 case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1715 case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
1716 case WODM_GETVOLUME: return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1717 case WODM_SETVOLUME: return wodSetVolume(wDevID, dwParam1);
1718 case WODM_RESTART: return wodRestart(wDevID);
1719 case WODM_RESET: return wodReset(wDevID);
1721 case DRV_QUERYDSOUNDIFACE: return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1);
1722 case DRV_QUERYDSOUNDDESC: return wodDsDesc(wDevID, (PDSDRIVERDESC)dwParam1);
1723 case DRV_QUERYDSOUNDGUID: return wodDsGuid(wDevID, (LPGUID)dwParam1);
1725 FIXME("unknown message %d!\n", wMsg);
1727 return MMSYSERR_NOTSUPPORTED;
1730 /*======================================================================*
1731 * Low level DSOUND implementation *
1732 *======================================================================*/
1734 typedef struct IDsDriverImpl IDsDriverImpl;
1735 typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;
1737 struct IDsDriverImpl
1739 /* IUnknown fields */
1740 ICOM_VFIELD(IDsDriver);
1742 /* IDsDriverImpl fields */
1744 IDsDriverBufferImpl*primary;
1747 struct IDsDriverBufferImpl
1749 /* IUnknown fields */
1750 ICOM_VFIELD(IDsDriverBuffer);
1752 /* IDsDriverBufferImpl fields */
1757 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
1759 /* we can't perform memory mapping as we don't have a file stream
1760 interface with jack like we do with oss */
1761 MESSAGE("This sound card's driver does not support direct access\n");
1762 MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
1763 return MMSYSERR_NOTSUPPORTED;
1766 static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
1768 memset(desc, 0, sizeof(*desc));
1769 strcpy(desc->szDesc, "Wine jack DirectSound Driver");
1770 strcpy(desc->szDrvName, "winejack.drv");
1771 return MMSYSERR_NOERROR;
1774 static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid)
1776 memcpy(pGuid, &DSDEVID_DefaultPlayback, sizeof(GUID));
1777 return MMSYSERR_NOERROR;
1780 /*======================================================================*
1781 * Low level WAVE IN implementation *
1782 *======================================================================*/
1784 /**************************************************************************
1785 * widNotifyClient [internal]
1787 static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
1789 TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
1795 if (wwi->wFlags != DCB_NULL &&
1796 !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
1797 (HDRVR)wwi->waveDesc.hWave, wMsg, wwi->waveDesc.dwInstance,
1798 dwParam1, dwParam2))
1800 WARN("can't notify client !\n");
1801 return MMSYSERR_ERROR;
1805 FIXME("Unknown callback message %u\n", wMsg);
1806 return MMSYSERR_INVALPARAM;
1808 return MMSYSERR_NOERROR;
1811 /******************************************************************
1814 /* everytime the jack server wants something from us it calls this
1816 int JACK_callback_wwi (nframes_t nframes, void *arg)
1820 WINE_WAVEIN* wwi = (WINE_WAVEIN*)arg;
1822 TRACE("wDevID: %u, nframes %u\n", wwi->wDevID, nframes);
1825 ERR("client is closed, this is weird...\n");
1827 in_l = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_l, nframes);
1830 in_r = (sample_t *) fp_jack_port_get_buffer(wwi->in_port_r, nframes);
1832 EnterCriticalSection(&wwi->access_crst);
1834 if((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
1836 LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
1837 nframes_t jackFramesLeft = nframes;
1840 if(wwi->in_use == FALSE)
1842 /* do nothing if nothing is being recorded */
1847 TRACE("wwi.state == WINE_WS_PLAYING\n");
1849 while (lpWaveHdr && jackFramesLeft)
1851 DWORD waveHdrFramesLeft = (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded) / (sizeof(short) * wwi->format.wf.nChannels);
1852 DWORD numFrames = min (jackFramesLeft, waveHdrFramesLeft);
1854 TRACE ("dwBufferLength=(%lu) dwBytesRecorded=(%ld)\n", lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
1855 TRACE ("jackFramesLeft=(%u) waveHdrFramesLeft=(%lu)\n", jackFramesLeft, waveHdrFramesLeft);
1859 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded), in_l+(nframes-jackFramesLeft), numFrames, 1);
1862 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded),
1863 in_l+(nframes-jackFramesLeft), numFrames, 2);
1864 sample_move_s16_d16((short *)((char *)lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded + sizeof(short)),
1865 in_r+(nframes-jackFramesLeft), numFrames, 2);
1868 lpWaveHdr->dwBytesRecorded += (numFrames * sizeof(short) * wwi->format.wf.nChannels );
1869 jackFramesLeft -= numFrames;
1871 if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
1873 /* must copy the value of next waveHdr, because we have no idea of what
1874 * will be done with the content of lpWaveHdr in callback
1876 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
1878 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1879 lpWaveHdr->dwFlags |= WHDR_DONE;
1881 TRACE("WaveHdr full. dwBytesRecorded=(%lu) dwFlags=(0x%lx)\n",lpWaveHdr->dwBytesRecorded,lpWaveHdr->dwFlags);
1883 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
1885 lpWaveHdr = wwi->lpQueuePtr = lpNext;
1888 TRACE ("jackFramesLeft=(%u) lpWaveHdr=(%p)\n", jackFramesLeft, lpWaveHdr);
1889 if (jackFramesLeft > 0) { WARN("Record buffer ran out of WaveHdrs\n"); }
1892 LeaveCriticalSection(&wwi->access_crst);
1897 /******************************************************************
1898 * JACK_OpenWaveInDevice
1900 static int JACK_OpenWaveInDevice(WINE_WAVEIN* wwi, WORD nChannels)
1904 char client_name[64];
1905 jack_port_t* in_port_l;
1906 jack_port_t* in_port_r = 0;
1907 jack_client_t* client;
1910 TRACE("creating jack client and setting up callbacks\n");
1912 if ((nChannels == 0) || (nChannels > 2)) {
1913 ERR ("nChannels = (%d), but we only support mono or stereo.\n", nChannels);
1918 /* see if this device is already open */
1921 /* if this device is already in use then it is bad for us to be in here */
1925 TRACE("using existing client\n");
1931 /* zero out the buffer pointer and the size of the buffer */
1932 wwi->sound_buffer = 0;
1933 wwi->buffer_size = 0;
1935 /* try to become a client of the JACK server */
1936 snprintf(client_name, sizeof(client_name), "wine_jack_in_%d", wwi->wDevID);
1937 TRACE("client name '%s'\n", client_name);
1938 if ((client = fp_jack_client_new (client_name)) == 0)
1940 /* jack has problems with shutting down clients, so lets */
1941 /* wait a short while and try once more before we give up */
1943 if ((client = fp_jack_client_new (client_name)) == 0)
1945 ERR("jack server not running?\n");
1949 wwi->client = client;
1951 /* tell the JACK server to call `JACK_wwi_callback()' whenever
1952 there is work to be done. */
1953 fp_jack_set_process_callback (client, JACK_callback_wwi, wwi);
1955 /* tell the JACK server to call `JACK_bufsize_wwi()' whenever
1956 the maximum number of frames that will be passed
1957 to `JACK_Callback()' changes */
1958 fp_jack_set_buffer_size_callback (client, JACK_bufsize_wwi, wwi);
1960 /* tell the JACK server to call `srate()' whenever
1961 the sample rate of the system changes. */
1962 fp_jack_set_sample_rate_callback (client, JACK_srate, wwi);
1964 /* tell the JACK server to call `jack_shutdown()' if
1965 it ever shuts down, either entirely, or if it
1966 just decides to stop calling us. */
1967 fp_jack_on_shutdown (client, JACK_shutdown_wwi, wwi);
1969 /* display the current sample rate. once the client is activated
1970 (see below), you should rely on your own sample rate
1971 callback (see above) for this value. */
1972 wwi->sample_rate = fp_jack_get_sample_rate(client);
1973 TRACE("engine sample rate: %lu\n", wwi->sample_rate);
1975 /* create the left and right channel output ports */
1976 /* jack's ports are all mono so for stereo you need two */
1977 in_port_l = fp_jack_port_register (client, "in_l",
1978 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
1979 wwi->in_port_l = in_port_l;
1980 TRACE("Created port. (%p)\n", in_port_l);
1984 in_port_r = fp_jack_port_register (client, "in_r",
1985 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
1986 TRACE("Created port. (%p)\n", in_port_r);
1988 wwi->in_port_r = in_port_r;
1991 wwi->in_use = TRUE; /* mark this device as in use since it now is ;-) */
1994 TRACE("activating client.\n");
1995 /* tell the JACK server that we are ready to roll */
1996 if (fp_jack_activate (client))
1998 ERR( "cannot activate client\n");
2001 TRACE("activated client.\n");
2002 /* figure out what the ports that we want to output on are */
2003 /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */
2004 /* this way works if names are changed */
2005 ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
2007 /* display a trace of the output ports we found */
2008 for(i = 0; ports[i]; i++)
2010 TRACE("ports[%d] = '%s'\n", i, ports[i]);
2015 ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsOutput'\n");
2018 /* connect the ports. Note: you can't do this before
2019 the client is activated (this may change in the future).
2021 /* we want to connect to two ports so we have stereo input ;-) */
2023 if(fp_jack_connect(client, ports[0], fp_jack_port_name(in_port_l)))
2025 ERR ("cannot connect to input port %d('%s')\n", 0, ports[0]);
2028 TRACE("Connected (%s)<->(%s)\n",ports[0],fp_jack_port_name(in_port_l));
2030 if ((nChannels == 2) && in_port_r) {
2031 if(fp_jack_connect(client, ports[1], fp_jack_port_name(in_port_r)))
2033 ERR ("cannot connect to input port %d('%s')\n", 1, ports[1]);
2036 TRACE("Connected (%s)<->(%s)\n",ports[1],fp_jack_port_name(in_port_r));
2038 free(ports); /* free the returned array of ports */
2040 /* if something failed we need to shut the client down and return 0 */
2044 JACK_CloseWaveInDevice(wwi, TRUE);
2046 JACK_CloseWaveInDevice(wwi);
2051 TRACE("return success.\n");
2052 return 1; /* return success */
2055 /**************************************************************************
2056 * widGetDevCaps [internal]
2058 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSA lpCaps, DWORD dwSize)
2060 TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
2062 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
2064 if (wDevID >= MAX_WAVEINDRV) {
2065 TRACE("MAX_WAVEINDRV reached !\n");
2066 return MMSYSERR_BADDEVICEID;
2069 memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
2070 return MMSYSERR_NOERROR;
2073 /**************************************************************************
2074 * widOpen [internal]
2076 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
2081 TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
2084 WARN("Invalid Parameter !\n");
2085 return MMSYSERR_INVALPARAM;
2087 if (wDevID >= MAX_WAVEINDRV) {
2088 TRACE ("MAX_WAVEINDRV reached !\n");
2089 return MMSYSERR_BADDEVICEID;
2093 if(WInDev[wDevID].client && WOutDev[wDevID].in_use)
2095 if(WInDev[wDevID].client)
2098 TRACE("device %d already allocated\n", wDevID);
2099 return MMSYSERR_ALLOCATED;
2102 /* Only the PCM format is supported so far...
2103 * Also we only support 16 bit mode.
2105 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
2106 lpDesc->lpFormat->nChannels == 0 ||
2107 lpDesc->lpFormat->nSamplesPerSec == 0 ||
2108 lpDesc->lpFormat->wBitsPerSample!=16)
2110 WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld wBitsPerSample=%d !\n",
2111 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2112 lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
2113 return WAVERR_BADFORMAT;
2116 if (dwFlags & WAVE_FORMAT_QUERY)
2118 TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
2119 lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
2120 lpDesc->lpFormat->nSamplesPerSec);
2121 return MMSYSERR_NOERROR;
2124 wwi = &WInDev[wDevID];
2125 wwi->wDevID = wDevID;
2127 /* Set things up before we call JACK_OpenWaveOutDevice because */
2128 /* we will start getting callbacks before JACK_OpenWaveOutDevice */
2129 /* even returns and we want to be initialized before then */
2130 wwi->state = WINE_WS_STOPPED; /* start in a stopped state */
2132 InitializeCriticalSection(&wwi->access_crst); /* initialize the critical section */
2133 EnterCriticalSection(&wwi->access_crst);
2135 /* open up jack ports for this device */
2136 if (!JACK_OpenWaveInDevice(&WInDev[wDevID], lpDesc->lpFormat->nChannels))
2138 ERR("JACK_OpenWaveInDevice(%d) failed\n", wDevID);
2139 LeaveCriticalSection(&wwi->access_crst);
2140 DeleteCriticalSection(&wwi->access_crst);
2141 return MMSYSERR_ERROR; /* return unspecified error */
2144 dwFlags &= ~WAVE_DIRECTSOUND; /* direct sound not supported, ignore the flag */
2146 wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
2148 memcpy(&wwi->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
2149 memcpy(&wwi->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
2151 LeaveCriticalSection(&wwi->access_crst);
2153 /* display the current wave format */
2154 TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
2155 wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
2156 wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
2157 wwi->format.wf.nBlockAlign);
2159 /* make sure that we have the same sample rate in our audio stream */
2160 /* as we do in the jack server */
2161 if(wwi->format.wf.nSamplesPerSec != wwi->sample_rate)
2163 TRACE("error: jack server sample rate is '%ld', wave sample rate is '%ld'\n",
2164 wwi->sample_rate, wwi->format.wf.nSamplesPerSec);
2167 JACK_CloseWaveInDevice(wwi, FALSE); /* close this device, don't force the client to close */
2169 JACK_CloseWaveInDevice(wwi); /* close this device */
2171 DeleteCriticalSection(&wwi->access_crst);
2172 return WAVERR_BADFORMAT;
2175 /* check for an invalid number of bits per sample */
2176 if (wwi->format.wBitsPerSample == 0)
2178 WARN("Resetting zeroed wBitsPerSample\n");
2179 wwi->format.wBitsPerSample = 8 *
2180 (wwi->format.wf.nAvgBytesPerSec /
2181 wwi->format.wf.nSamplesPerSec) /
2182 wwi->format.wf.nChannels;
2185 TRACE("notify client.\n");
2186 EnterCriticalSection(&wwi->access_crst);
2187 retval = widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
2188 LeaveCriticalSection(&wwi->access_crst);
2192 /**************************************************************************
2193 * widClose [internal]
2195 static DWORD widClose(WORD wDevID)
2197 DWORD ret = MMSYSERR_NOERROR;
2200 TRACE("(%u);\n", wDevID);
2202 if (wDevID >= MAX_WAVEINDRV || !WInDev[wDevID].client)
2204 WARN("bad device ID !\n");
2205 return MMSYSERR_BADDEVICEID;
2208 wwi = &WInDev[wDevID];
2209 if (wwi->lpQueuePtr)
2211 WARN("buffers still playing !\n");
2212 ret = WAVERR_STILLPLAYING;
2215 /* sanity check: this should not happen since the device must have been reset before */
2216 if (wwi->lpQueuePtr) ERR("out of sync\n");
2218 wwi->state = WINE_WS_CLOSED; /* mark the device as closed */
2221 JACK_CloseWaveInDevice(wwi, FALSE); /* close the jack device, DO NOT force the client to close */
2223 JACK_CloseWaveInDevice(wwi); /* close the jack device */
2225 DeleteCriticalSection(&wwi->access_crst); /* delete the critical section so we can initialize it again from wodOpen() */
2227 ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
2233 /**************************************************************************
2234 * widAddBuffer [internal]
2236 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2238 WINE_WAVEIN* wwi = &WInDev[wDevID];
2240 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2242 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2243 WARN("can't do it !\n");
2244 return MMSYSERR_INVALHANDLE;
2246 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
2247 TRACE("never been prepared !\n");
2248 return WAVERR_UNPREPARED;
2250 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2251 TRACE("header already in use !\n");
2252 return WAVERR_STILLPLAYING;
2255 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
2256 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2257 lpWaveHdr->dwBytesRecorded = 0;
2258 lpWaveHdr->lpNext = NULL;
2260 EnterCriticalSection(&wwi->access_crst);
2261 /* insert buffer at end of queue */
2264 for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
2267 LeaveCriticalSection(&wwi->access_crst);
2269 return MMSYSERR_NOERROR;
2272 /**************************************************************************
2273 * widPrepare [internal]
2275 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2277 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2279 if (wDevID >= MAX_WAVEINDRV) return MMSYSERR_INVALHANDLE;
2281 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
2282 return WAVERR_STILLPLAYING;
2284 lpWaveHdr->dwFlags |= WHDR_PREPARED;
2285 lpWaveHdr->dwFlags &= ~WHDR_DONE;
2286 lpWaveHdr->dwBytesRecorded = 0;
2287 lpWaveHdr->lpNext = NULL;
2289 return MMSYSERR_NOERROR;
2292 /**************************************************************************
2293 * widUnprepare [internal]
2295 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
2297 TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
2298 if (wDevID >= MAX_WAVEINDRV) {
2299 WARN("bad device ID !\n");
2300 return MMSYSERR_INVALHANDLE;
2303 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
2304 TRACE("Still playing...\n");
2305 return WAVERR_STILLPLAYING;
2308 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
2309 lpWaveHdr->dwFlags |= WHDR_DONE;
2311 return MMSYSERR_NOERROR;
2314 /**************************************************************************
2315 * widStart [internal]
2317 static DWORD widStart(WORD wDevID)
2319 TRACE("(%u);\n", wDevID);
2320 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2321 WARN("can't start recording !\n");
2322 return MMSYSERR_INVALHANDLE;
2325 WInDev[wDevID].state = WINE_WS_PLAYING;
2326 return MMSYSERR_NOERROR;
2329 /**************************************************************************
2330 * widStop [internal]
2332 static DWORD widStop(WORD wDevID)
2334 WINE_WAVEIN* wwi = &WInDev[wDevID];
2336 TRACE("(%u);\n", wDevID);
2337 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2338 WARN("can't stop !\n");
2339 return MMSYSERR_INVALHANDLE;
2342 if (wwi->state != WINE_WS_STOPPED)
2345 /* do something here to stop recording ??? */
2347 /* return current buffer to app */
2348 lpWaveHdr = wwi->lpQueuePtr;
2351 LPWAVEHDR lpNext = lpWaveHdr->lpNext;
2352 TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2353 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2354 lpWaveHdr->dwFlags |= WHDR_DONE;
2355 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2356 wwi->lpQueuePtr = lpNext;
2359 wwi->state = WINE_WS_STOPPED;
2361 return MMSYSERR_NOERROR;
2364 /**************************************************************************
2365 * widReset [internal]
2367 static DWORD widReset(WORD wDevID)
2369 WINE_WAVEIN* wwi = &WInDev[wDevID];
2372 TRACE("(%u);\n", wDevID);
2373 if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
2374 WARN("can't reset !\n");
2375 return MMSYSERR_INVALHANDLE;
2378 wwi->state = WINE_WS_STOPPED;
2380 /* return all buffers to the app */
2381 for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
2382 TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
2383 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
2384 lpWaveHdr->dwFlags |= WHDR_DONE;
2386 widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
2388 wwi->lpQueuePtr = NULL;
2390 return MMSYSERR_NOERROR;
2393 /**************************************************************************
2394 * widMessage (WINEJACK.6)
2396 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2397 DWORD dwParam1, DWORD dwParam2)
2399 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
2400 wDevID, wMsg, dwUser, dwParam1, dwParam2);
2407 /* FIXME: Pretend this is supported */
2409 case WIDM_OPEN: return widOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
2410 case WIDM_CLOSE: return widClose (wDevID);
2411 case WIDM_ADDBUFFER: return widAddBuffer (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2412 case WIDM_PREPARE: return widPrepare (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2413 case WIDM_UNPREPARE: return widUnprepare (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
2414 case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (LPWAVEINCAPSA)dwParam1, dwParam2);
2415 case WIDM_GETNUMDEVS: return MAX_WAVEINDRV;
2416 case WIDM_RESET: return widReset (wDevID);
2417 case WIDM_START: return widStart (wDevID);
2418 case WIDM_STOP: return widStop (wDevID);
2420 FIXME("unknown message %d!\n", wMsg);
2423 return MMSYSERR_NOTSUPPORTED;
2426 #else /* !HAVE_JACK_JACK_H */
2428 /**************************************************************************
2429 * widMessage (WINEJACK.6)
2431 DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2432 DWORD dwParam1, DWORD dwParam2)
2434 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2435 return MMSYSERR_NOTENABLED;
2438 /**************************************************************************
2439 * wodMessage (WINEJACK.7)
2441 DWORD WINAPI JACK_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
2442 DWORD dwParam1, DWORD dwParam2)
2444 FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
2445 return MMSYSERR_NOTENABLED;
2448 #endif /* HAVE_JACK_JACK_H */