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

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

fix for soundcards without ioctl90 support

File size: 54.8 KB
Line 
1/* $Id: mixer.cpp,v 1.16 2002-05-25 08:07:59 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", lpMlc->cControls, lpMlc->cbmxctrl));
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_INVALVALUE;
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 dprintf(("MIXER_GETLINEINFOF_COMPONENTTYPE"));
652 switch (lpMl->dwComponentType)
653 {
654 case MIXERLINE_COMPONENTTYPE_DST_UNDEFINED:
655 dprintf(("MIXERLINE_COMPONENTTYPE_DST_UNDEFINED"));
656 break;
657 case MIXERLINE_COMPONENTTYPE_DST_DIGITAL:
658 dprintf(("MIXERLINE_COMPONENTTYPE_DST_DIGITAL"));
659 break;
660 case MIXERLINE_COMPONENTTYPE_DST_LINE:
661 dprintf(("MIXERLINE_COMPONENTTYPE_DST_LINE"));
662 break;
663 case MIXERLINE_COMPONENTTYPE_DST_MONITOR:
664 dprintf(("MIXERLINE_COMPONENTTYPE_DST_MONITOR"));
665 break;
666 case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS:
667 dprintf(("MIXERLINE_COMPONENTTYPE_DST_SPEAKERS"));
668 break;
669 case MIXERLINE_COMPONENTTYPE_DST_HEADPHONES:
670 dprintf(("MIXERLINE_COMPONENTTYPE_DST_HEADPHONES"));
671 break;
672 case MIXERLINE_COMPONENTTYPE_DST_TELEPHONE:
673 dprintf(("MIXERLINE_COMPONENTTYPE_DST_TELEPHONE"));
674 break;
675 case MIXERLINE_COMPONENTTYPE_DST_WAVEIN:
676 dprintf(("MIXERLINE_COMPONENTTYPE_DST_WAVEIN"));
677 break;
678 case MIXERLINE_COMPONENTTYPE_DST_VOICEIN:
679 dprintf(("MIXERLINE_COMPONENTTYPE_DST_VOICEIN"));
680 break;
681 default:
682 dprintf(("Unhandled component type (%08lx)\n", lpMl->dwComponentType));
683 return MMSYSERR_INVALPARAM;
684 }
685 return MIXERR_INVALLINE;
686 break;
687
688 case MIXER_GETLINEINFOF_TARGETTYPE:
689 dprintf(("_TARGETTYPE not implemented yet.\n"));
690 return MIXERR_INVALLINE;
691 break;
692 default:
693 dprintf(("Unknown flag (%08lx)\n", fdwInfo & MIXER_GETLINEINFOF_QUERYMASK));
694 return MMSYSERR_INVALPARAM;
695 break;
696 }
697 return MMSYSERR_NOERROR;
698}
699/******************************************************************************/
700/******************************************************************************/
701MMRESULT WINAPI mixerGetLineInfoW(HMIXEROBJ hmxobj, LPMIXERLINEW pmxl, DWORD fdwInfo)
702{
703 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
704 MIXERLINEA line;
705 MMRESULT result;
706
707 line.cbStruct = sizeof(MIXERLINEA);
708 line.cChannels = pmxl->cChannels;
709 line.cConnections = pmxl->cConnections;
710 line.dwComponentType = pmxl->dwComponentType;
711 line.dwDestination = pmxl->dwDestination;
712 line.dwLineID = pmxl->dwLineID;
713 line.dwSource = pmxl->dwSource;
714 line.dwUser = pmxl->dwUser;
715 line.fdwLine = pmxl->fdwLine;
716 line.szName[0] = 0;
717 line.szShortName[0] = 0;
718 line.Target.dwDeviceID = pmxl->Target.dwDeviceID;
719 line.Target.dwType = pmxl->Target.dwType;
720 line.Target.vDriverVersion = pmxl->Target.vDriverVersion;
721 line.Target.wMid = pmxl->Target.wMid;
722 line.Target.wPid = pmxl->Target.wPid;
723 line.Target.szPname[0] = 0;
724
725 result = mixerGetLineInfoA(hmxobj, &line, fdwInfo);
726 if(result != MMSYSERR_NOERROR) {
727 return result;
728 }
729 pmxl->cbStruct = sizeof(MIXERLINEA);
730 pmxl->cChannels = line.cChannels;
731 pmxl->cConnections = line.cConnections;
732 pmxl->dwComponentType = line.dwComponentType;
733 pmxl->dwDestination = line.dwDestination;
734 pmxl->dwLineID = line.dwLineID;
735 pmxl->dwSource = line.dwSource;
736 pmxl->dwUser = line.dwUser;
737 pmxl->fdwLine = line.fdwLine;
738 MultiByteToWideChar(CP_ACP, 0, line.szName, -1, pmxl->szName, sizeof(line.szName));
739 MultiByteToWideChar(CP_ACP, 0, line.szShortName, -1, pmxl->szShortName, sizeof(line.szShortName));
740 pmxl->Target.dwDeviceID = line.Target.dwDeviceID;
741 pmxl->Target.dwType = line.Target.dwType;
742 pmxl->Target.vDriverVersion = line.Target.vDriverVersion;
743 pmxl->Target.wMid = line.Target.wMid;
744 pmxl->Target.wPid = line.Target.wPid;
745 pmxl->Target.szPname[0] = 0;
746 MultiByteToWideChar(CP_ACP, 0, line.Target.szPname, -1, pmxl->Target.szPname, sizeof(line.Target.szPname));
747 return MMSYSERR_NOERROR;
748}
749/******************************************************************************/
750/******************************************************************************/
751MMRESULT WINAPI mixerMessage(HMIXER hmx, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
752{
753 dprintf(("WINMM:mixerMessage - stub\n" ));
754 return MMSYSERR_INVALPARAM;
755}
756/******************************************************************************/
757/******************************************************************************/
758UINT WINAPI mixerGetNumDevs()
759{
760 if(fMMPMAvailable == FALSE || DartWaveOut::getNumDevices() == 0) {
761 return 0;
762 }
763 return 1;
764}
765/******************************************************************************/
766/******************************************************************************/
767MMRESULT WINAPI mixerGetDevCapsA(UINT uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps)
768{
769 if(fMMPMAvailable == FALSE || DartWaveOut::getNumDevices() == 0) {
770 return MMSYSERR_BADDEVICEID;
771 }
772
773 if(uMxId > 0) {
774 return MMSYSERR_BADDEVICEID;
775 }
776
777 //According to MSDN, nothing is copied when cbmxcaps is zero
778 if(cbmxcaps >= sizeof(MIXERCAPSA)) {
779 // we have to fill in this thing
780 pmxcaps->wMid = 0; /* manufacturer ID */
781 pmxcaps->wPid = 0; /* product ID */
782 pmxcaps->vDriverVersion = 0x0001; /* version of the driver */
783 strcpy( pmxcaps->szPname, WINMM_MIXERSTRING_A); /* product name */
784
785 pmxcaps->fdwSupport = 0; //no mixer flags exist
786 pmxcaps->cDestinations = nrDestinations;
787 dprintf(("mixerGetDevCapsA: cDestinations %d", pmxcaps->cDestinations));
788 }
789
790 return MMSYSERR_NOERROR;
791}
792/******************************************************************************/
793/******************************************************************************/
794MMRESULT WINAPI mixerGetDevCapsW(UINT uMxId, LPMIXERCAPSW pmxcaps, UINT cbmxcaps)
795{
796 if(fMMPMAvailable == FALSE || DartWaveOut::getNumDevices() == 0) {
797 return MMSYSERR_BADDEVICEID;
798 }
799
800 if(uMxId > 0) {
801 return MMSYSERR_BADDEVICEID;
802 }
803
804 //According to MSDN, nothing is copied when cbmxcaps is zero
805 if(cbmxcaps >= sizeof(MIXERCAPSW)) {
806 // we have to fill in this thing
807 pmxcaps->wMid = 0; /* manufacturer ID */
808 pmxcaps->wPid = 0; /* product ID */
809 pmxcaps->vDriverVersion = 0x0001; /* version of the driver */
810 lstrcpyW( pmxcaps->szPname, WINMM_MIXERSTRING_W ); /* product name */
811
812 pmxcaps->fdwSupport = 0; //no mixer flags exist
813 pmxcaps->cDestinations = nrDestinations;
814 dprintf(("mixerGetDevCapsW: cDestinations %d", pmxcaps->cDestinations));
815 }
816
817 return MMSYSERR_NOERROR;
818}
819/******************************************************************************/
820/******************************************************************************/
821MMRESULT WINAPI mixerGetID(HMIXEROBJ hmxobj, UINT * puMxId, DWORD fdwId)
822{
823 switch(fdwId) {
824 case MIXER_OBJECTF_MIXER:
825 {
826 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
827 if(!pMixInfo) {
828 if(puMxId) {
829 *puMxId = -1;
830 }
831 return MMSYSERR_INVALHANDLE;
832 }
833 if(puMxId) {
834 *puMxId = pMixInfo->uDeviceID;
835 }
836 break;
837 }
838
839 case MIXER_OBJECTF_HMIXER:
840 case MIXER_OBJECTF_WAVEOUT:
841 case MIXER_OBJECTF_HWAVEOUT:
842 case MIXER_OBJECTF_WAVEIN:
843 case MIXER_OBJECTF_HWAVEIN:
844 case MIXER_OBJECTF_MIDIOUT:
845 case MIXER_OBJECTF_HMIDIOUT:
846 case MIXER_OBJECTF_MIDIIN:
847 case MIXER_OBJECTF_HMIDIIN:
848 case MIXER_OBJECTF_AUX:
849 //TODO: assume default mixer
850 if(puMxId) {
851 *puMxId = 0;
852 }
853 break;
854 default:
855 if(puMxId) {
856 *puMxId = -1;
857 }
858 return MMSYSERR_INVALPARAM;
859 }
860 return MMSYSERR_NOERROR;
861}
862/******************************************************************************/
863/******************************************************************************/
864MMRESULT WINAPI mixerOpen(LPHMIXER phmx, UINT uMxId, DWORD dwCallback, DWORD dwInstance,
865 DWORD fdwOpen)
866{
867 DEVICE_STRUCT *pMixInfo;
868
869 if(DartWaveOut::getNumDevices() == 0) {
870 if(phmx) *phmx = 0;
871 return MMSYSERR_NODRIVER;
872 }
873 pMixInfo = (DEVICE_STRUCT *)malloc(sizeof(DEVICE_STRUCT));
874 if(pMixInfo == NULL) {
875 return MMSYSERR_NODRIVER;
876 }
877 pMixInfo->dwCallback = dwCallback;
878 pMixInfo->dwDriverInstance = dwInstance;
879 pMixInfo->dwFlags = fdwOpen;
880 pMixInfo->uDeviceID = uMxId;
881 pMixInfo->type = WINMM_MIXER;
882 if(phmx)
883 *phmx = (HMIXER)pMixInfo;
884
885 return MMSYSERR_NOERROR;
886}
887/******************************************************************************/
888/******************************************************************************/
889MMRESULT WINAPI mixerClose(HMIXER hmx)
890{
891 if(hmx) {
892 free((void *)hmx);
893 }
894 return MMSYSERR_NOERROR;
895}
896/******************************************************************************/
897/******************************************************************************/
898BOOL mixerInit()
899{
900 MIXERLINEA *pDestLine;
901 MIXERCONTROLA *pLineOutMix;
902 MIXERCONTROLA *pWaveInMux;
903
904 if(!fMMPMAvailable) return TRUE;
905
906 memset(mixerSourceLineId, -1, sizeof(mixerSourceLineId));
907 memset(mixerLineControls, -1, sizeof(mixerLineControls));
908 memset(mixerDestInputs, -1, sizeof(mixerDestInputs));
909
910 if(OSLibMixerOpen() == TRUE) {
911 //Line out destination
912 pDestLine = mixerAddDestination(MIXER_DEST_LINEOUT);
913
914 pLineOutMix = mixerAddControl(pDestLine, MIX_CTRL_MIX_OUT_LINE, pDestLine);
915 mixerAddControl(pDestLine, MIX_CTRL_VOL_OUT_LINE, pDestLine);
916 mixerAddControl(pDestLine, MIX_CTRL_MUTE_OUT_LINE, pDestLine);
917 pLineOutMix->cMultipleItems = pDestLine->cConnections;
918
919 //WaveIn destination
920 pDestLine = mixerAddDestination(MIXER_DEST_WAVEIN);
921 pWaveInMux = mixerAddControl(pDestLine, MIX_CTRL_MUX_IN_W_SRC, pDestLine);
922 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MIC, pDestLine);
923 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_LINE, pDestLine);
924 pWaveInMux->cMultipleItems = pDestLine->cConnections;
925 return TRUE;
926 }
927 //Line out destination
928 pDestLine = mixerAddDestination(MIXER_DEST_LINEOUT);
929
930 pLineOutMix = mixerAddControl(pDestLine, MIX_CTRL_MIX_OUT_LINE, pDestLine);
931
932 mixerAddControl(pDestLine, MIX_CTRL_VOL_OUT_LINE, pDestLine);
933 mixerAddControl(pDestLine, MIX_CTRL_MUTE_OUT_LINE, pDestLine);
934 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_3DCENTER)) {
935 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_3DCENTER, pDestLine);
936 }
937 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_3DDEPTH)) {
938 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_3DDEPTH, pDestLine);
939 }
940 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_TREBLE)) {
941 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_TREBLE, pDestLine);
942 }
943 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_BASS)) {
944 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_BASS, pDestLine);
945 }
946
947 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_PCM)) {
948 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_PCM);
949 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_PCM, pLine);
950 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_PCM, pLine);
951 }
952 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_WAVETABLE)) {
953 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_WAVETABLE);
954 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_WAVETABLE, pLine);
955 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_WAVETABLE, pLine);
956 }
957 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_MIDI)) {
958 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_MIDI);
959 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_MIDI, pLine);
960 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_MIDI, pLine);
961 }
962 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_MIC)) {
963 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_MIC);
964 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_MIC, pLine);
965 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_MIC, pLine);
966 if(OSLibMixIsControlPresent(MIX_CTRL_BOOST_IN_L_MIC)) {
967 mixerAddControl(pDestLine, MIX_CTRL_BOOST_IN_L_MIC, pLine);
968 }
969 }
970 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_LINE)) {
971 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_LINE);
972 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_LINE, pLine);
973 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_LINE, pLine);
974 }
975 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_CD)) {
976 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_CD);
977 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_CD, pLine);
978 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_CD, pLine);
979 }
980 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_AUX)) {
981 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_AUX);
982 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_AUX, pLine);
983 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_AUX, pLine);
984 }
985 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_SPDIF)) {
986 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_SPDIF);
987 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_SPDIF, pLine);
988 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_SPDIF, pLine);
989 }
990 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_MONO)) {
991 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_MONOIN);
992 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_MONO, pLine);
993 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_MONO, pLine);
994 }
995 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_PHONE)) {
996 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_PHONE);
997 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_PHONE, pLine);
998 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_PHONE, pLine);
999 }
1000 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_VIDEO)) {
1001 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_VIDEO);
1002 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_VIDEO, pLine);
1003 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_VIDEO, pLine);
1004 }
1005 pLineOutMix->cMultipleItems = pDestLine->cConnections;
1006
1007 //Wave In Destination
1008 if(OSLibMixIsControlPresent(MIX_CTRL_MUX_IN_W_SRC)) {
1009 pDestLine = mixerAddDestination(MIXER_DEST_WAVEIN);
1010 pWaveInMux = mixerAddControl(pDestLine, MIX_CTRL_MUX_IN_W_SRC, pDestLine);
1011
1012 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_MIC)) {
1013 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MIC, pDestLine);
1014 }
1015 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_LINE)) {
1016 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_LINE, pDestLine);
1017 }
1018 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_CD)) {
1019 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_CD, pDestLine);
1020 }
1021 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_AUX)) {
1022 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_AUX, pDestLine);
1023 }
1024 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_PCM)) {
1025 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_PCM, pDestLine);
1026 }
1027 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_WAVETABLE)) {
1028 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_WAVETABLE, pDestLine);
1029 }
1030 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_MIDI)) {
1031 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MIDI, pDestLine);
1032 }
1033 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_MONO)) {
1034 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MONO, pDestLine);
1035 }
1036 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_PHONE)) {
1037 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_PHONE, pDestLine);
1038 }
1039 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_SPDIF)) {
1040 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_SPDIF, pDestLine);
1041 }
1042 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_VIDEO)) {
1043 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_VIDEO, pDestLine);
1044 }
1045 pWaveInMux->cMultipleItems = pDestLine->cConnections;
1046 }
1047
1048 //SPDIF destination
1049 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_OUT_SPDIF)) {
1050 pDestLine = mixerAddDestination(MIXER_DEST_SPDIFOUT);
1051 mixerAddControl(pDestLine, MIX_CTRL_VOL_OUT_SPDIF, pDestLine);
1052 mixerAddControl(pDestLine, MIX_CTRL_MUTE_OUT_SPDIF, pDestLine);
1053 }
1054
1055 return TRUE;
1056}
1057/******************************************************************************/
1058/******************************************************************************/
1059void mixerExit()
1060{
1061 OSLibMixerClose();
1062}
1063/******************************************************************************/
1064/******************************************************************************/
1065static MIXERLINEA *mixerAddSource(MIXERLINEA *pDestLine, DWORD dwSource)
1066{
1067 MIXERLINEA *pline = &mixerSource[nrSources];
1068
1069 if(nrSources >= MAX_MIXER_SOURCES) {
1070 dprintf(("ERROR: mixerAddSource: out of room!!!"));
1071 DebugInt3();
1072 return NULL;
1073 }
1074
1075 pline->cbStruct = sizeof(MIXERLINEA);
1076 memset(pline, 0, sizeof(MIXERLINEA));
1077
1078 pline->cConnections = 0;
1079 pline->cControls = 0;
1080 pline->dwDestination = 0;
1081 pline->fdwLine = MIXERLINE_LINEF_SOURCE;
1082 pline->dwSource = nrSources;
1083
1084 switch(dwSource) {
1085 case MIXER_SRC_MONOIN:
1086 case MIXER_SRC_PHONE:
1087 pline->cChannels = 1;
1088 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE;
1089 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1090 break;
1091
1092 case MIXER_SRC_MIC:
1093 pline->cChannels = 1;
1094 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
1095 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1096 break;
1097
1098 case MIXER_SRC_LINE:
1099 pline->cChannels = 2;
1100 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE;
1101 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1102 break;
1103
1104 case MIXER_SRC_CD:
1105 pline->cChannels = 2;
1106 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
1107 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1108 break;
1109
1110 case MIXER_SRC_SPDIF:
1111 pline->cChannels = 2;
1112 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL;
1113 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1114 break;
1115
1116 case MIXER_SRC_VIDEO:
1117 pline->cChannels = 2;
1118 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED;
1119 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1120 break;
1121
1122 case MIXER_SRC_AUX:
1123 pline->cChannels = 2;
1124 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
1125 pline->Target.dwType = MIXERLINE_TARGETTYPE_AUX;
1126 break;
1127
1128 case MIXER_SRC_PCM:
1129 pline->cChannels = 2;
1130 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
1131 pline->Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT;
1132 break;
1133
1134 case MIXER_SRC_WAVETABLE:
1135 case MIXER_SRC_MIDI:
1136 pline->cChannels = 2;
1137 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
1138 pline->Target.dwType = MIXERLINE_TARGETTYPE_MIDIOUT;
1139 break;
1140
1141 default:
1142 DebugInt3();
1143 return NULL;
1144 }
1145 strncpy(pline->szShortName, szSourceName[dwSource][0], sizeof(pline->szShortName));
1146 strncpy(pline->szName, szSourceName[dwSource][1], sizeof(pline->szName));
1147
1148 dprintf(("Adding Source %s (%s)", pline->szName, pline->szShortName));
1149 nrSources++;
1150
1151 mixerDestInputs[MIXER_DEST_LINEOUT][nrLineOutInputs] = pline->dwSource;
1152 nrLineOutInputs++;
1153
1154 pline->dwLineID = nrLines;
1155 pmixerLines[nrLines] = pline;
1156 nrLines++;
1157
1158 //increase nr of inputs at destinateion line
1159 pDestLine->cConnections++;
1160
1161 //store line id in source to line mapping array
1162 mixerSourceLineId[dwSource] = pline->dwLineID;
1163
1164 return pline;
1165}
1166/******************************************************************************/
1167/******************************************************************************/
1168static MIXERLINEA *mixerAddDestination(DWORD dwDest)
1169{
1170 MIXERLINEA *pline = &mixerDest[nrDestinations];
1171
1172 if(nrDestinations >= MAX_MIXER_DESTINATIONS) {
1173 dprintf(("ERROR: mixerAddDestination: out of room!!!"));
1174 DebugInt3();
1175 return NULL;
1176 }
1177 pline->cbStruct = sizeof(MIXERLINEA);
1178 memset(pline, 0, sizeof(MIXERLINEA));
1179
1180 switch(dwDest) {
1181 case MIXER_DEST_LINEOUT:
1182 pline->dwDestination = nrDestinations;
1183 pline->cChannels = 2;
1184 pline->cConnections = 0;
1185 pline->cControls = 0;
1186 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
1187 pline->dwSource = 0;
1188 pline->fdwLine = MIXERLINE_LINEF_ACTIVE;
1189 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1190 break;
1191
1192 case MIXER_DEST_SPDIFOUT:
1193 pline->dwDestination = nrDestinations;
1194 pline->cChannels = 2;
1195 pline->cConnections = 0;
1196 pline->cControls = 0;
1197 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_DIGITAL;
1198 pline->dwSource = 0;
1199 pline->fdwLine = MIXERLINE_LINEF_ACTIVE;
1200 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1201 break;
1202
1203 case MIXER_DEST_WAVEIN:
1204 pline->dwSource = nrDestinations;
1205 pline->cChannels = 2;
1206 pline->cConnections = 0;
1207 pline->cControls = 0;
1208 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
1209 pline->dwDestination = 0;
1210 pline->fdwLine = MIXERLINE_LINEF_SOURCE;
1211 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1212 break;
1213
1214 default:
1215 DebugInt3();
1216 return NULL;
1217 }
1218 strncpy(pline->szShortName, szDestName[dwDest][0], sizeof(pline->szShortName));
1219 strncpy(pline->szName, szDestName[dwDest][1], sizeof(pline->szName));
1220 dprintf(("Adding destination %s (%s) connections %d controls %d", pline->szName, pline->szShortName, pline->cConnections, pline->cControls));
1221 nrDestinations++;
1222
1223 pline->dwLineID = nrLines;
1224 pmixerLines[nrLines] = pline;
1225 nrLines++;
1226 return pline;
1227}
1228/******************************************************************************/
1229/******************************************************************************/
1230static int mixerWaveInVolToSource(DWORD dwControl)
1231{
1232 switch(dwControl) {
1233 case MIX_CTRL_VOL_IN_W_MONO:
1234 return MIXER_SRC_MONOIN;
1235 case MIX_CTRL_VOL_IN_W_PHONE:
1236 return MIXER_SRC_PHONE;
1237 case MIX_CTRL_VOL_IN_W_MIC:
1238 return MIXER_SRC_MIC;
1239 case MIX_CTRL_VOL_IN_W_LINE:
1240 return MIXER_SRC_LINE;
1241 case MIX_CTRL_VOL_IN_W_CD:
1242 return MIXER_SRC_CD;
1243 case MIX_CTRL_VOL_IN_W_SPDIF:
1244 return MIXER_SRC_SPDIF;
1245 case MIX_CTRL_VOL_IN_W_VIDEO:
1246 return MIXER_SRC_VIDEO;
1247 case MIX_CTRL_VOL_IN_W_AUX:
1248 return MIXER_SRC_AUX;
1249 case MIX_CTRL_VOL_IN_W_PCM:
1250 return MIXER_SRC_PCM;
1251 case MIX_CTRL_VOL_IN_W_WAVETABLE:
1252 return MIXER_SRC_WAVETABLE;
1253 case MIX_CTRL_VOL_IN_W_MIDI:
1254 return MIXER_SRC_MIDI;
1255 default:
1256 DebugInt3();
1257 return 0;
1258 }
1259}
1260/******************************************************************************/
1261/******************************************************************************/
1262static MIXERCONTROLA * mixerAddControl(MIXERLINEA *pDestLine, DWORD dwControl, MIXERLINEA *pSrcLine)
1263{
1264 MIXERCONTROLA *pctrl = &mixerControls[nrControls];
1265
1266 if(nrControls >= MAX_MIXER_CONTROLS) {
1267 dprintf(("ERROR: mixerAddControl: out of room!!!"));
1268 DebugInt3();
1269 return NULL;
1270 }
1271
1272 pctrl->cbStruct = sizeof(MIXERCONTROLA);
1273 memset(pctrl, 0, sizeof(MIXERCONTROLA));
1274
1275 pctrl->cMultipleItems = 0;
1276 pctrl->dwControlID = nrControls;
1277 pctrl->fdwControl = 0;
1278 switch(dwControl) {
1279 case MIX_CTRL_MIX_OUT_LINE:
1280 pctrl->fdwControl = MIXERCONTROL_CONTROLF_MULTIPLE | MIXERCONTROL_CONTROLF_UNIFORM;
1281 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MIXER;
1282 pctrl->Bounds.s.lMinimum = 0;
1283 pctrl->Bounds.s.lMaximum = 1;
1284 pctrl->Metrics.cSteps = 1;
1285 pctrl->cMultipleItems = 0; //to be filled in later (see caller)
1286 break;
1287
1288 case MIX_CTRL_MUX_IN_W_SRC:
1289 pctrl->fdwControl = MIXERCONTROL_CONTROLF_MULTIPLE | MIXERCONTROL_CONTROLF_UNIFORM;
1290 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;
1291 pctrl->Bounds.s.lMinimum = 0;
1292 pctrl->Bounds.s.lMaximum = 1;
1293 pctrl->Metrics.cSteps = 1;
1294 pctrl->cMultipleItems = 0; //to be filled in later (see caller)
1295 break;
1296
1297 case MIX_CTRL_VOL_OUT_LINE:
1298 case MIX_CTRL_VOL_IN_L_MONO:
1299 case MIX_CTRL_VOL_IN_L_PHONE:
1300 case MIX_CTRL_VOL_IN_L_MIC:
1301 case MIX_CTRL_VOL_IN_L_LINE:
1302 case MIX_CTRL_VOL_IN_L_CD:
1303 case MIX_CTRL_VOL_IN_L_SPDIF:
1304 case MIX_CTRL_VOL_IN_L_VIDEO:
1305 case MIX_CTRL_VOL_IN_L_AUX:
1306 case MIX_CTRL_VOL_IN_L_PCM:
1307 case MIX_CTRL_VOL_IN_L_WAVETABLE:
1308 case MIX_CTRL_VOL_IN_L_MIDI:
1309 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1310 pctrl->Bounds.s.lMinimum = 0;
1311 pctrl->Bounds.s.lMaximum = 100;
1312 pctrl->Metrics.cSteps = 1;
1313 break;
1314
1315 case MIX_CTRL_VOL_IN_W_MONO:
1316 case MIX_CTRL_VOL_IN_W_PHONE:
1317 case MIX_CTRL_VOL_IN_W_MIC:
1318 case MIX_CTRL_VOL_IN_W_LINE:
1319 case MIX_CTRL_VOL_IN_W_CD:
1320 case MIX_CTRL_VOL_IN_W_SPDIF:
1321 case MIX_CTRL_VOL_IN_W_VIDEO:
1322 case MIX_CTRL_VOL_IN_W_AUX:
1323 case MIX_CTRL_VOL_IN_W_PCM:
1324 case MIX_CTRL_VOL_IN_W_WAVETABLE:
1325 case MIX_CTRL_VOL_IN_W_MIDI:
1326 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1327 pctrl->Bounds.s.lMinimum = 0;
1328 pctrl->Bounds.s.lMaximum = 100;
1329 pctrl->Metrics.cSteps = 1;
1330 mixerDestInputs[MIXER_DEST_WAVEIN][nrWaveInInputs] = mixerSourceLineId[mixerWaveInVolToSource(dwControl)];
1331 nrWaveInInputs++;
1332 break;
1333
1334 case MIX_CTRL_MUTE_OUT_LINE:
1335 case MIX_CTRL_MUTE_IN_L_MONO:
1336 case MIX_CTRL_MUTE_IN_L_PHONE:
1337 case MIX_CTRL_MUTE_IN_L_MIC:
1338 case MIX_CTRL_MUTE_IN_L_LINE:
1339 case MIX_CTRL_MUTE_IN_L_CD:
1340 case MIX_CTRL_MUTE_IN_L_SPDIF:
1341 case MIX_CTRL_MUTE_IN_L_VIDEO:
1342 case MIX_CTRL_MUTE_IN_L_AUX:
1343 case MIX_CTRL_MUTE_IN_L_PCM:
1344 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1345 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
1346 pctrl->Bounds.s.lMinimum = 0;
1347 pctrl->Bounds.s.lMaximum = 1;
1348 pctrl->Metrics.cSteps = 0;
1349 break;
1350
1351 case MIX_CTRL_VOL_OUT_SPDIF:
1352 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1353 pctrl->Bounds.s.lMinimum = 0;
1354 pctrl->Bounds.s.lMaximum = 100;
1355 pctrl->Metrics.cSteps = 1;
1356 break;
1357
1358 case MIX_CTRL_MUTE_OUT_SPDIF:
1359 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1360 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
1361 pctrl->Bounds.s.lMinimum = 0;
1362 pctrl->Bounds.s.lMaximum = 1;
1363 pctrl->Metrics.cSteps = 0;
1364 break;
1365
1366 case MIX_CTRL_BOOST_IN_L_MIC:
1367 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1368 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_ONOFF;
1369 pctrl->Bounds.s.lMinimum = 0;
1370 pctrl->Bounds.s.lMaximum = 1;
1371 pctrl->Metrics.cSteps = 0;
1372 break;
1373
1374 case MIX_CTRL_OUT_L_3DDEPTH:
1375 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1376 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_FADER;
1377 pctrl->Bounds.s.lMinimum = 0;
1378 pctrl->Bounds.s.lMaximum = 100;
1379 pctrl->Metrics.cSteps = 1;
1380 break;
1381
1382 case MIX_CTRL_OUT_L_3DCENTER:
1383 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1384 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_FADER;
1385 pctrl->Bounds.s.lMinimum = 0;
1386 pctrl->Bounds.s.lMaximum = 100;
1387 pctrl->Metrics.cSteps = 1;
1388 break;
1389
1390 case MIX_CTRL_OUT_L_TREBLE:
1391 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_TREBLE;
1392 pctrl->Bounds.s.lMinimum = 0;
1393 pctrl->Bounds.s.lMaximum = 100;
1394 pctrl->Metrics.cSteps = 1;
1395 break;
1396
1397 case MIX_CTRL_OUT_L_BASS:
1398 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_BASS;
1399 pctrl->Bounds.s.lMinimum = 0;
1400 pctrl->Bounds.s.lMaximum = 100;
1401 pctrl->Metrics.cSteps = 1;
1402 break;
1403
1404 default:
1405 DebugInt3();
1406 return FALSE;
1407 }
1408 //increase nr of controls of corresponding destinateion line
1409 pDestLine->cControls++;
1410
1411 //add control to list of controls associated with source line
1412 for(int i=0;i<MAX_SOURCE_CONTROLS;i++) {
1413 if(mixerLineControls[pSrcLine->dwLineID][i] == -1) {
1414 mixerLineControls[pSrcLine->dwLineID][i] = pctrl->dwControlID;
1415 break;
1416 }
1417 }
1418 if(i == MAX_SOURCE_CONTROLS) {
1419 DebugInt3();
1420 }
1421
1422 strncpy(pctrl->szShortName, szCtrlName[dwControl][0], sizeof(pctrl->szShortName));
1423 strncpy(pctrl->szName, szCtrlName[dwControl][1], sizeof(pctrl->szName));
1424
1425 //save internal id
1426 mixerControlId[nrControls] = dwControl;
1427 nrControls++;
1428 dprintf(("Adding control %s (%s)", pctrl->szName, pctrl->szShortName));
1429 return pctrl;
1430}
1431/******************************************************************************/
1432/******************************************************************************/
1433
Note: See TracBrowser for help on using the repository browser.