source: trunk/src/winmm/mixer.cpp@ 8492

Last change on this file since 8492 was 8492, checked in by sandervl, 23 years ago

more mixer changes/fixes

File size: 58.4 KB
Line 
1/* $Id: mixer.cpp,v 1.17 2002-05-25 17:19:40 sandervl Exp $ */
2
3/*
4 * Mixer functions
5 *
6 * Copyright 2002 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * TODO: Mixer notification
9 *
10 * NOTE: Not really flexible (capabilities, > 1 audio card)
11 *
12 * Some portions borrowed from Wine (X11): (dll\winmm\mmsystem.c)
13 * (mixerGetLineControlsW/mixerGetControlDetailsW)
14 * Copyright 1993 Martin Ayotte
15 * Eric POUECH
16 *
17 * Project Odin Software License can be found in LICENSE.TXT
18 *
19 */
20
21/****************************************************************************
22 * Includes *
23 ****************************************************************************/
24
25#define NONAMELESSUNION
26#define NONAMELESSSTRUCT
27
28#include <os2win.h>
29#include <string.h>
30#include <dbglog.h>
31#include <mmsystem.h>
32#include <winnls.h>
33
34#include "waveoutdart.h"
35#include "winmm.h"
36#include "initwinmm.h"
37#include "mixer.h"
38#include "mixeros2.h"
39
40#define DBG_LOCALLOG DBG_mixer
41#include "dbglocal.h"
42
43static MIXERCONTROLA *mixerAddControl(MIXERLINEA *pDestLine, DWORD dwControl, MIXERLINEA *pSrcLine);
44static MIXERLINEA *mixerAddSource(MIXERLINEA *pDestLine, DWORD dwSource);
45static MIXERLINEA *mixerAddDestination(DWORD dwDest);
46
47//array of destination mixer lines
48static MIXERLINEA mixerDest[MAX_MIXER_DESTINATIONS] = {0};
49//array of connected sources to destinations
50static int mixerDestInputs[MAX_MIXER_DESTINATIONS][MAX_MIXER_SOURCES] = {-1};
51//array of source mixer lines
52static MIXERLINEA mixerSource[MAX_MIXER_SOURCES] = {0};
53//array of controls connected to mixer lines
54static int mixerLineControls[MAX_MIXER_LINES][MAX_SOURCE_CONTROLS] = {-1};
55//array of all mixer lines
56static MIXERLINEA *pmixerLines[MAX_MIXER_LINES] = {NULL};
57//mapping from src to line id
58static int mixerSourceLineId[MAX_MIXER_SOURCES] = {-1};
59//array of all mixer controls
60static MIXERCONTROLA mixerControls[MAX_MIXER_CONTROLS] = {0};
61//mapping of mixer id to internal id
62static int mixerControlId[MAX_MIXER_CONTROLS] = {0};
63
64static int nrDestinations = 0;
65static int nrSources = 0;
66static int nrControls = 0;
67static int nrLines = 0;
68static int nrLineOutInputs = 0;
69static int nrWaveInInputs = 0;
70
71/******************************************************************************/
72/******************************************************************************/
73MMRESULT WINAPI mixerGetControlDetailsA(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails)
74{
75 DWORD lineID, controlType;
76 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
77
78 if((fdwDetails & 0xF0000000)== MIXER_OBJECTF_HMIXER) {
79 if(!pMixInfo) {
80 return MMSYSERR_INVALHANDLE;
81 }
82 }
83 else
84 if((fdwDetails & 0xF0000000) == MIXER_OBJECTF_MIXER) {
85 if(!HIWORD(hmxobj) && hmxobj > 0) {
86 return MMSYSERR_NODRIVER;
87 }
88 }
89
90 if(lpmcd == NULL || lpmcd->cbStruct != sizeof(MIXERCONTROLDETAILS)) {
91 dprintf(("ERROR: invalid pointer or structure size %d (%d)", (lpmcd) ? lpmcd->cbStruct : 0, sizeof(MIXERCONTROLDETAILS)));
92 return MMSYSERR_INVALPARAM;
93 }
94
95 switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) {
96 case MIXER_GETCONTROLDETAILSF_VALUE:
97 dprintf(("MIXER_GETCONTROLDETAILSF_VALUE %d (internal id %d)", lpmcd->dwControlID, mixerControlId[lpmcd->dwControlID]));
98 if(lpmcd->dwControlID >= nrControls) {
99 dprintf(("invalid control %d", lpmcd->dwControlID));
100 return MIXERR_INVALCONTROL;
101 }
102 switch(mixerControls[lpmcd->dwControlID].dwControlType) {
103 case MIXERCONTROL_CONTROLTYPE_MUX:
104 dprintf(("MIXERCONTROL_CONTROLTYPE_MUX"));
105 break;
106 case MIXERCONTROL_CONTROLTYPE_MIXER:
107 dprintf(("MIXERCONTROL_CONTROLTYPE_MIXER"));
108 break;
109 case MIXERCONTROL_CONTROLTYPE_FADER:
110 dprintf(("MIXERCONTROL_CONTROLTYPE_FADER"));
111 break;
112 case MIXERCONTROL_CONTROLTYPE_VOLUME: //unsigned
113 {
114 MIXERCONTROLDETAILS_UNSIGNED *pDetails = (MIXERCONTROLDETAILS_UNSIGNED *)lpmcd->paDetails;
115 DWORD dwVolLeft, dwVolRight;
116
117 dprintf(("MIXERCONTROL_CONTROLTYPE_VOLUME"));
118 if(OSLibMixGetVolume(mixerControlId[lpmcd->dwControlID], NULL, &dwVolLeft, &dwVolRight) == FALSE) {
119 dprintf(("OSLibMixGetVolume failed!!"));
120 return MIXERR_INVALCONTROL;
121 }
122 pDetails->dwValue = dwVolLeft;
123 dprintf(("Left volume %d", dwVolLeft));
124 if(lpmcd->cChannels == 2) {
125 dprintf(("Right volume %d", dwVolRight));
126 pDetails += 1;
127 pDetails->dwValue = dwVolRight;
128 }
129 //todo > 2 channels
130 break;
131 }
132 case MIXERCONTROL_CONTROLTYPE_BASS:
133 dprintf(("MIXERCONTROL_CONTROLTYPE_BASS"));
134 break;
135 case MIXERCONTROL_CONTROLTYPE_TREBLE:
136 dprintf(("MIXERCONTROL_CONTROLTYPE_TREBLE"));
137 break;
138 case MIXERCONTROL_CONTROLTYPE_MUTE:
139 {
140 MIXERCONTROLDETAILS_UNSIGNED *pDetails = (MIXERCONTROLDETAILS_UNSIGNED *)lpmcd->paDetails;
141 BOOL fMute;
142
143 dprintf(("MIXERCONTROL_CONTROLTYPE_MUTE"));
144 if(OSLibMixGetVolume(mixerControlId[lpmcd->dwControlID], &fMute, NULL, NULL) == FALSE) {
145 dprintf(("OSLibMixGetVolume failed!!"));
146 return MIXERR_INVALCONTROL;
147 }
148 pDetails->dwValue = fMute;
149 dprintf(("Left mute %d", fMute));
150 if(lpmcd->cChannels == 2) {
151 dprintf(("Right mute %d", fMute));
152 pDetails += 1;
153 pDetails->dwValue = fMute;
154 }
155 //todo > 2 channels
156 break;
157 }
158 case MIXERCONTROL_CONTROLTYPE_CUSTOM:
159 dprintf(("MIXERCONTROL_CONTROLTYPE_CUSTOM"));
160 break;
161 case MIXERCONTROL_CONTROLTYPE_BOOLEANMETER:
162 dprintf(("MIXERCONTROL_CONTROLTYPE_BOOLEANMETER"));
163 break;
164 case MIXERCONTROL_CONTROLTYPE_SIGNEDMETER:
165 dprintf(("MIXERCONTROL_CONTROLTYPE_SIGNEDMETER"));
166 break;
167 case MIXERCONTROL_CONTROLTYPE_PEAKMETER:
168 dprintf(("MIXERCONTROL_CONTROLTYPE_PEAKMETER"));
169 break;
170 case MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER:
171 dprintf(("MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER"));
172 break;
173 case MIXERCONTROL_CONTROLTYPE_BOOLEAN:
174 dprintf(("MIXERCONTROL_CONTROLTYPE_BOOLEAN"));
175 break;
176 case MIXERCONTROL_CONTROLTYPE_ONOFF:
177 dprintf(("MIXERCONTROL_CONTROLTYPE_ONOFF"));
178 break;
179 case MIXERCONTROL_CONTROLTYPE_MONO:
180 dprintf(("MIXERCONTROL_CONTROLTYPE_MONO"));
181 break;
182 case MIXERCONTROL_CONTROLTYPE_LOUDNESS:
183 dprintf(("MIXERCONTROL_CONTROLTYPE_LOUDNESS"));
184 break;
185 case MIXERCONTROL_CONTROLTYPE_STEREOENH:
186 dprintf(("MIXERCONTROL_CONTROLTYPE_STEREOENH"));
187 break;
188 case MIXERCONTROL_CONTROLTYPE_BUTTON:
189 dprintf(("MIXERCONTROL_CONTROLTYPE_BUTTON"));
190 break;
191 case MIXERCONTROL_CONTROLTYPE_DECIBELS:
192 dprintf(("MIXERCONTROL_CONTROLTYPE_DECIBELS"));
193 break;
194 case MIXERCONTROL_CONTROLTYPE_SIGNED:
195 dprintf(("MIXERCONTROL_CONTROLTYPE_SIGNED"));
196 break;
197 case MIXERCONTROL_CONTROLTYPE_UNSIGNED:
198 dprintf(("MIXERCONTROL_CONTROLTYPE_UNSIGNED"));
199 break;
200 case MIXERCONTROL_CONTROLTYPE_PERCENT:
201 dprintf(("MIXERCONTROL_CONTROLTYPE_PERCENT"));
202 break;
203 case MIXERCONTROL_CONTROLTYPE_SLIDER:
204 dprintf(("MIXERCONTROL_CONTROLTYPE_SLIDER"));
205 break;
206 case MIXERCONTROL_CONTROLTYPE_PAN:
207 dprintf(("MIXERCONTROL_CONTROLTYPE_PAN"));
208 break;
209 case MIXERCONTROL_CONTROLTYPE_QSOUNDPAN:
210 dprintf(("MIXERCONTROL_CONTROLTYPE_QSOUNDPAN"));
211 break;
212 case MIXERCONTROL_CONTROLTYPE_EQUALIZER:
213 dprintf(("MIXERCONTROL_CONTROLTYPE_EQUALIZER"));
214 break;
215 case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
216 dprintf(("MIXERCONTROL_CONTROLTYPE_SINGLESELECT"));
217 break;
218 case MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT:
219 dprintf(("MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT"));
220 break;
221 case MIXERCONTROL_CONTROLTYPE_MICROTIME:
222 dprintf(("MIXERCONTROL_CONTROLTYPE_MICROTIME"));
223 break;
224 case MIXERCONTROL_CONTROLTYPE_MILLITIME:
225 dprintf(("MIXERCONTROL_CONTROLTYPE_MILLITIME"));
226 break;
227 default:
228 DebugInt3();
229 return MIXERR_INVALCONTROL;
230 }
231 break;
232 case MIXER_GETCONTROLDETAILSF_LISTTEXT:
233 dprintf(("MIXER_GETCONTROLDETAILSF_LISTTEXT %d", lpmcd->dwControlID));
234 if(lpmcd->dwControlID >= nrControls) {
235 dprintf(("invalid control %d", lpmcd->dwControlID));
236 return MIXERR_INVALCONTROL;
237 }
238 break;
239 default:
240 dprintf(("Unknown flag (%08lx)\n", fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK));
241 break;
242 }
243 return MMSYSERR_NOERROR;
244}
245/******************************************************************************/
246/******************************************************************************/
247MMRESULT WINAPI mixerGetControlDetailsW(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails)
248{
249 DWORD ret = MMSYSERR_NOTENABLED;
250
251 if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd))
252 return MMSYSERR_INVALPARAM;
253
254 switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) {
255 case MIXER_GETCONTROLDETAILSF_VALUE:
256 /* can safely use W structure as it is, no string inside */
257 ret = mixerGetControlDetailsA(hmxobj, lpmcd, fdwDetails);
258 break;
259
260 case MIXER_GETCONTROLDETAILSF_LISTTEXT:
261 {
262 LPVOID paDetailsW = lpmcd->paDetails;
263 int size = max(1, lpmcd->cChannels) * sizeof(MIXERCONTROLDETAILS_LISTTEXTA);
264
265 if (lpmcd->u.cMultipleItems != 0 && lpmcd->u.cMultipleItems != lpmcd->u.hwndOwner) {
266 size *= lpmcd->u.cMultipleItems;
267 }
268 lpmcd->paDetails = HeapAlloc(GetProcessHeap(), 0, size);
269 /* set up lpmcd->paDetails */
270 ret = mixerGetControlDetailsA(hmxobj, lpmcd, fdwDetails);
271 /* copy from lpmcd->paDetails back to paDetailsW; */
272 HeapFree(GetProcessHeap(), 0, lpmcd->paDetails);
273 lpmcd->paDetails = paDetailsW;
274 break;
275 }
276 default:
277 dprintf(("Unsupported fdwDetails=0x%08lx\n", fdwDetails));
278 break;
279 }
280
281 return ret;
282}
283/******************************************************************************/
284/******************************************************************************/
285MMRESULT WINAPI mixerSetControlDetails(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails)
286{
287 DWORD ret = MMSYSERR_NOTSUPPORTED;
288 DWORD lineID, controlType;
289 int val;
290 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
291
292 if((fdwDetails & 0xF0000000) == MIXER_OBJECTF_HMIXER) {
293 if(!pMixInfo) {
294 return MMSYSERR_INVALHANDLE;
295 }
296 }
297 else
298 if((fdwDetails & 0xF0000000) == MIXER_OBJECTF_MIXER) {
299 if(!HIWORD(hmxobj) && hmxobj > 0) {
300 return MMSYSERR_NODRIVER;
301 }
302 }
303 if(lpmcd == NULL || lpmcd->cbDetails != sizeof(MIXERCONTROLDETAILS)) {
304 dprintf(("ERROR: invalid pointer or structure size"));
305 return MMSYSERR_INVALPARAM;
306 }
307
308 switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) {
309 case MIXER_GETCONTROLDETAILSF_VALUE:
310 dprintf(("MIXER_GETCONTROLDETAILSF_VALUE"));
311 break;
312 case MIXER_GETCONTROLDETAILSF_LISTTEXT:
313 dprintf(("MIXER_GETCONTROLDETAILSF_LISTTEXT"));
314 break;
315 default:
316 dprintf(("Unknown flag (%08lx)\n", fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK));
317 break;
318 }
319 return MMSYSERR_NOTSUPPORTED;
320}
321/******************************************************************************/
322/******************************************************************************/
323MMRESULT WINAPI mixerGetLineControlsA(HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA lpMlc, DWORD fdwControls)
324{
325 DWORD dwRet = MMSYSERR_NOERROR;
326 DWORD lineID, controlType;
327 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
328
329 if((fdwControls & 0xF0000000) == MIXER_OBJECTF_HMIXER) {
330 if(!pMixInfo) {
331 return MMSYSERR_INVALHANDLE;
332 }
333 }
334 else
335 if((fdwControls & 0xF0000000) == MIXER_OBJECTF_MIXER) {
336 if(!HIWORD(hmxobj) && hmxobj > 0) {
337 return MMSYSERR_NODRIVER;
338 }
339 }
340
341 if (lpMlc == NULL) return MMSYSERR_INVALPARAM;
342
343 if (lpMlc->cbStruct < sizeof(*lpMlc) || lpMlc->cbmxctrl < sizeof(MIXERCONTROLA))
344 return MMSYSERR_INVALPARAM;
345
346 switch(fdwControls & MIXER_GETLINECONTROLSF_QUERYMASK)
347 {
348 case MIXER_GETLINECONTROLSF_ALL:
349 {
350 MIXERLINEA *pLine;
351 MIXERCONTROLA *pCtrl;
352
353 dprintf(("MIXER_GETLINECONTROLSF_ALL for line %d", lpMlc->dwLineID));
354 if(lpMlc->dwLineID >= nrLines) {
355 dprintf(("ERROR: Invalid line %d", lpMlc->dwLineID));
356 return MIXERR_INVALLINE;
357 }
358 pLine = pmixerLines[lpMlc->dwLineID];
359 if(lpMlc->cControls != pLine->cControls || lpMlc->cbmxctrl < pLine->cControls*sizeof(MIXERCONTROLA)) {
360 dprintf(("ERROR: invalid nr of controls %d or structure size %d (%d) (ptr %x)", lpMlc->cControls, lpMlc->cbmxctrl, pLine->cControls*sizeof(MIXERCONTROLA), lpMlc->pamxctrl));
361 return MMSYSERR_INVALPARAM;
362 }
363 for(int i=0;i<lpMlc->cControls;i++) {
364 pCtrl = lpMlc->pamxctrl+i;
365 memcpy(pCtrl, &mixerControls[mixerLineControls[lpMlc->dwLineID][i]], sizeof(MIXERCONTROLA));
366 dprintf(("found control %s (%s) control id %d", pCtrl->szName, pCtrl->szShortName, pCtrl->dwControlID));
367 }
368 break;
369 }
370
371 case MIXER_GETLINECONTROLSF_ONEBYID:
372 {
373 dprintf(("MIXER_GETLINECONTROLSF_ONEBYID %x", lpMlc->u.dwControlID));
374 if(lpMlc->cControls != 1 || lpMlc->cbmxctrl != sizeof(MIXERCONTROLA)) {
375 dprintf(("invalid parameters"));
376 return MMSYSERR_INVALPARAM;
377 }
378 if(lpMlc->u.dwControlID >= nrControls) {
379 dprintf(("invalid control"));
380 return MIXERR_INVALCONTROL;
381 }
382 //find line associated with this control
383 lpMlc->dwLineID = -1;
384 for(int i=0;i<MAX_MIXER_LINES;i++) {
385 for(int j=0;j<MAX_SOURCE_CONTROLS;j++) {
386 if(mixerLineControls[i][j] == lpMlc->u.dwControlID) {
387 lpMlc->dwLineID = i;
388 break;
389 }
390 else
391 if(mixerLineControls[i][j] == -1) {
392 break;
393 }
394 }
395 if(lpMlc->dwLineID != -1) {
396 break;
397 }
398 }
399 if(i == MAX_MIXER_LINES) {
400 dprintf(("Associated line for control %d NOT FOUND", lpMlc->u.dwControlID));
401 return MIXERR_INVALCONTROL;
402 }
403 memcpy(lpMlc->pamxctrl, &mixerControls[lpMlc->u.dwControlID], sizeof(MIXERCONTROLA));
404
405 dprintf(("found control %s (%s) associated line %d", lpMlc->pamxctrl->szName, lpMlc->pamxctrl->szShortName, lpMlc->dwLineID));
406 break;
407 }
408
409 case MIXER_GETLINECONTROLSF_ONEBYTYPE:
410 {
411 dprintf(("MIXER_GETLINECONTROLSF_ONEBYTYPE %x %d", lpMlc->u.dwControlType, lpMlc->dwLineID));
412 if(lpMlc->dwLineID >= nrLines) {
413 dprintf(("ERROR: Invalid line %d", lpMlc->dwLineID));
414 return MIXERR_INVALLINE;
415 }
416#ifdef DEBUG
417 switch (lpMlc->u.dwControlType) {
418 case MIXERCONTROL_CONTROLTYPE_CUSTOM:
419 dprintf(("MIXERCONTROL_CONTROLTYPE_CUSTOM"));
420 break;
421 case MIXERCONTROL_CONTROLTYPE_BOOLEANMETER:
422 dprintf(("MIXERCONTROL_CONTROLTYPE_BOOLEANMETER"));
423 break;
424 case MIXERCONTROL_CONTROLTYPE_SIGNEDMETER:
425 dprintf(("MIXERCONTROL_CONTROLTYPE_SIGNEDMETER"));
426 break;
427 case MIXERCONTROL_CONTROLTYPE_PEAKMETER:
428 dprintf(("MIXERCONTROL_CONTROLTYPE_PEAKMETER"));
429 break;
430 case MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER:
431 dprintf(("MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER"));
432 break;
433 case MIXERCONTROL_CONTROLTYPE_BOOLEAN:
434 dprintf(("MIXERCONTROL_CONTROLTYPE_BOOLEAN"));
435 break;
436 case MIXERCONTROL_CONTROLTYPE_ONOFF:
437 dprintf(("MIXERCONTROL_CONTROLTYPE_ONOFF"));
438 break;
439 case MIXERCONTROL_CONTROLTYPE_MUTE:
440 dprintf(("MIXERCONTROL_CONTROLTYPE_MUTE"));
441 break;
442 case MIXERCONTROL_CONTROLTYPE_MONO:
443 dprintf(("MIXERCONTROL_CONTROLTYPE_MONO"));
444 break;
445 case MIXERCONTROL_CONTROLTYPE_LOUDNESS:
446 dprintf(("MIXERCONTROL_CONTROLTYPE_LOUDNESS"));
447 break;
448 case MIXERCONTROL_CONTROLTYPE_STEREOENH:
449 dprintf(("MIXERCONTROL_CONTROLTYPE_STEREOENH"));
450 break;
451 case MIXERCONTROL_CONTROLTYPE_BUTTON:
452 dprintf(("MIXERCONTROL_CONTROLTYPE_BUTTON"));
453 break;
454 case MIXERCONTROL_CONTROLTYPE_DECIBELS:
455 dprintf(("MIXERCONTROL_CONTROLTYPE_DECIBELS"));
456 break;
457 case MIXERCONTROL_CONTROLTYPE_SIGNED:
458 dprintf(("MIXERCONTROL_CONTROLTYPE_SIGNED"));
459 break;
460 case MIXERCONTROL_CONTROLTYPE_UNSIGNED:
461 dprintf(("MIXERCONTROL_CONTROLTYPE_UNSIGNED"));
462 break;
463 case MIXERCONTROL_CONTROLTYPE_PERCENT:
464 dprintf(("MIXERCONTROL_CONTROLTYPE_PERCENT"));
465 break;
466 case MIXERCONTROL_CONTROLTYPE_SLIDER:
467 dprintf(("MIXERCONTROL_CONTROLTYPE_SLIDER"));
468 break;
469 case MIXERCONTROL_CONTROLTYPE_PAN:
470 dprintf(("MIXERCONTROL_CONTROLTYPE_PAN"));
471 break;
472 case MIXERCONTROL_CONTROLTYPE_QSOUNDPAN:
473 dprintf(("MIXERCONTROL_CONTROLTYPE_QSOUNDPAN"));
474 break;
475 case MIXERCONTROL_CONTROLTYPE_FADER:
476 dprintf(("MIXERCONTROL_CONTROLTYPE_FADER"));
477 break;
478 case MIXERCONTROL_CONTROLTYPE_VOLUME:
479 dprintf(("MIXERCONTROL_CONTROLTYPE_VOLUME"));
480 break;
481 case MIXERCONTROL_CONTROLTYPE_BASS:
482 dprintf(("MIXERCONTROL_CONTROLTYPE_BASS"));
483 break;
484 case MIXERCONTROL_CONTROLTYPE_TREBLE:
485 dprintf(("MIXERCONTROL_CONTROLTYPE_TREBLE"));
486 break;
487 case MIXERCONTROL_CONTROLTYPE_EQUALIZER:
488 dprintf(("MIXERCONTROL_CONTROLTYPE_EQUALIZER"));
489 break;
490 case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
491 dprintf(("MIXERCONTROL_CONTROLTYPE_SINGLESELECT"));
492 break;
493 case MIXERCONTROL_CONTROLTYPE_MUX:
494 dprintf(("MIXERCONTROL_CONTROLTYPE_MUX"));
495 break;
496 case MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT:
497 dprintf(("MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT"));
498 break;
499 case MIXERCONTROL_CONTROLTYPE_MIXER:
500 dprintf(("MIXERCONTROL_CONTROLTYPE_MIXER"));
501 break;
502 case MIXERCONTROL_CONTROLTYPE_MICROTIME:
503 dprintf(("MIXERCONTROL_CONTROLTYPE_MICROTIME"));
504 break;
505 case MIXERCONTROL_CONTROLTYPE_MILLITIME:
506 dprintf(("MIXERCONTROL_CONTROLTYPE_MILLITIME"));
507 break;
508 default:
509 return MMSYSERR_INVALPARAM;
510 }
511#endif
512 int idx;
513
514 for(int i=0;i<MAX_SOURCE_CONTROLS;i++) {
515 idx = mixerLineControls[lpMlc->dwLineID][i];
516 if(idx == -1) break;
517 if(mixerControls[idx].dwControlType == lpMlc->u.dwControlType) {
518 memcpy(lpMlc->pamxctrl, &mixerControls[idx], sizeof(MIXERCONTROLA));
519 dprintf(("found control %s (%s) control id %d", lpMlc->pamxctrl->szName, lpMlc->pamxctrl->szShortName, lpMlc->pamxctrl->dwControlID));
520 return MMSYSERR_NOERROR;
521 }
522
523 }
524 return MIXERR_INVALLINE; //returned by win2k when type not found
525 }
526 default:
527 dprintf(("Unknown flag %08lx\n", fdwControls & MIXER_GETLINECONTROLSF_QUERYMASK));
528 dwRet = MMSYSERR_INVALPARAM;
529 break;
530 }
531
532 return dwRet;
533}
534/******************************************************************************/
535/******************************************************************************/
536MMRESULT WINAPI mixerGetLineControlsW(HMIXEROBJ hmxobj, LPMIXERLINECONTROLSW lpmlcW, DWORD fdwControls)
537{
538 MIXERLINECONTROLSA mlcA;
539 DWORD ret;
540 int i;
541
542 if (lpmlcW == NULL || lpmlcW->cbStruct != sizeof(*lpmlcW) || lpmlcW->cbmxctrl != sizeof(MIXERCONTROLW))
543 return MMSYSERR_INVALPARAM;
544
545 mlcA.cbStruct = sizeof(mlcA);
546 mlcA.dwLineID = lpmlcW->dwLineID;
547 mlcA.u.dwControlID = lpmlcW->u.dwControlID;
548 mlcA.u.dwControlType = lpmlcW->u.dwControlType;
549 mlcA.cControls = lpmlcW->cControls;
550 mlcA.cbmxctrl = sizeof(MIXERCONTROLA);
551 mlcA.pamxctrl = (MIXERCONTROLA *)HeapAlloc(GetProcessHeap(), 0, mlcA.cControls * mlcA.cbmxctrl);
552
553 ret = mixerGetLineControlsA(hmxobj, &mlcA, fdwControls);
554
555 if (ret == MMSYSERR_NOERROR) {
556 lpmlcW->dwLineID = mlcA.dwLineID;
557 lpmlcW->u.dwControlID = mlcA.u.dwControlID;
558 lpmlcW->u.dwControlType = mlcA.u.dwControlType;
559 lpmlcW->cControls = mlcA.cControls;
560
561 for (i = 0; i < mlcA.cControls; i++) {
562 lpmlcW->pamxctrl[i].cbStruct = sizeof(MIXERCONTROLW);
563 lpmlcW->pamxctrl[i].dwControlID = mlcA.pamxctrl[i].dwControlID;
564 lpmlcW->pamxctrl[i].dwControlType = mlcA.pamxctrl[i].dwControlType;
565 lpmlcW->pamxctrl[i].fdwControl = mlcA.pamxctrl[i].fdwControl;
566 lpmlcW->pamxctrl[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems;
567 MultiByteToWideChar( CP_ACP, 0, mlcA.pamxctrl[i].szShortName, -1,
568 lpmlcW->pamxctrl[i].szShortName,
569 sizeof(lpmlcW->pamxctrl[i].szShortName)/sizeof(WCHAR) );
570 MultiByteToWideChar( CP_ACP, 0, mlcA.pamxctrl[i].szName, -1,
571 lpmlcW->pamxctrl[i].szName,
572 sizeof(lpmlcW->pamxctrl[i].szName)/sizeof(WCHAR) );
573 /* sizeof(lpmlcW->pamxctrl[i].Bounds) ==
574 * sizeof(mlcA.pamxctrl[i].Bounds) */
575 memcpy(&lpmlcW->pamxctrl[i].Bounds, &mlcA.pamxctrl[i].Bounds,
576 sizeof(mlcA.pamxctrl[i].Bounds));
577 /* sizeof(lpmlcW->pamxctrl[i].Metrics) ==
578 * sizeof(mlcA.pamxctrl[i].Metrics) */
579 memcpy(&lpmlcW->pamxctrl[i].Metrics, &mlcA.pamxctrl[i].Metrics,
580 sizeof(mlcA.pamxctrl[i].Metrics));
581 }
582 }
583
584 HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl);
585 return ret;
586}
587/******************************************************************************/
588/******************************************************************************/
589MMRESULT WINAPI mixerGetLineInfoA(HMIXEROBJ hmxobj, LPMIXERLINEA lpMl, DWORD fdwInfo)
590{
591 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
592
593 if((fdwInfo & 0xF0000000) == MIXER_OBJECTF_HMIXER) {
594 if(!pMixInfo) {
595 return MMSYSERR_INVALHANDLE;
596 }
597 }
598 else
599 if((fdwInfo & 0xF0000000) == MIXER_OBJECTF_MIXER) {
600 if(!HIWORD(hmxobj) && hmxobj > 0) {
601 return MMSYSERR_NODRIVER;
602 }
603 }
604
605 if (lpMl == NULL || lpMl->cbStruct != sizeof(*lpMl)) {
606 dprintf(("ERROR: mixerGetLineInfoA: invalid paramter!!"));
607 return MMSYSERR_INVALPARAM;
608 }
609
610 switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK)
611 {
612 case MIXER_GETLINEINFOF_DESTINATION:
613 dprintf(("MIXER_GETLINEINFOF_DESTINATION %d", lpMl->dwDestination));
614 if(lpMl->dwDestination >= nrDestinations) {
615 dprintf(("ERROR: Invalid destination %d", lpMl->dwDestination));
616 return MMSYSERR_INVALPARAM;
617 }
618 memcpy(lpMl, &mixerDest[lpMl->dwDestination], sizeof(MIXERLINEA));
619 dprintf(("found line %s (%s) id %d connections %d controls %d", lpMl->szName, lpMl->szShortName, lpMl->dwLineID, lpMl->cConnections, lpMl->cControls));
620 break;
621
622 case MIXER_GETLINEINFOF_LINEID:
623 dprintf(("MIXER_GETLINEINFOF_LINEID %d", lpMl->dwLineID));
624 if(lpMl->dwLineID >= nrLines) {
625 dprintf(("ERROR: Invalid line %d", lpMl->dwLineID));
626 return MIXERR_INVALLINE;
627 }
628 memcpy(lpMl, pmixerLines[lpMl->dwLineID], sizeof(MIXERLINEA));
629 dprintf(("found line %s (%s) connections %d controls %d", lpMl->szName, lpMl->szShortName, lpMl->cConnections, lpMl->cControls));
630 break;
631
632 case MIXER_GETLINEINFOF_SOURCE:
633 dprintf(("MIXER_GETLINEINFOF_SOURCE %d %d", lpMl->dwDestination, lpMl->dwSource));
634 if(lpMl->dwDestination >= nrDestinations) {
635 dprintf(("ERROR: Invalid destination %d", lpMl->dwDestination));
636 return MIXERR_INVALLINE;
637 }
638 if(lpMl->dwSource >= MIXER_SRC_MAX) {
639 dprintf(("ERROR: Invalid destination %d", lpMl->dwDestination));
640 return MIXERR_INVALLINE;
641 }
642 if(mixerDestInputs[lpMl->dwDestination][lpMl->dwSource] == -1) {
643 dprintf(("ERROR: Invalid destination %d", lpMl->dwDestination));
644 return MIXERR_INVALLINE;
645 }
646 memcpy(lpMl, &mixerSource[mixerDestInputs[lpMl->dwDestination][lpMl->dwSource]], sizeof(MIXERLINEA));
647 dprintf(("found line %s (%s) id %d connections %d controls %d", lpMl->szName, lpMl->szShortName, lpMl->dwLineID, lpMl->cConnections, lpMl->cControls));
648 break;
649
650 case MIXER_GETLINEINFOF_COMPONENTTYPE:
651 {
652 dprintf(("MIXER_GETLINEINFOF_COMPONENTTYPE"));
653#ifdef DEBUG
654 switch (lpMl->dwComponentType)
655 {
656 case MIXERLINE_COMPONENTTYPE_DST_UNDEFINED:
657 dprintf(("MIXERLINE_COMPONENTTYPE_DST_UNDEFINED"));
658 break;
659 case MIXERLINE_COMPONENTTYPE_DST_DIGITAL:
660 dprintf(("MIXERLINE_COMPONENTTYPE_DST_DIGITAL"));
661 break;
662 case MIXERLINE_COMPONENTTYPE_DST_LINE:
663 dprintf(("MIXERLINE_COMPONENTTYPE_DST_LINE"));
664 break;
665 case MIXERLINE_COMPONENTTYPE_DST_MONITOR:
666 dprintf(("MIXERLINE_COMPONENTTYPE_DST_MONITOR"));
667 break;
668 case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS:
669 dprintf(("MIXERLINE_COMPONENTTYPE_DST_SPEAKERS"));
670 break;
671 case MIXERLINE_COMPONENTTYPE_DST_HEADPHONES:
672 dprintf(("MIXERLINE_COMPONENTTYPE_DST_HEADPHONES"));
673 break;
674 case MIXERLINE_COMPONENTTYPE_DST_TELEPHONE:
675 dprintf(("MIXERLINE_COMPONENTTYPE_DST_TELEPHONE"));
676 break;
677 case MIXERLINE_COMPONENTTYPE_DST_WAVEIN:
678 dprintf(("MIXERLINE_COMPONENTTYPE_DST_WAVEIN"));
679 break;
680 case MIXERLINE_COMPONENTTYPE_DST_VOICEIN:
681 dprintf(("MIXERLINE_COMPONENTTYPE_DST_VOICEIN"));
682 break;
683 case MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED:
684 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED"));
685 break;
686 case MIXERLINE_COMPONENTTYPE_SRC_DIGITAL:
687 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_DIGITAL"));
688 break;
689 case MIXERLINE_COMPONENTTYPE_SRC_LINE:
690 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_LINE"));
691 break;
692 case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE:
693 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE"));
694 break;
695 case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER:
696 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER"));
697 break;
698 case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC:
699 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC"));
700 break;
701 case MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE:
702 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE"));
703 break;
704 case MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER:
705 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER"));
706 break;
707 case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT:
708 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT"));
709 break;
710 case MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY:
711 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY"));
712 break;
713 case MIXERLINE_COMPONENTTYPE_SRC_ANALOG:
714 dprintf(("MIXERLINE_COMPONENTTYPE_SRC_ANALOG"));
715 break;
716 default:
717 dprintf(("Unhandled component type (%08lx)\n", lpMl->dwComponentType));
718 return MMSYSERR_INVALPARAM;
719 }
720#endif
721 //search all lines (src & dest) for one with specified type
722 for(int i=0;i<nrLines;i++) {
723 if(pmixerLines[i]->dwComponentType == lpMl->dwComponentType) {
724 break;
725 }
726 }
727 if(i == nrLines) {
728 dprintf(("Component type %d not found!!", lpMl->dwComponentType));
729 return MIXERR_INVALLINE;
730 }
731 memcpy(lpMl, pmixerLines[i], sizeof(MIXERLINEA));
732 dprintf(("found line %s (%s) id %d connections %d controls %d", lpMl->szName, lpMl->szShortName, lpMl->dwLineID, lpMl->cConnections, lpMl->cControls));
733 break;
734 }
735 case MIXER_GETLINEINFOF_TARGETTYPE:
736 {
737 dprintf(("MIXER_GETLINEINFOF_TARGETTYPE %x", lpMl->Target.dwType));
738#ifdef DEBUG
739 switch(lpMl->Target.dwType) {
740 case MIXERLINE_TARGETTYPE_UNDEFINED:
741 dprintf(("MIXERLINE_TARGETTYPE_UNDEFINED"));
742 break;
743 case MIXERLINE_TARGETTYPE_WAVEOUT:
744 dprintf(("MIXERLINE_TARGETTYPE_WAVEOUT"));
745 break;
746 case MIXERLINE_TARGETTYPE_WAVEIN:
747 dprintf(("MIXERLINE_TARGETTYPE_WAVEIN"));
748 break;
749 case MIXERLINE_TARGETTYPE_MIDIOUT:
750 dprintf(("MIXERLINE_TARGETTYPE_MIDIOUT"));
751 break;
752 case MIXERLINE_TARGETTYPE_MIDIIN:
753 dprintf(("MIXERLINE_TARGETTYPE_MIDIIN"));
754 break;
755 case MIXERLINE_TARGETTYPE_AUX:
756 dprintf(("MIXERLINE_TARGETTYPE_AUX"));
757 break;
758 default:
759 dprintf(("Unhandled target type (%08lx)\n", lpMl->Target.dwType));
760 return MMSYSERR_INVALPARAM;
761 }
762#endif
763 //search all lines (src & dest) for one with specified type
764 //TODO: Should we compare mid, pid & pddname too? (must be initialized according to MSDN)
765 // (see below; unicode version doesn't copy pddname; change if these checks are required)
766 for(int i=0;i<nrLines;i++) {
767 if(pmixerLines[i]->Target.dwType == lpMl->Target.dwType) {
768 break;
769 }
770 }
771 if(i == nrLines) {
772 dprintf(("Component type %d not found!!", lpMl->Target.dwType));
773 return MIXERR_INVALLINE;
774 }
775 memcpy(lpMl, pmixerLines[i], sizeof(MIXERLINEA));
776 dprintf(("found line %s (%s) id %d connections %d controls %d", lpMl->szName, lpMl->szShortName, lpMl->dwLineID, lpMl->cConnections, lpMl->cControls));
777 break;
778 }
779 default:
780 dprintf(("Unknown flag (%08lx)\n", fdwInfo & MIXER_GETLINEINFOF_QUERYMASK));
781 return MMSYSERR_INVALPARAM;
782 break;
783 }
784 return MMSYSERR_NOERROR;
785}
786/******************************************************************************/
787/******************************************************************************/
788MMRESULT WINAPI mixerGetLineInfoW(HMIXEROBJ hmxobj, LPMIXERLINEW pmxl, DWORD fdwInfo)
789{
790 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
791 MIXERLINEA line;
792 MMRESULT result;
793
794 line.cbStruct = sizeof(MIXERLINEA);
795 line.cChannels = pmxl->cChannels;
796 line.cConnections = pmxl->cConnections;
797 line.dwComponentType = pmxl->dwComponentType;
798 line.dwDestination = pmxl->dwDestination;
799 line.dwLineID = pmxl->dwLineID;
800 line.dwSource = pmxl->dwSource;
801 line.dwUser = pmxl->dwUser;
802 line.fdwLine = pmxl->fdwLine;
803 line.szName[0] = 0;
804 line.szShortName[0] = 0;
805 line.Target.dwDeviceID = pmxl->Target.dwDeviceID;
806 line.Target.dwType = pmxl->Target.dwType;
807 line.Target.vDriverVersion = pmxl->Target.vDriverVersion;
808 line.Target.wMid = pmxl->Target.wMid;
809 line.Target.wPid = pmxl->Target.wPid;
810 //TODO: need to copy this?? (MIXER_GETLINEINFOF_TARGETTYPE)
811 line.Target.szPname[0] = 0;
812
813 result = mixerGetLineInfoA(hmxobj, &line, fdwInfo);
814 if(result != MMSYSERR_NOERROR) {
815 return result;
816 }
817 pmxl->cbStruct = sizeof(MIXERLINEA);
818 pmxl->cChannels = line.cChannels;
819 pmxl->cConnections = line.cConnections;
820 pmxl->dwComponentType = line.dwComponentType;
821 pmxl->dwDestination = line.dwDestination;
822 pmxl->dwLineID = line.dwLineID;
823 pmxl->dwSource = line.dwSource;
824 pmxl->dwUser = line.dwUser;
825 pmxl->fdwLine = line.fdwLine;
826 MultiByteToWideChar(CP_ACP, 0, line.szName, -1, pmxl->szName, sizeof(line.szName));
827 MultiByteToWideChar(CP_ACP, 0, line.szShortName, -1, pmxl->szShortName, sizeof(line.szShortName));
828 pmxl->Target.dwDeviceID = line.Target.dwDeviceID;
829 pmxl->Target.dwType = line.Target.dwType;
830 pmxl->Target.vDriverVersion = line.Target.vDriverVersion;
831 pmxl->Target.wMid = line.Target.wMid;
832 pmxl->Target.wPid = line.Target.wPid;
833 pmxl->Target.szPname[0] = 0;
834 MultiByteToWideChar(CP_ACP, 0, line.Target.szPname, -1, pmxl->Target.szPname, sizeof(line.Target.szPname));
835 return MMSYSERR_NOERROR;
836}
837/******************************************************************************/
838/******************************************************************************/
839MMRESULT WINAPI mixerMessage(HMIXER hmx, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
840{
841 dprintf(("WINMM:mixerMessage - NOT IMPLEMENTED" ));
842 return MMSYSERR_NOTSUPPORTED;
843}
844/******************************************************************************/
845/******************************************************************************/
846UINT WINAPI mixerGetNumDevs()
847{
848 if(fMMPMAvailable == FALSE || DartWaveOut::getNumDevices() == 0) {
849 return 0;
850 }
851 return 1;
852}
853/******************************************************************************/
854/******************************************************************************/
855MMRESULT WINAPI mixerGetDevCapsA(UINT uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps)
856{
857 if(fMMPMAvailable == FALSE || DartWaveOut::getNumDevices() == 0) {
858 return MMSYSERR_BADDEVICEID;
859 }
860
861 if(uMxId > 0) {
862 return MMSYSERR_BADDEVICEID;
863 }
864
865 //According to MSDN, nothing is copied when cbmxcaps is zero
866 if(cbmxcaps >= sizeof(MIXERCAPSA)) {
867 // we have to fill in this thing
868 pmxcaps->wMid = WINMM_MIXER_CAPS_WMID; /* manufacturer ID */
869 pmxcaps->wPid = WINMM_MIXER_CAPS_WPID; /* product ID */
870 pmxcaps->vDriverVersion = WINMM_MIXER_CAPS_VERSION; /* version of the driver */
871 strncpy( pmxcaps->szPname, WINMM_MIXERSTRING_A, sizeof(pmxcaps->szPname)); /* product name */
872
873 pmxcaps->fdwSupport = 0; //no mixer flags exist
874 pmxcaps->cDestinations = nrDestinations;
875 dprintf(("mixerGetDevCapsA: cDestinations %d", pmxcaps->cDestinations));
876 }
877
878 return MMSYSERR_NOERROR;
879}
880/******************************************************************************/
881/******************************************************************************/
882MMRESULT WINAPI mixerGetDevCapsW(UINT uMxId, LPMIXERCAPSW pmxcaps, UINT cbmxcaps)
883{
884 if(fMMPMAvailable == FALSE || DartWaveOut::getNumDevices() == 0) {
885 return MMSYSERR_BADDEVICEID;
886 }
887
888 if(uMxId > 0) {
889 return MMSYSERR_BADDEVICEID;
890 }
891
892 //According to MSDN, nothing is copied when cbmxcaps is zero
893 if(cbmxcaps >= sizeof(MIXERCAPSW)) {
894 // we have to fill in this thing
895 pmxcaps->wMid = WINMM_MIXER_CAPS_WMID; /* manufacturer ID */
896 pmxcaps->wPid = WINMM_MIXER_CAPS_WPID; /* product ID */
897 pmxcaps->vDriverVersion = WINMM_MIXER_CAPS_VERSION; /* version of the driver */
898 lstrcpyW( pmxcaps->szPname, WINMM_MIXERSTRING_W ); /* product name */
899
900 pmxcaps->fdwSupport = 0; //no mixer flags exist
901 pmxcaps->cDestinations = nrDestinations;
902 dprintf(("mixerGetDevCapsW: cDestinations %d", pmxcaps->cDestinations));
903 }
904
905 return MMSYSERR_NOERROR;
906}
907/******************************************************************************/
908/******************************************************************************/
909MMRESULT WINAPI mixerGetID(HMIXEROBJ hmxobj, UINT * puMxId, DWORD fdwId)
910{
911 switch(fdwId) {
912 case MIXER_OBJECTF_MIXER:
913 {
914 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
915 if(!pMixInfo) {
916 if(puMxId) {
917 *puMxId = -1;
918 }
919 return MMSYSERR_INVALHANDLE;
920 }
921 if(puMxId) {
922 *puMxId = pMixInfo->uDeviceID;
923 }
924 break;
925 }
926
927 case MIXER_OBJECTF_HMIXER:
928 case MIXER_OBJECTF_WAVEOUT:
929 case MIXER_OBJECTF_HWAVEOUT:
930 case MIXER_OBJECTF_WAVEIN:
931 case MIXER_OBJECTF_HWAVEIN:
932 case MIXER_OBJECTF_MIDIOUT:
933 case MIXER_OBJECTF_HMIDIOUT:
934 case MIXER_OBJECTF_MIDIIN:
935 case MIXER_OBJECTF_HMIDIIN:
936 case MIXER_OBJECTF_AUX:
937 //TODO: assume default mixer
938 if(puMxId) {
939 *puMxId = 0;
940 }
941 break;
942 default:
943 if(puMxId) {
944 *puMxId = -1;
945 }
946 return MMSYSERR_INVALPARAM;
947 }
948 return MMSYSERR_NOERROR;
949}
950/******************************************************************************/
951/******************************************************************************/
952MMRESULT WINAPI mixerOpen(LPHMIXER phmx, UINT uMxId, DWORD dwCallback, DWORD dwInstance,
953 DWORD fdwOpen)
954{
955 DEVICE_STRUCT *pMixInfo;
956
957 if(DartWaveOut::getNumDevices() == 0) {
958 if(phmx) *phmx = 0;
959 return MMSYSERR_NODRIVER;
960 }
961 pMixInfo = (DEVICE_STRUCT *)malloc(sizeof(DEVICE_STRUCT));
962 if(pMixInfo == NULL) {
963 return MMSYSERR_NODRIVER;
964 }
965 pMixInfo->dwCallback = dwCallback;
966 pMixInfo->dwDriverInstance = dwInstance;
967 pMixInfo->dwFlags = fdwOpen;
968 pMixInfo->uDeviceID = uMxId;
969 pMixInfo->type = WINMM_MIXER;
970 if(phmx)
971 *phmx = (HMIXER)pMixInfo;
972
973 return MMSYSERR_NOERROR;
974}
975/******************************************************************************/
976/******************************************************************************/
977MMRESULT WINAPI mixerClose(HMIXER hmx)
978{
979 if(hmx) {
980 free((void *)hmx);
981 }
982 return MMSYSERR_NOERROR;
983}
984/******************************************************************************/
985/******************************************************************************/
986BOOL mixerInit()
987{
988 MIXERLINEA *pDestLine;
989 MIXERCONTROLA *pWaveInMux;
990
991 if(!fMMPMAvailable) return TRUE;
992
993 memset(mixerSourceLineId, -1, sizeof(mixerSourceLineId));
994 memset(mixerLineControls, -1, sizeof(mixerLineControls));
995 memset(mixerDestInputs, -1, sizeof(mixerDestInputs));
996
997 if(OSLibMixerOpen() == FALSE) {
998 //Line out destination
999 pDestLine = mixerAddDestination(MIXER_DEST_LINEOUT);
1000 mixerAddControl(pDestLine, MIX_CTRL_VOL_OUT_LINE, pDestLine);
1001 mixerAddControl(pDestLine, MIX_CTRL_MUTE_OUT_LINE, pDestLine);
1002
1003 //WaveIn destination
1004 pDestLine = mixerAddDestination(MIXER_DEST_WAVEIN);
1005 pWaveInMux = mixerAddControl(pDestLine, MIX_CTRL_MUX_IN_W_SRC, pDestLine);
1006 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MIC, pDestLine);
1007 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_LINE, pDestLine);
1008 pWaveInMux->cMultipleItems = pDestLine->cConnections;
1009 return TRUE;
1010 }
1011
1012 //Line out destination
1013 pDestLine = mixerAddDestination(MIXER_DEST_LINEOUT);
1014
1015 mixerAddControl(pDestLine, MIX_CTRL_VOL_OUT_LINE, pDestLine);
1016 mixerAddControl(pDestLine, MIX_CTRL_MUTE_OUT_LINE, pDestLine);
1017 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_3DCENTER)) {
1018 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_3DCENTER, pDestLine);
1019 }
1020 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_3DDEPTH)) {
1021 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_3DDEPTH, pDestLine);
1022 }
1023 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_TREBLE)) {
1024 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_TREBLE, pDestLine);
1025 }
1026 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_BASS)) {
1027 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_BASS, pDestLine);
1028 }
1029
1030 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_PCM)) {
1031 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_PCM);
1032 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_PCM, pLine);
1033 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_PCM, pLine);
1034 }
1035 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_WAVETABLE)) {
1036 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_WAVETABLE);
1037 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_WAVETABLE, pLine);
1038 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_WAVETABLE, pLine);
1039 }
1040 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_MIDI)) {
1041 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_MIDI);
1042 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_MIDI, pLine);
1043 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_MIDI, pLine);
1044 }
1045 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_MIC)) {
1046 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_MIC);
1047 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_MIC, pLine);
1048 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_MIC, pLine);
1049 if(OSLibMixIsControlPresent(MIX_CTRL_BOOST_IN_L_MIC)) {
1050 mixerAddControl(pDestLine, MIX_CTRL_BOOST_IN_L_MIC, pLine);
1051 }
1052 }
1053 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_LINE)) {
1054 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_LINE);
1055 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_LINE, pLine);
1056 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_LINE, pLine);
1057 }
1058 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_CD)) {
1059 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_CD);
1060 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_CD, pLine);
1061 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_CD, pLine);
1062 }
1063 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_AUX)) {
1064 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_AUX);
1065 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_AUX, pLine);
1066 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_AUX, pLine);
1067 }
1068 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_SPDIF)) {
1069 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_SPDIF);
1070 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_SPDIF, pLine);
1071 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_SPDIF, pLine);
1072 }
1073 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_MONO)) {
1074 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_MONOIN);
1075 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_MONO, pLine);
1076 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_MONO, pLine);
1077 }
1078 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_PHONE)) {
1079 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_PHONE);
1080 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_PHONE, pLine);
1081 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_PHONE, pLine);
1082 }
1083 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_VIDEO)) {
1084 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_VIDEO);
1085 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_VIDEO, pLine);
1086 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_VIDEO, pLine);
1087 }
1088
1089 //Wave In Destination
1090 if(OSLibMixIsControlPresent(MIX_CTRL_MUX_IN_W_SRC)) {
1091 pDestLine = mixerAddDestination(MIXER_DEST_WAVEIN);
1092 pWaveInMux = mixerAddControl(pDestLine, MIX_CTRL_MUX_IN_W_SRC, pDestLine);
1093
1094 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_MIC)) {
1095 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MIC, pDestLine);
1096 }
1097 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_LINE)) {
1098 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_LINE, pDestLine);
1099 }
1100 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_CD)) {
1101 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_CD, pDestLine);
1102 }
1103 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_AUX)) {
1104 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_AUX, pDestLine);
1105 }
1106 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_PCM)) {
1107 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_PCM, pDestLine);
1108 }
1109 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_WAVETABLE)) {
1110 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_WAVETABLE, pDestLine);
1111 }
1112 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_MIDI)) {
1113 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MIDI, pDestLine);
1114 }
1115 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_MONO)) {
1116 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MONO, pDestLine);
1117 }
1118 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_PHONE)) {
1119 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_PHONE, pDestLine);
1120 }
1121 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_SPDIF)) {
1122 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_SPDIF, pDestLine);
1123 }
1124 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_VIDEO)) {
1125 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_VIDEO, pDestLine);
1126 }
1127 pWaveInMux->cMultipleItems = pDestLine->cConnections;
1128 }
1129
1130 //SPDIF destination
1131 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_OUT_SPDIF)) {
1132 pDestLine = mixerAddDestination(MIXER_DEST_SPDIFOUT);
1133 mixerAddControl(pDestLine, MIX_CTRL_VOL_OUT_SPDIF, pDestLine);
1134 mixerAddControl(pDestLine, MIX_CTRL_MUTE_OUT_SPDIF, pDestLine);
1135 }
1136
1137 return TRUE;
1138}
1139/******************************************************************************/
1140/******************************************************************************/
1141void mixerExit()
1142{
1143 OSLibMixerClose();
1144}
1145/******************************************************************************/
1146/******************************************************************************/
1147static MIXERLINEA *mixerAddSource(MIXERLINEA *pDestLine, DWORD dwSource)
1148{
1149 MIXERLINEA *pline = &mixerSource[nrSources];
1150
1151 if(nrSources >= MAX_MIXER_SOURCES) {
1152 dprintf(("ERROR: mixerAddSource: out of room!!!"));
1153 DebugInt3();
1154 return NULL;
1155 }
1156
1157 memset(pline, 0, sizeof(MIXERLINEA));
1158
1159 pline->cbStruct = sizeof(MIXERLINEA);
1160 pline->cConnections = 0;
1161 pline->cControls = 0;
1162 pline->dwDestination = 0;
1163 pline->fdwLine = MIXERLINE_LINEF_SOURCE;
1164 pline->dwSource = nrSources;
1165 pline->Target.dwDeviceID = 0;
1166 pline->Target.wMid = WINMM_MIXER_CAPS_WMID;
1167 pline->Target.vDriverVersion = WINMM_MIXER_CAPS_VERSION;
1168
1169 switch(dwSource) {
1170 case MIXER_SRC_MONOIN:
1171 case MIXER_SRC_PHONE:
1172 pline->cChannels = 1;
1173 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE;
1174 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1175 break;
1176
1177 case MIXER_SRC_MIC:
1178 pline->cChannels = 1;
1179 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
1180 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1181 break;
1182
1183 case MIXER_SRC_LINE:
1184 pline->cChannels = 2;
1185 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE;
1186 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1187 break;
1188
1189 case MIXER_SRC_CD:
1190 pline->cChannels = 2;
1191 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
1192 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1193 break;
1194
1195 case MIXER_SRC_SPDIF:
1196 pline->cChannels = 2;
1197 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL;
1198 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1199 break;
1200
1201 case MIXER_SRC_VIDEO:
1202 pline->cChannels = 2;
1203 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED;
1204 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1205 break;
1206
1207 case MIXER_SRC_AUX:
1208 pline->cChannels = 2;
1209 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
1210 pline->Target.dwType = MIXERLINE_TARGETTYPE_AUX;
1211 break;
1212
1213 case MIXER_SRC_PCM:
1214 pline->cChannels = 2;
1215 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
1216 pline->Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT;
1217 break;
1218
1219 case MIXER_SRC_WAVETABLE:
1220 case MIXER_SRC_MIDI:
1221 pline->cChannels = 2;
1222 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
1223 pline->Target.dwType = MIXERLINE_TARGETTYPE_MIDIOUT;
1224 break;
1225
1226 default:
1227 DebugInt3();
1228 return NULL;
1229 }
1230 strncpy(pline->szShortName, szSourceName[dwSource][0], sizeof(pline->szShortName));
1231 strncpy(pline->szName, szSourceName[dwSource][1], sizeof(pline->szName));
1232 strncpy(pline->Target.szPname, WINMM_MIXERSTRING_A, sizeof(pline->Target.szPname));
1233
1234 dprintf(("Adding Source %s (%s)", pline->szName, pline->szShortName));
1235 nrSources++;
1236
1237 mixerDestInputs[MIXER_DEST_LINEOUT][nrLineOutInputs] = pline->dwSource;
1238 nrLineOutInputs++;
1239
1240 pline->dwLineID = nrLines;
1241 pmixerLines[nrLines] = pline;
1242 nrLines++;
1243
1244 //increase nr of inputs at destination line
1245 pDestLine->cConnections++;
1246
1247 //store line id in source to line mapping array
1248 mixerSourceLineId[dwSource] = pline->dwLineID;
1249
1250 return pline;
1251}
1252/******************************************************************************/
1253/******************************************************************************/
1254static MIXERLINEA *mixerAddDestination(DWORD dwDest)
1255{
1256 MIXERLINEA *pline = &mixerDest[nrDestinations];
1257
1258 if(nrDestinations >= MAX_MIXER_DESTINATIONS) {
1259 dprintf(("ERROR: mixerAddDestination: out of room!!!"));
1260 DebugInt3();
1261 return NULL;
1262 }
1263 memset(pline, 0, sizeof(MIXERLINEA));
1264 pline->cbStruct = sizeof(MIXERLINEA);
1265 pline->cConnections = 0;
1266 pline->cControls = 0;
1267 pline->dwSource = (DWORD)-1;
1268 pline->dwDestination = nrDestinations;
1269
1270 switch(dwDest) {
1271 case MIXER_DEST_LINEOUT:
1272 pline->cChannels = 2;
1273 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
1274 pline->fdwLine = MIXERLINE_LINEF_ACTIVE;
1275 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1276 break;
1277
1278 case MIXER_DEST_SPDIFOUT:
1279 pline->cChannels = 2;
1280 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_DIGITAL;
1281 pline->fdwLine = MIXERLINE_LINEF_ACTIVE;
1282 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1283 break;
1284
1285 case MIXER_DEST_WAVEIN:
1286 pline->cChannels = 2;
1287 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
1288 pline->fdwLine = MIXERLINE_LINEF_ACTIVE;
1289 pline->Target.dwType = MIXERLINE_TARGETTYPE_WAVEIN;
1290 break;
1291
1292 default:
1293 DebugInt3();
1294 return NULL;
1295 }
1296 strncpy(pline->szShortName, szDestName[dwDest][0], sizeof(pline->szShortName));
1297 strncpy(pline->szName, szDestName[dwDest][1], sizeof(pline->szName));
1298 strncpy(pline->Target.szPname, WINMM_MIXERSTRING_A, sizeof(pline->Target.szPname));
1299 pline->Target.dwDeviceID = 0;
1300 pline->Target.wMid = WINMM_MIXER_CAPS_WMID;
1301 pline->Target.wPid = WINMM_MIXER_CAPS_WPID;
1302 pline->Target.vDriverVersion = WINMM_MIXER_CAPS_VERSION;
1303
1304 dprintf(("Adding destination %s (%s) connections %d controls %d", pline->szName, pline->szShortName, pline->cConnections, pline->cControls));
1305 nrDestinations++;
1306
1307 pline->dwLineID = nrLines;
1308 pmixerLines[nrLines] = pline;
1309 nrLines++;
1310 return pline;
1311}
1312/******************************************************************************/
1313/******************************************************************************/
1314static int mixerWaveInVolToSource(DWORD dwControl)
1315{
1316 switch(dwControl) {
1317 case MIX_CTRL_VOL_IN_W_MONO:
1318 return MIXER_SRC_MONOIN;
1319 case MIX_CTRL_VOL_IN_W_PHONE:
1320 return MIXER_SRC_PHONE;
1321 case MIX_CTRL_VOL_IN_W_MIC:
1322 return MIXER_SRC_MIC;
1323 case MIX_CTRL_VOL_IN_W_LINE:
1324 return MIXER_SRC_LINE;
1325 case MIX_CTRL_VOL_IN_W_CD:
1326 return MIXER_SRC_CD;
1327 case MIX_CTRL_VOL_IN_W_SPDIF:
1328 return MIXER_SRC_SPDIF;
1329 case MIX_CTRL_VOL_IN_W_VIDEO:
1330 return MIXER_SRC_VIDEO;
1331 case MIX_CTRL_VOL_IN_W_AUX:
1332 return MIXER_SRC_AUX;
1333 case MIX_CTRL_VOL_IN_W_PCM:
1334 return MIXER_SRC_PCM;
1335 case MIX_CTRL_VOL_IN_W_WAVETABLE:
1336 return MIXER_SRC_WAVETABLE;
1337 case MIX_CTRL_VOL_IN_W_MIDI:
1338 return MIXER_SRC_MIDI;
1339 default:
1340 DebugInt3();
1341 return 0;
1342 }
1343}
1344/******************************************************************************/
1345/******************************************************************************/
1346static MIXERCONTROLA * mixerAddControl(MIXERLINEA *pDestLine, DWORD dwControl, MIXERLINEA *pSrcLine)
1347{
1348 MIXERCONTROLA *pctrl = &mixerControls[nrControls];
1349
1350 if(nrControls >= MAX_MIXER_CONTROLS) {
1351 dprintf(("ERROR: mixerAddControl: out of room!!!"));
1352 DebugInt3();
1353 return NULL;
1354 }
1355
1356 memset(pctrl, 0, sizeof(MIXERCONTROLA));
1357 pctrl->cbStruct = sizeof(MIXERCONTROLA);
1358 pctrl->cMultipleItems = 0;
1359 pctrl->dwControlID = nrControls;
1360 pctrl->fdwControl = 0;
1361 switch(dwControl) {
1362 case MIX_CTRL_MUX_IN_W_SRC:
1363 pctrl->fdwControl = MIXERCONTROL_CONTROLF_MULTIPLE | MIXERCONTROL_CONTROLF_UNIFORM;
1364 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;
1365 pctrl->Bounds.s.lMinimum = 0;
1366 pctrl->Bounds.s.lMaximum = 1;
1367 pctrl->Metrics.cSteps = 1;
1368 pctrl->cMultipleItems = 0; //to be filled in later (see caller)
1369 break;
1370
1371 case MIX_CTRL_VOL_OUT_LINE:
1372 case MIX_CTRL_VOL_IN_L_MONO:
1373 case MIX_CTRL_VOL_IN_L_PHONE:
1374 case MIX_CTRL_VOL_IN_L_MIC:
1375 case MIX_CTRL_VOL_IN_L_LINE:
1376 case MIX_CTRL_VOL_IN_L_CD:
1377 case MIX_CTRL_VOL_IN_L_SPDIF:
1378 case MIX_CTRL_VOL_IN_L_VIDEO:
1379 case MIX_CTRL_VOL_IN_L_AUX:
1380 case MIX_CTRL_VOL_IN_L_PCM:
1381 case MIX_CTRL_VOL_IN_L_WAVETABLE:
1382 case MIX_CTRL_VOL_IN_L_MIDI:
1383 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1384 OSLibMixGetCtrlCaps(dwControl, &pctrl->Bounds.s.lMinimum, &pctrl->Bounds.s.lMaximum, &pctrl->Metrics.cSteps);
1385 break;
1386
1387 case MIX_CTRL_VOL_IN_W_MONO:
1388 case MIX_CTRL_VOL_IN_W_PHONE:
1389 case MIX_CTRL_VOL_IN_W_MIC:
1390 case MIX_CTRL_VOL_IN_W_LINE:
1391 case MIX_CTRL_VOL_IN_W_CD:
1392 case MIX_CTRL_VOL_IN_W_SPDIF:
1393 case MIX_CTRL_VOL_IN_W_VIDEO:
1394 case MIX_CTRL_VOL_IN_W_AUX:
1395 case MIX_CTRL_VOL_IN_W_PCM:
1396 case MIX_CTRL_VOL_IN_W_WAVETABLE:
1397 case MIX_CTRL_VOL_IN_W_MIDI:
1398 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1399 OSLibMixGetCtrlCaps(dwControl, &pctrl->Bounds.s.lMinimum, &pctrl->Bounds.s.lMaximum, &pctrl->Metrics.cSteps);
1400 mixerDestInputs[MIXER_DEST_WAVEIN][nrWaveInInputs] = mixerSourceLineId[mixerWaveInVolToSource(dwControl)];
1401 nrWaveInInputs++;
1402 break;
1403
1404 case MIX_CTRL_MUTE_OUT_LINE:
1405 case MIX_CTRL_MUTE_IN_L_MONO:
1406 case MIX_CTRL_MUTE_IN_L_PHONE:
1407 case MIX_CTRL_MUTE_IN_L_MIC:
1408 case MIX_CTRL_MUTE_IN_L_LINE:
1409 case MIX_CTRL_MUTE_IN_L_CD:
1410 case MIX_CTRL_MUTE_IN_L_SPDIF:
1411 case MIX_CTRL_MUTE_IN_L_VIDEO:
1412 case MIX_CTRL_MUTE_IN_L_AUX:
1413 case MIX_CTRL_MUTE_IN_L_PCM:
1414 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1415 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
1416 pctrl->Bounds.s.lMinimum = 0;
1417 pctrl->Bounds.s.lMaximum = 1;
1418 pctrl->Metrics.cSteps = 0;
1419 break;
1420
1421 case MIX_CTRL_VOL_OUT_SPDIF:
1422 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1423 OSLibMixGetCtrlCaps(dwControl, &pctrl->Bounds.s.lMinimum, &pctrl->Bounds.s.lMaximum, &pctrl->Metrics.cSteps);
1424 break;
1425
1426 case MIX_CTRL_MUTE_OUT_SPDIF:
1427 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1428 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
1429 pctrl->Bounds.s.lMinimum = 0;
1430 pctrl->Bounds.s.lMaximum = 1;
1431 pctrl->Metrics.cSteps = 0;
1432 break;
1433
1434 case MIX_CTRL_BOOST_IN_L_MIC:
1435 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1436 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_ONOFF;
1437 pctrl->Bounds.s.lMinimum = 0;
1438 pctrl->Bounds.s.lMaximum = 1;
1439 pctrl->Metrics.cSteps = 0;
1440 break;
1441
1442 case MIX_CTRL_OUT_L_3DDEPTH:
1443 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1444 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_FADER;
1445 OSLibMixGetCtrlCaps(dwControl, &pctrl->Bounds.s.lMinimum, &pctrl->Bounds.s.lMaximum, &pctrl->Metrics.cSteps);
1446 break;
1447
1448 case MIX_CTRL_OUT_L_3DCENTER:
1449 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1450 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_FADER;
1451 OSLibMixGetCtrlCaps(dwControl, &pctrl->Bounds.s.lMinimum, &pctrl->Bounds.s.lMaximum, &pctrl->Metrics.cSteps);
1452 break;
1453
1454 case MIX_CTRL_OUT_L_TREBLE:
1455 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_TREBLE;
1456 OSLibMixGetCtrlCaps(dwControl, &pctrl->Bounds.s.lMinimum, &pctrl->Bounds.s.lMaximum, &pctrl->Metrics.cSteps);
1457 break;
1458
1459 case MIX_CTRL_OUT_L_BASS:
1460 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_BASS;
1461 OSLibMixGetCtrlCaps(dwControl, &pctrl->Bounds.s.lMinimum, &pctrl->Bounds.s.lMaximum, &pctrl->Metrics.cSteps);
1462 break;
1463
1464 default:
1465 DebugInt3();
1466 return FALSE;
1467 }
1468
1469 //add control to list of controls associated with source line
1470 for(int i=0;i<MAX_SOURCE_CONTROLS;i++) {
1471 if(mixerLineControls[pSrcLine->dwLineID][i] == -1) {
1472 mixerLineControls[pSrcLine->dwLineID][i] = pctrl->dwControlID;
1473 break;
1474 }
1475 }
1476 if(i == MAX_SOURCE_CONTROLS) {
1477 DebugInt3();
1478 }
1479 //increase nr of controls of corresponding source line
1480 pSrcLine->cControls++;
1481
1482 strncpy(pctrl->szShortName, szCtrlName[dwControl][0], sizeof(pctrl->szShortName));
1483 strncpy(pctrl->szName, szCtrlName[dwControl][1], sizeof(pctrl->szName));
1484
1485 //save internal id
1486 mixerControlId[nrControls] = dwControl;
1487 nrControls++;
1488 dprintf(("Adding control %s (%s)", pctrl->szName, pctrl->szShortName));
1489 return pctrl;
1490}
1491/******************************************************************************/
1492/******************************************************************************/
1493
Note: See TracBrowser for help on using the repository browser.