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

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

mixer updates

File size: 45.8 KB
Line 
1/* $Id: mixer.cpp,v 1.14 2002-05-23 20:42:06 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 BOOL 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
62static int nrDestinations = 0;
63static int nrSources = 0;
64static int nrControls = 0;
65static int nrLines = 0;
66static int nrLineOutInputs = 0;
67static int nrWaveInInputs = 0;
68
69/******************************************************************************/
70/******************************************************************************/
71MMRESULT WINAPI mixerGetControlDetailsA(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails)
72{
73 DWORD lineID, controlType;
74 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
75
76 if(fdwDetails == MIXER_OBJECTF_HMIXER) {
77 if(!pMixInfo) {
78 return MMSYSERR_INVALHANDLE;
79 }
80 }
81 else
82 if(fdwDetails == MIXER_OBJECTF_MIXER) {
83 if(hmxobj > 0) {
84 return MMSYSERR_NODRIVER;
85 }
86 }
87
88 if (lpmcd == NULL) return MMSYSERR_INVALPARAM;
89
90 switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) {
91 case MIXER_GETCONTROLDETAILSF_VALUE:
92 break;
93 case MIXER_GETCONTROLDETAILSF_LISTTEXT:
94 dprintf(("mixerGetControlDetailsA: NIY\n"));
95 break;
96 default:
97 dprintf(("Unknown flag (%08lx)\n", fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK));
98 break;
99 }
100 return MMSYSERR_NOERROR;
101}
102/******************************************************************************/
103/******************************************************************************/
104MMRESULT WINAPI mixerGetControlDetailsW(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails)
105{
106 DWORD ret = MMSYSERR_NOTENABLED;
107
108 if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd))
109 return MMSYSERR_INVALPARAM;
110
111 switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) {
112 case MIXER_GETCONTROLDETAILSF_VALUE:
113 /* can safely use W structure as it is, no string inside */
114 ret = mixerGetControlDetailsA(hmxobj, lpmcd, fdwDetails);
115 break;
116
117 case MIXER_GETCONTROLDETAILSF_LISTTEXT:
118 {
119 LPVOID paDetailsW = lpmcd->paDetails;
120 int size = max(1, lpmcd->cChannels) * sizeof(MIXERCONTROLDETAILS_LISTTEXTA);
121
122 if (lpmcd->u.cMultipleItems != 0 && lpmcd->u.cMultipleItems != lpmcd->u.hwndOwner) {
123 size *= lpmcd->u.cMultipleItems;
124 }
125 lpmcd->paDetails = HeapAlloc(GetProcessHeap(), 0, size);
126 /* set up lpmcd->paDetails */
127 ret = mixerGetControlDetailsA(hmxobj, lpmcd, fdwDetails);
128 /* copy from lpmcd->paDetails back to paDetailsW; */
129 HeapFree(GetProcessHeap(), 0, lpmcd->paDetails);
130 lpmcd->paDetails = paDetailsW;
131 break;
132 }
133 default:
134 dprintf(("Unsupported fdwDetails=0x%08lx\n", fdwDetails));
135 break;
136 }
137
138 return ret;
139}
140/******************************************************************************/
141/******************************************************************************/
142MMRESULT WINAPI mixerSetControlDetails(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails)
143{
144 DWORD ret = MMSYSERR_NOTSUPPORTED;
145 DWORD lineID, controlType;
146 int val;
147 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
148
149 if(fdwDetails == MIXER_OBJECTF_HMIXER) {
150 if(!pMixInfo) {
151 return MMSYSERR_INVALHANDLE;
152 }
153 }
154 else
155 if(fdwDetails == MIXER_OBJECTF_MIXER) {
156 if(hmxobj > 0) {
157 return MMSYSERR_NODRIVER;
158 }
159 }
160 if (lpmcd == NULL) return MMSYSERR_INVALPARAM;
161
162 switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) {
163 case MIXER_GETCONTROLDETAILSF_VALUE:
164 break;
165 case MIXER_GETCONTROLDETAILSF_LISTTEXT:
166 dprintf(("mixerSetControlDetails: NIY\n"));
167 break;
168 default:
169 dprintf(("Unknown flag (%08lx)\n", fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK));
170 break;
171 }
172 return MMSYSERR_NOTSUPPORTED;
173}
174/******************************************************************************/
175/******************************************************************************/
176MMRESULT WINAPI mixerGetLineControlsA(HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA lpMlc, DWORD fdwControls)
177{
178 DWORD dwRet = MMSYSERR_NOERROR;
179 DWORD lineID, controlType;
180 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
181
182 if(fdwControls == MIXER_OBJECTF_HMIXER) {
183 if(!pMixInfo) {
184 return MMSYSERR_INVALHANDLE;
185 }
186 }
187 else
188 if(fdwControls == MIXER_OBJECTF_MIXER) {
189 if(hmxobj > 0) {
190 return MMSYSERR_NODRIVER;
191 }
192 }
193
194 if (lpMlc == NULL) return MMSYSERR_INVALPARAM;
195
196 if (lpMlc->cbStruct < sizeof(*lpMlc) || lpMlc->cbmxctrl < sizeof(MIXERCONTROLA))
197 return MMSYSERR_INVALPARAM;
198
199 switch(fdwControls & MIXER_GETLINECONTROLSF_QUERYMASK)
200 {
201 case MIXER_GETLINECONTROLSF_ALL:
202 dprintf(("MIXER_GETLINECONTROLSF_ALL"));
203 return MIXERR_INVALLINE;
204 break;
205
206 case MIXER_GETLINECONTROLSF_ONEBYID:
207 dprintf(("MIXER_GETLINECONTROLSF_ONEBYID %x", lpMlc->u.dwControlID));
208 if(lpMlc->cControls != 1 || lpMlc->cbmxctrl != sizeof(MIXERCONTROLA)) {
209 dprintf(("invalid parameters"));
210 return MMSYSERR_INVALPARAM;
211 }
212 if(lpMlc->u.dwControlID >= nrControls) {
213 dprintf(("invalid control"));
214 return MIXERR_INVALCONTROL;
215 }
216 memcpy(lpMlc->pamxctrl, &mixerControls[lpMlc->u.dwControlID], sizeof(MIXERCONTROLA));
217 dprintf(("found control %s (%s)", lpMlc->pamxctrl->szName, lpMlc->pamxctrl->szShortName));
218 break;
219
220 case MIXER_GETLINECONTROLSF_ONEBYTYPE:
221 {
222 dprintf(("MIXER_GETLINECONTROLSF_ONEBYTYPE %x %d", lpMlc->u.dwControlType, lpMlc->dwLineID));
223 if(lpMlc->dwLineID >= nrLines) {
224 dprintf(("ERROR: Invalid line %d", lpMlc->dwLineID));
225 return MIXERR_INVALLINE;
226 }
227#ifdef DEBUG
228 switch (lpMlc->u.dwControlType) {
229 case MIXERCONTROL_CONTROLTYPE_CUSTOM:
230 dprintf(("MIXERCONTROL_CONTROLTYPE_CUSTOM"));
231 break;
232 case MIXERCONTROL_CONTROLTYPE_BOOLEANMETER:
233 dprintf(("MIXERCONTROL_CONTROLTYPE_BOOLEANMETER"));
234 break;
235 case MIXERCONTROL_CONTROLTYPE_SIGNEDMETER:
236 dprintf(("MIXERCONTROL_CONTROLTYPE_SIGNEDMETER"));
237 break;
238 case MIXERCONTROL_CONTROLTYPE_PEAKMETER:
239 dprintf(("MIXERCONTROL_CONTROLTYPE_PEAKMETER"));
240 break;
241 case MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER:
242 dprintf(("MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER"));
243 break;
244 case MIXERCONTROL_CONTROLTYPE_BOOLEAN:
245 dprintf(("MIXERCONTROL_CONTROLTYPE_BOOLEAN"));
246 break;
247 case MIXERCONTROL_CONTROLTYPE_ONOFF:
248 dprintf(("MIXERCONTROL_CONTROLTYPE_ONOFF"));
249 break;
250 case MIXERCONTROL_CONTROLTYPE_MUTE:
251 dprintf(("MIXERCONTROL_CONTROLTYPE_MUTE"));
252 break;
253 case MIXERCONTROL_CONTROLTYPE_MONO:
254 dprintf(("MIXERCONTROL_CONTROLTYPE_MONO"));
255 break;
256 case MIXERCONTROL_CONTROLTYPE_LOUDNESS:
257 dprintf(("MIXERCONTROL_CONTROLTYPE_LOUDNESS"));
258 break;
259 case MIXERCONTROL_CONTROLTYPE_STEREOENH:
260 dprintf(("MIXERCONTROL_CONTROLTYPE_STEREOENH"));
261 break;
262 case MIXERCONTROL_CONTROLTYPE_BUTTON:
263 dprintf(("MIXERCONTROL_CONTROLTYPE_BUTTON"));
264 break;
265 case MIXERCONTROL_CONTROLTYPE_DECIBELS:
266 dprintf(("MIXERCONTROL_CONTROLTYPE_DECIBELS"));
267 break;
268 case MIXERCONTROL_CONTROLTYPE_SIGNED:
269 dprintf(("MIXERCONTROL_CONTROLTYPE_SIGNED"));
270 break;
271 case MIXERCONTROL_CONTROLTYPE_UNSIGNED:
272 dprintf(("MIXERCONTROL_CONTROLTYPE_UNSIGNED"));
273 break;
274 case MIXERCONTROL_CONTROLTYPE_PERCENT:
275 dprintf(("MIXERCONTROL_CONTROLTYPE_PERCENT"));
276 break;
277 case MIXERCONTROL_CONTROLTYPE_SLIDER:
278 dprintf(("MIXERCONTROL_CONTROLTYPE_SLIDER"));
279 break;
280 case MIXERCONTROL_CONTROLTYPE_PAN:
281 dprintf(("MIXERCONTROL_CONTROLTYPE_PAN"));
282 break;
283 case MIXERCONTROL_CONTROLTYPE_QSOUNDPAN:
284 dprintf(("MIXERCONTROL_CONTROLTYPE_QSOUNDPAN"));
285 break;
286 case MIXERCONTROL_CONTROLTYPE_FADER:
287 dprintf(("MIXERCONTROL_CONTROLTYPE_FADER"));
288 break;
289 case MIXERCONTROL_CONTROLTYPE_VOLUME:
290 dprintf(("MIXERCONTROL_CONTROLTYPE_VOLUME"));
291 break;
292 case MIXERCONTROL_CONTROLTYPE_BASS:
293 dprintf(("MIXERCONTROL_CONTROLTYPE_BASS"));
294 break;
295 case MIXERCONTROL_CONTROLTYPE_TREBLE:
296 dprintf(("MIXERCONTROL_CONTROLTYPE_TREBLE"));
297 break;
298 case MIXERCONTROL_CONTROLTYPE_EQUALIZER:
299 dprintf(("MIXERCONTROL_CONTROLTYPE_EQUALIZER"));
300 break;
301 case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
302 dprintf(("MIXERCONTROL_CONTROLTYPE_SINGLESELECT"));
303 break;
304 case MIXERCONTROL_CONTROLTYPE_MUX:
305 dprintf(("MIXERCONTROL_CONTROLTYPE_MUX"));
306 break;
307 case MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT:
308 dprintf(("MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT"));
309 break;
310 case MIXERCONTROL_CONTROLTYPE_MIXER:
311 dprintf(("MIXERCONTROL_CONTROLTYPE_MIXER"));
312 break;
313 case MIXERCONTROL_CONTROLTYPE_MICROTIME:
314 dprintf(("MIXERCONTROL_CONTROLTYPE_MICROTIME"));
315 break;
316 case MIXERCONTROL_CONTROLTYPE_MILLITIME:
317 dprintf(("MIXERCONTROL_CONTROLTYPE_MILLITIME"));
318 break;
319 default:
320 return MMSYSERR_INVALPARAM;
321 }
322#endif
323 int idx;
324
325 for(int i=0;i<MAX_SOURCE_CONTROLS;i++) {
326 idx = mixerLineControls[lpMlc->dwLineID][i];
327 if(idx == -1) break;
328 if(mixerControls[idx].dwControlType == lpMlc->u.dwControlType) {
329 memcpy(lpMlc->pamxctrl, &mixerControls[idx], sizeof(MIXERCONTROLA));
330 dprintf(("found control %s (%s)", lpMlc->pamxctrl->szName, lpMlc->pamxctrl->szShortName));
331 return MMSYSERR_NOERROR;
332 }
333
334 }
335 return MIXERR_INVALLINE;
336 }
337 default:
338 dprintf(("Unknown flag %08lx\n", fdwControls & MIXER_GETLINECONTROLSF_QUERYMASK));
339 dwRet = MMSYSERR_INVALPARAM;
340 break;
341 }
342
343 return dwRet;
344}
345/******************************************************************************/
346/******************************************************************************/
347MMRESULT WINAPI mixerGetLineControlsW(HMIXEROBJ hmxobj, LPMIXERLINECONTROLSW lpmlcW, DWORD fdwControls)
348{
349 MIXERLINECONTROLSA mlcA;
350 DWORD ret;
351 int i;
352
353 if (lpmlcW == NULL || lpmlcW->cbStruct != sizeof(*lpmlcW) || lpmlcW->cbmxctrl != sizeof(MIXERCONTROLW))
354 return MMSYSERR_INVALPARAM;
355
356 mlcA.cbStruct = sizeof(mlcA);
357 mlcA.dwLineID = lpmlcW->dwLineID;
358 mlcA.u.dwControlID = lpmlcW->u.dwControlID;
359 mlcA.u.dwControlType = lpmlcW->u.dwControlType;
360 mlcA.cControls = lpmlcW->cControls;
361 mlcA.cbmxctrl = sizeof(MIXERCONTROLA);
362 mlcA.pamxctrl = (MIXERCONTROLA *)HeapAlloc(GetProcessHeap(), 0, mlcA.cControls * mlcA.cbmxctrl);
363
364 ret = mixerGetLineControlsA(hmxobj, &mlcA, fdwControls);
365
366 if (ret == MMSYSERR_NOERROR) {
367 lpmlcW->dwLineID = mlcA.dwLineID;
368 lpmlcW->u.dwControlID = mlcA.u.dwControlID;
369 lpmlcW->u.dwControlType = mlcA.u.dwControlType;
370 lpmlcW->cControls = mlcA.cControls;
371
372 for (i = 0; i < mlcA.cControls; i++) {
373 lpmlcW->pamxctrl[i].cbStruct = sizeof(MIXERCONTROLW);
374 lpmlcW->pamxctrl[i].dwControlID = mlcA.pamxctrl[i].dwControlID;
375 lpmlcW->pamxctrl[i].dwControlType = mlcA.pamxctrl[i].dwControlType;
376 lpmlcW->pamxctrl[i].fdwControl = mlcA.pamxctrl[i].fdwControl;
377 lpmlcW->pamxctrl[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems;
378 MultiByteToWideChar( CP_ACP, 0, mlcA.pamxctrl[i].szShortName, -1,
379 lpmlcW->pamxctrl[i].szShortName,
380 sizeof(lpmlcW->pamxctrl[i].szShortName)/sizeof(WCHAR) );
381 MultiByteToWideChar( CP_ACP, 0, mlcA.pamxctrl[i].szName, -1,
382 lpmlcW->pamxctrl[i].szName,
383 sizeof(lpmlcW->pamxctrl[i].szName)/sizeof(WCHAR) );
384 /* sizeof(lpmlcW->pamxctrl[i].Bounds) ==
385 * sizeof(mlcA.pamxctrl[i].Bounds) */
386 memcpy(&lpmlcW->pamxctrl[i].Bounds, &mlcA.pamxctrl[i].Bounds,
387 sizeof(mlcA.pamxctrl[i].Bounds));
388 /* sizeof(lpmlcW->pamxctrl[i].Metrics) ==
389 * sizeof(mlcA.pamxctrl[i].Metrics) */
390 memcpy(&lpmlcW->pamxctrl[i].Metrics, &mlcA.pamxctrl[i].Metrics,
391 sizeof(mlcA.pamxctrl[i].Metrics));
392 }
393 }
394
395 HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl);
396 return ret;
397}
398/******************************************************************************/
399/******************************************************************************/
400MMRESULT WINAPI mixerGetLineInfoA(HMIXEROBJ hmxobj, LPMIXERLINEA lpMl, DWORD fdwInfo)
401{
402 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
403
404 if(fdwInfo & MIXER_OBJECTF_HMIXER) {
405 if(!pMixInfo) {
406 return MMSYSERR_INVALHANDLE;
407 }
408 }
409 else
410 if((fdwInfo & MIXER_OBJECTF_MIXER) == MIXER_OBJECTF_MIXER) {
411 if(hmxobj > 0) {
412 return MMSYSERR_NODRIVER;
413 }
414 }
415
416 if (lpMl == NULL || lpMl->cbStruct != sizeof(*lpMl)) {
417 dprintf(("ERROR: mixerGetLineInfoA: invalid paramter!!"));
418 return MMSYSERR_INVALPARAM;
419 }
420
421 switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK)
422 {
423 case MIXER_GETLINEINFOF_DESTINATION:
424 dprintf(("MIXER_GETLINEINFOF_DESTINATION %d", lpMl->dwDestination));
425 if(lpMl->dwDestination >= nrDestinations) {
426 dprintf(("ERROR: Invalid destination %d", lpMl->dwDestination));
427 return MMSYSERR_INVALPARAM;
428 }
429 memcpy(lpMl, &mixerDest[lpMl->dwDestination], sizeof(MIXERLINEA));
430 dprintf(("found line %s (%s) connections %d controls %d", lpMl->szName, lpMl->szShortName, lpMl->cConnections, lpMl->cControls));
431 break;
432
433 case MIXER_GETLINEINFOF_LINEID:
434 dprintf(("MIXER_GETLINEINFOF_LINEID %d", lpMl->dwLineID));
435 if(lpMl->dwLineID >= nrLines) {
436 dprintf(("ERROR: Invalid destination %d", lpMl->dwLineID));
437 return MIXERR_INVALLINE;
438 }
439 memcpy(lpMl, pmixerLines[lpMl->dwLineID], sizeof(MIXERLINEA));
440 dprintf(("found line %s (%s) connections %d controls %d", lpMl->szName, lpMl->szShortName, lpMl->cConnections, lpMl->cControls));
441 break;
442
443 case MIXER_GETLINEINFOF_SOURCE:
444 dprintf(("MIXER_GETLINEINFOF_SOURCE %d %d", lpMl->dwDestination, lpMl->dwSource));
445 if(lpMl->dwDestination >= nrDestinations) {
446 dprintf(("ERROR: Invalid destination %d", lpMl->dwDestination));
447 return MIXERR_INVALLINE;
448 }
449 if(lpMl->dwSource >= MIXER_SRC_MAX) {
450 dprintf(("ERROR: Invalid destination %d", lpMl->dwDestination));
451 return MIXERR_INVALLINE;
452 }
453 if(mixerDestInputs[lpMl->dwDestination][lpMl->dwSource] == -1) {
454 dprintf(("ERROR: Invalid destination %d", lpMl->dwDestination));
455 return MIXERR_INVALLINE;
456 }
457 memcpy(lpMl, &mixerSource[mixerDestInputs[lpMl->dwDestination][lpMl->dwSource]], sizeof(MIXERLINEA));
458 dprintf(("found line %s (%s) connections %d controls %d", lpMl->szName, lpMl->szShortName, lpMl->cConnections, lpMl->cControls));
459 break;
460
461 case MIXER_GETLINEINFOF_COMPONENTTYPE:
462 dprintf(("MIXER_GETLINEINFOF_COMPONENTTYPE"));
463 switch (lpMl->dwComponentType)
464 {
465 case MIXERLINE_COMPONENTTYPE_DST_UNDEFINED:
466 dprintf(("MIXERLINE_COMPONENTTYPE_DST_UNDEFINED"));
467 break;
468 case MIXERLINE_COMPONENTTYPE_DST_DIGITAL:
469 dprintf(("MIXERLINE_COMPONENTTYPE_DST_DIGITAL"));
470 break;
471 case MIXERLINE_COMPONENTTYPE_DST_LINE:
472 dprintf(("MIXERLINE_COMPONENTTYPE_DST_LINE"));
473 break;
474 case MIXERLINE_COMPONENTTYPE_DST_MONITOR:
475 dprintf(("MIXERLINE_COMPONENTTYPE_DST_MONITOR"));
476 break;
477 case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS:
478 dprintf(("MIXERLINE_COMPONENTTYPE_DST_SPEAKERS"));
479 break;
480 case MIXERLINE_COMPONENTTYPE_DST_HEADPHONES:
481 dprintf(("MIXERLINE_COMPONENTTYPE_DST_HEADPHONES"));
482 break;
483 case MIXERLINE_COMPONENTTYPE_DST_TELEPHONE:
484 dprintf(("MIXERLINE_COMPONENTTYPE_DST_TELEPHONE"));
485 break;
486 case MIXERLINE_COMPONENTTYPE_DST_WAVEIN:
487 dprintf(("MIXERLINE_COMPONENTTYPE_DST_WAVEIN"));
488 break;
489 case MIXERLINE_COMPONENTTYPE_DST_VOICEIN:
490 dprintf(("MIXERLINE_COMPONENTTYPE_DST_VOICEIN"));
491 break;
492 default:
493 dprintf(("Unhandled component type (%08lx)\n", lpMl->dwComponentType));
494 return MMSYSERR_INVALPARAM;
495 }
496 return MIXERR_INVALLINE;
497 break;
498
499 case MIXER_GETLINEINFOF_TARGETTYPE:
500 dprintf(("_TARGETTYPE not implemented yet.\n"));
501 return MIXERR_INVALLINE;
502 break;
503 default:
504 dprintf(("Unknown flag (%08lx)\n", fdwInfo & MIXER_GETLINEINFOF_QUERYMASK));
505 return MMSYSERR_INVALPARAM;
506 break;
507 }
508 return MMSYSERR_NOERROR;
509}
510/******************************************************************************/
511/******************************************************************************/
512MMRESULT WINAPI mixerGetLineInfoW(HMIXEROBJ hmxobj, LPMIXERLINEW pmxl, DWORD fdwInfo)
513{
514 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
515 MIXERLINEA line;
516 MMRESULT result;
517
518 line.cbStruct = sizeof(MIXERLINEA);
519 line.cChannels = pmxl->cChannels;
520 line.cConnections = pmxl->cConnections;
521 line.dwComponentType = pmxl->dwComponentType;
522 line.dwDestination = pmxl->dwDestination;
523 line.dwLineID = pmxl->dwLineID;
524 line.dwSource = pmxl->dwSource;
525 line.dwUser = pmxl->dwUser;
526 line.fdwLine = pmxl->fdwLine;
527 line.szName[0] = 0;
528 line.szShortName[0] = 0;
529 line.Target.dwDeviceID = pmxl->Target.dwDeviceID;
530 line.Target.dwType = pmxl->Target.dwType;
531 line.Target.vDriverVersion = pmxl->Target.vDriverVersion;
532 line.Target.wMid = pmxl->Target.wMid;
533 line.Target.wPid = pmxl->Target.wPid;
534 line.Target.szPname[0] = 0;
535
536 result = mixerGetLineInfoA(hmxobj, &line, fdwInfo);
537 if(result != MMSYSERR_NOERROR) {
538 return result;
539 }
540 pmxl->cbStruct = sizeof(MIXERLINEA);
541 pmxl->cChannels = line.cChannels;
542 pmxl->cConnections = line.cConnections;
543 pmxl->dwComponentType = line.dwComponentType;
544 pmxl->dwDestination = line.dwDestination;
545 pmxl->dwLineID = line.dwLineID;
546 pmxl->dwSource = line.dwSource;
547 pmxl->dwUser = line.dwUser;
548 pmxl->fdwLine = line.fdwLine;
549 MultiByteToWideChar(CP_ACP, 0, line.szName, -1, pmxl->szName, sizeof(line.szName));
550 MultiByteToWideChar(CP_ACP, 0, line.szShortName, -1, pmxl->szShortName, sizeof(line.szShortName));
551 pmxl->Target.dwDeviceID = line.Target.dwDeviceID;
552 pmxl->Target.dwType = line.Target.dwType;
553 pmxl->Target.vDriverVersion = line.Target.vDriverVersion;
554 pmxl->Target.wMid = line.Target.wMid;
555 pmxl->Target.wPid = line.Target.wPid;
556 pmxl->Target.szPname[0] = 0;
557 MultiByteToWideChar(CP_ACP, 0, line.Target.szPname, -1, pmxl->Target.szPname, sizeof(line.Target.szPname));
558 return MMSYSERR_NOERROR;
559}
560/******************************************************************************/
561/******************************************************************************/
562MMRESULT WINAPI mixerMessage(HMIXER hmx, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
563{
564 dprintf(("WINMM:mixerMessage - stub\n" ));
565 return MMSYSERR_INVALPARAM;
566}
567/******************************************************************************/
568/******************************************************************************/
569UINT WINAPI mixerGetNumDevs()
570{
571 if(fMMPMAvailable == FALSE || DartWaveOut::getNumDevices() == 0) {
572 return 0;
573 }
574 return 1;
575}
576/******************************************************************************/
577/******************************************************************************/
578MMRESULT WINAPI mixerGetDevCapsA(UINT uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps)
579{
580 if(fMMPMAvailable == FALSE || DartWaveOut::getNumDevices() == 0) {
581 return MMSYSERR_BADDEVICEID;
582 }
583
584 if(uMxId > 0) {
585 return MMSYSERR_BADDEVICEID;
586 }
587
588 //According to MSDN, nothing is copied when cbmxcaps is zero
589 if(cbmxcaps >= sizeof(MIXERCAPSA)) {
590 // we have to fill in this thing
591 pmxcaps->wMid = 0; /* manufacturer ID */
592 pmxcaps->wPid = 0; /* product ID */
593 pmxcaps->vDriverVersion = 0x0001; /* version of the driver */
594 strcpy( pmxcaps->szPname, WINMM_MIXERSTRING_A); /* product name */
595
596 pmxcaps->fdwSupport = 0; //no mixer flags exist
597 pmxcaps->cDestinations = nrDestinations;
598 }
599
600 return MMSYSERR_NOERROR;
601}
602/******************************************************************************/
603/******************************************************************************/
604MMRESULT WINAPI mixerGetDevCapsW(UINT uMxId, LPMIXERCAPSW pmxcaps, UINT cbmxcaps)
605{
606 if(fMMPMAvailable == FALSE || DartWaveOut::getNumDevices() == 0) {
607 return MMSYSERR_BADDEVICEID;
608 }
609
610 if(uMxId > 0) {
611 return MMSYSERR_BADDEVICEID;
612 }
613
614 //According to MSDN, nothing is copied when cbmxcaps is zero
615 if(cbmxcaps >= sizeof(MIXERCAPSW)) {
616 // we have to fill in this thing
617 pmxcaps->wMid = 0; /* manufacturer ID */
618 pmxcaps->wPid = 0; /* product ID */
619 pmxcaps->vDriverVersion = 0x0001; /* version of the driver */
620 lstrcpyW( pmxcaps->szPname, WINMM_MIXERSTRING_W ); /* product name */
621
622 pmxcaps->fdwSupport = 0; //no mixer flags exist
623 pmxcaps->cDestinations = nrDestinations;
624 }
625
626 return MMSYSERR_NOERROR;
627}
628/******************************************************************************/
629/******************************************************************************/
630MMRESULT WINAPI mixerGetID(HMIXEROBJ hmxobj, UINT * puMxId, DWORD fdwId)
631{
632 switch(fdwId) {
633 case MIXER_OBJECTF_MIXER:
634 {
635 DEVICE_STRUCT *pMixInfo = (DEVICE_STRUCT *)hmxobj;
636 if(!pMixInfo) {
637 if(puMxId) {
638 *puMxId = -1;
639 }
640 return MMSYSERR_INVALHANDLE;
641 }
642 if(puMxId) {
643 *puMxId = pMixInfo->uDeviceID;
644 }
645 break;
646 }
647
648 case MIXER_OBJECTF_HMIXER:
649 case MIXER_OBJECTF_WAVEOUT:
650 case MIXER_OBJECTF_HWAVEOUT:
651 case MIXER_OBJECTF_WAVEIN:
652 case MIXER_OBJECTF_HWAVEIN:
653 case MIXER_OBJECTF_MIDIOUT:
654 case MIXER_OBJECTF_HMIDIOUT:
655 case MIXER_OBJECTF_MIDIIN:
656 case MIXER_OBJECTF_HMIDIIN:
657 case MIXER_OBJECTF_AUX:
658 //TODO: assume default mixer
659 if(puMxId) {
660 *puMxId = 0;
661 }
662 break;
663 default:
664 if(puMxId) {
665 *puMxId = -1;
666 }
667 return MMSYSERR_INVALPARAM;
668 }
669 return MMSYSERR_NOERROR;
670}
671/******************************************************************************/
672/******************************************************************************/
673MMRESULT WINAPI mixerOpen(LPHMIXER phmx, UINT uMxId, DWORD dwCallback, DWORD dwInstance,
674 DWORD fdwOpen)
675{
676 DEVICE_STRUCT *pMixInfo;
677
678 if(DartWaveOut::getNumDevices() == 0) {
679 if(phmx) *phmx = 0;
680 return MMSYSERR_NODRIVER;
681 }
682 pMixInfo = (DEVICE_STRUCT *)malloc(sizeof(DEVICE_STRUCT));
683 if(pMixInfo == NULL) {
684 return MMSYSERR_NODRIVER;
685 }
686 pMixInfo->dwCallback = dwCallback;
687 pMixInfo->dwDriverInstance = dwInstance;
688 pMixInfo->dwFlags = fdwOpen;
689 pMixInfo->uDeviceID = uMxId;
690 pMixInfo->type = WINMM_MIXER;
691 if(phmx)
692 *phmx = (HMIXER)pMixInfo;
693
694 return MMSYSERR_NOERROR;
695}
696/******************************************************************************/
697/******************************************************************************/
698MMRESULT WINAPI mixerClose(HMIXER hmx)
699{
700 if(hmx) {
701 free((void *)hmx);
702 }
703 return MMSYSERR_NOERROR;
704}
705/******************************************************************************/
706/******************************************************************************/
707BOOL mixerInit()
708{
709 MIXERLINEA *pDestLine;
710
711 if(!fMMPMAvailable) return TRUE;
712
713 memset(mixerSourceLineId, -1, sizeof(mixerSourceLineId));
714 memset(mixerLineControls, -1, sizeof(mixerLineControls));
715 memset(mixerDestInputs, -1, sizeof(mixerDestInputs));
716
717 if(OSLibMixerOpen() == FALSE) {
718 //Line out destination
719 pDestLine = mixerAddDestination(MIXER_DEST_LINEOUT);
720
721 mixerAddControl(pDestLine, MIX_CTRL_VOL_OUT_LINE, pDestLine);
722 mixerAddControl(pDestLine, MIX_CTRL_MUTE_OUT_LINE, pDestLine);
723
724 //WaveIn destination
725 pDestLine = mixerAddDestination(MIXER_DEST_WAVEIN);
726 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MIC, pDestLine);
727 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_LINE, pDestLine);
728 //must add after all recording inputs (to count them)
729 mixerAddControl(pDestLine, MIX_CTRL_MUX_IN_W_SRC, pDestLine);
730 return TRUE;
731 }
732 //Line out destination
733 pDestLine = mixerAddDestination(MIXER_DEST_LINEOUT);
734
735 mixerAddControl(pDestLine, MIX_CTRL_VOL_OUT_LINE, pDestLine);
736 mixerAddControl(pDestLine, MIX_CTRL_MUTE_OUT_LINE, pDestLine);
737 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_3DCENTER)) {
738 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_3DCENTER, pDestLine);
739 }
740 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_3DDEPTH)) {
741 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_3DDEPTH, pDestLine);
742 }
743 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_TREBLE)) {
744 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_TREBLE, pDestLine);
745 }
746 if(OSLibMixIsControlPresent(MIX_CTRL_OUT_L_BASS)) {
747 mixerAddControl(pDestLine, MIX_CTRL_OUT_L_BASS, pDestLine);
748 }
749
750 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_SPDIF)) {
751 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_SPDIF);
752 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_SPDIF, pLine);
753 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_SPDIF, pLine);
754 }
755
756 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_MONO)) {
757 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_MONOIN);
758 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_MONO, pLine);
759 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_MONO, pLine);
760 }
761 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_PHONE)) {
762 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_PHONE);
763 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_PHONE, pLine);
764 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_PHONE, pLine);
765 }
766 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_MIC)) {
767 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_MIC);
768 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_MIC, pLine);
769 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_MIC, pLine);
770 if(OSLibMixIsControlPresent(MIX_CTRL_BOOST_IN_L_MIC)) {
771 mixerAddControl(pDestLine, MIX_CTRL_BOOST_IN_L_MIC, pLine);
772 }
773 }
774 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_LINE)) {
775 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_LINE);
776 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_LINE, pLine);
777 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_LINE, pLine);
778 }
779 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_CD)) {
780 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_CD);
781 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_CD, pLine);
782 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_CD, pLine);
783 }
784 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_VIDEO)) {
785 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_VIDEO);
786 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_VIDEO, pLine);
787 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_VIDEO, pLine);
788 }
789 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_AUX)) {
790 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_AUX);
791 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_AUX, pLine);
792 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_AUX, pLine);
793 }
794 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_PCM)) {
795 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_PCM);
796 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_PCM, pLine);
797 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_PCM, pLine);
798 }
799 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_WAVETABLE)) {
800 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_WAVETABLE);
801 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_WAVETABLE, pLine);
802 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_WAVETABLE, pLine);
803 }
804 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_IN_L_MIDI)) {
805 MIXERLINEA *pLine = mixerAddSource(pDestLine, MIXER_SRC_MIDI);
806 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_L_MIDI, pLine);
807 mixerAddControl(pDestLine, MIX_CTRL_MUTE_IN_L_MIDI, pLine);
808 }
809
810 //Wave In Destination
811 if(OSLibMixIsControlPresent(MIX_CTRL_MUX_IN_W_SRC)) {
812 pDestLine = mixerAddDestination(MIXER_DEST_WAVEIN);
813 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_MONO)) {
814 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MONO, pDestLine);
815 }
816 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_PHONE)) {
817 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_PHONE, pDestLine);
818 }
819 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_MIC)) {
820 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MIC, pDestLine);
821 }
822 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_LINE)) {
823 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_LINE, pDestLine);
824 }
825 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_CD)) {
826 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_CD, pDestLine);
827 }
828 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_SPDIF)) {
829 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_SPDIF, pDestLine);
830 }
831 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_VIDEO)) {
832 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_VIDEO, pDestLine);
833 }
834 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_AUX)) {
835 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_AUX, pDestLine);
836 }
837 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_PCM)) {
838 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_PCM, pDestLine);
839 }
840 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_WAVETABLE)) {
841 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_WAVETABLE, pDestLine);
842 }
843 if(OSLibMixIsRecSourcePresent(MIX_CTRL_VOL_IN_W_MIDI)) {
844 mixerAddControl(pDestLine, MIX_CTRL_VOL_IN_W_MIDI, pDestLine);
845 }
846 //must add after all recording inputs (to count them)
847 mixerAddControl(pDestLine, MIX_CTRL_MUX_IN_W_SRC, pDestLine);
848 }
849
850 //SPDIF destination
851 if(OSLibMixIsControlPresent(MIX_CTRL_VOL_OUT_SPDIF)) {
852 pDestLine = mixerAddDestination(MIXER_DEST_SPDIFOUT);
853 mixerAddControl(pDestLine, MIX_CTRL_VOL_OUT_SPDIF, pDestLine);
854 mixerAddControl(pDestLine, MIX_CTRL_MUTE_OUT_SPDIF, pDestLine);
855 }
856
857 return TRUE;
858}
859/******************************************************************************/
860/******************************************************************************/
861void mixerExit()
862{
863 OSLibMixerClose();
864}
865/******************************************************************************/
866/******************************************************************************/
867static MIXERLINEA *mixerAddSource(MIXERLINEA *pDestLine, DWORD dwSource)
868{
869 MIXERLINEA *pline = &mixerSource[nrSources];
870
871 if(nrSources >= MAX_MIXER_SOURCES) {
872 dprintf(("ERROR: mixerAddSource: out of room!!!"));
873 DebugInt3();
874 return NULL;
875 }
876
877 pline->cbStruct = sizeof(MIXERLINEA);
878 memset(pline, 0, sizeof(MIXERLINEA));
879
880 pline->cConnections = 0;
881 pline->cControls = 0;
882 pline->dwDestination = 0;
883 pline->fdwLine = MIXERLINE_LINEF_SOURCE;
884 pline->dwSource = nrSources;
885
886 switch(dwSource) {
887 case MIXER_SRC_MONOIN:
888 case MIXER_SRC_PHONE:
889 pline->cChannels = 1;
890 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE;
891 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
892 break;
893
894 case MIXER_SRC_MIC:
895 pline->cChannels = 1;
896 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
897 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
898 break;
899
900 case MIXER_SRC_LINE:
901 pline->cChannels = 2;
902 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE;
903 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
904 break;
905
906 case MIXER_SRC_CD:
907 pline->cChannels = 2;
908 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
909 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
910 break;
911
912 case MIXER_SRC_SPDIF:
913 pline->cChannels = 2;
914 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL;
915 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
916 break;
917
918 case MIXER_SRC_VIDEO:
919 pline->cChannels = 2;
920 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED;
921 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
922 break;
923
924 case MIXER_SRC_AUX:
925 pline->cChannels = 2;
926 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
927 pline->Target.dwType = MIXERLINE_TARGETTYPE_AUX;
928 break;
929
930 case MIXER_SRC_PCM:
931 pline->cChannels = 2;
932 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
933 pline->Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT;
934 break;
935
936 case MIXER_SRC_WAVETABLE:
937 case MIXER_SRC_MIDI:
938 pline->cChannels = 2;
939 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
940 pline->Target.dwType = MIXERLINE_TARGETTYPE_MIDIOUT;
941 break;
942
943 default:
944 DebugInt3();
945 return NULL;
946 }
947 strncpy(pline->szShortName, szSourceName[dwSource][0], sizeof(pline->szShortName));
948 strncpy(pline->szName, szSourceName[dwSource][1], sizeof(pline->szName));
949
950 dprintf(("Adding Source %s (%s)", pline->szName, pline->szShortName));
951 nrSources++;
952
953 mixerDestInputs[MIXER_DEST_LINEOUT][nrLineOutInputs] = pline->dwSource;
954 nrLineOutInputs++;
955
956 pline->dwLineID = nrLines;
957 pmixerLines[nrLines] = pline;
958 nrLines++;
959
960 //increase nr of inputs at destinateion line
961 pDestLine->cConnections++;
962
963 //store line id in source to line mapping array
964 mixerSourceLineId[dwSource] = pline->dwLineID;
965
966 return pline;
967}
968/******************************************************************************/
969/******************************************************************************/
970static MIXERLINEA *mixerAddDestination(DWORD dwDest)
971{
972 MIXERLINEA *pline = &mixerDest[nrDestinations];
973
974 if(nrDestinations >= MAX_MIXER_DESTINATIONS) {
975 dprintf(("ERROR: mixerAddDestination: out of room!!!"));
976 DebugInt3();
977 return NULL;
978 }
979 pline->cbStruct = sizeof(MIXERLINEA);
980 memset(pline, 0, sizeof(MIXERLINEA));
981
982 switch(dwDest) {
983 case MIXER_DEST_LINEOUT:
984 pline->dwDestination = nrDestinations;
985 pline->cChannels = 2;
986 pline->cConnections = 0;
987 pline->cControls = 0;
988 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
989 pline->dwSource = 0;
990 pline->fdwLine = MIXERLINE_LINEF_ACTIVE;
991 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
992 break;
993
994 case MIXER_DEST_SPDIFOUT:
995 pline->dwDestination = nrDestinations;
996 pline->cChannels = 2;
997 pline->cConnections = 0;
998 pline->cControls = 0;
999 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_DIGITAL;
1000 pline->dwSource = 0;
1001 pline->fdwLine = MIXERLINE_LINEF_ACTIVE;
1002 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1003 break;
1004
1005 case MIXER_DEST_WAVEIN:
1006 pline->dwSource = nrDestinations;
1007 pline->cChannels = 2;
1008 pline->cConnections = 0;
1009 pline->cControls = 0;
1010 pline->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
1011 pline->dwDestination = 0;
1012 pline->fdwLine = MIXERLINE_LINEF_SOURCE;
1013 pline->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1014 break;
1015
1016 default:
1017 DebugInt3();
1018 return NULL;
1019 }
1020 strncpy(pline->szShortName, szDestName[dwDest][0], sizeof(pline->szShortName));
1021 strncpy(pline->szName, szDestName[dwDest][1], sizeof(pline->szName));
1022 dprintf(("Adding destination %s (%s) connections %d controls %d", pline->szName, pline->szShortName, pline->cConnections, pline->cControls));
1023 nrDestinations++;
1024
1025 pline->dwLineID = nrLines;
1026 pmixerLines[nrLines] = pline;
1027 nrLines++;
1028 return pline;
1029}
1030/******************************************************************************/
1031/******************************************************************************/
1032static int mixerWaveInVolToSource(DWORD dwControl)
1033{
1034 switch(dwControl) {
1035 case MIX_CTRL_VOL_IN_W_MONO:
1036 return MIXER_SRC_MONOIN;
1037 case MIX_CTRL_VOL_IN_W_PHONE:
1038 return MIXER_SRC_PHONE;
1039 case MIX_CTRL_VOL_IN_W_MIC:
1040 return MIXER_SRC_MIC;
1041 case MIX_CTRL_VOL_IN_W_LINE:
1042 return MIXER_SRC_LINE;
1043 case MIX_CTRL_VOL_IN_W_CD:
1044 return MIXER_SRC_CD;
1045 case MIX_CTRL_VOL_IN_W_SPDIF:
1046 return MIXER_SRC_SPDIF;
1047 case MIX_CTRL_VOL_IN_W_VIDEO:
1048 return MIXER_SRC_VIDEO;
1049 case MIX_CTRL_VOL_IN_W_AUX:
1050 return MIXER_SRC_AUX;
1051 case MIX_CTRL_VOL_IN_W_PCM:
1052 return MIXER_SRC_PCM;
1053 case MIX_CTRL_VOL_IN_W_WAVETABLE:
1054 return MIXER_SRC_WAVETABLE;
1055 case MIX_CTRL_VOL_IN_W_MIDI:
1056 return MIXER_SRC_MIDI;
1057 default:
1058 DebugInt3();
1059 return 0;
1060 }
1061}
1062/******************************************************************************/
1063/******************************************************************************/
1064static BOOL mixerAddControl(MIXERLINEA *pDestLine, DWORD dwControl, MIXERLINEA *pSrcLine)
1065{
1066 MIXERCONTROLA *pctrl = &mixerControls[nrControls];
1067
1068 if(nrControls >= MAX_MIXER_CONTROLS) {
1069 dprintf(("ERROR: mixerAddControl: out of room!!!"));
1070 DebugInt3();
1071 return FALSE;
1072 }
1073
1074 pctrl->cbStruct = sizeof(MIXERCONTROLA);
1075 memset(pctrl, 0, sizeof(MIXERCONTROLA));
1076
1077 pctrl->cMultipleItems = 0;
1078 pctrl->dwControlID = nrControls;
1079 pctrl->fdwControl = 0;
1080 switch(dwControl) {
1081 case MIX_CTRL_VOL_OUT_LINE:
1082 case MIX_CTRL_VOL_IN_L_MONO:
1083 case MIX_CTRL_VOL_IN_L_PHONE:
1084 case MIX_CTRL_VOL_IN_L_MIC:
1085 case MIX_CTRL_VOL_IN_L_LINE:
1086 case MIX_CTRL_VOL_IN_L_CD:
1087 case MIX_CTRL_VOL_IN_L_SPDIF:
1088 case MIX_CTRL_VOL_IN_L_VIDEO:
1089 case MIX_CTRL_VOL_IN_L_AUX:
1090 case MIX_CTRL_VOL_IN_L_PCM:
1091 case MIX_CTRL_VOL_IN_L_WAVETABLE:
1092 case MIX_CTRL_VOL_IN_L_MIDI:
1093 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1094 pctrl->Bounds.s.lMinimum = 0;
1095 pctrl->Bounds.s.lMaximum = 100;
1096 pctrl->Metrics.cSteps = 1;
1097 break;
1098
1099 case MIX_CTRL_VOL_IN_W_MONO:
1100 case MIX_CTRL_VOL_IN_W_PHONE:
1101 case MIX_CTRL_VOL_IN_W_MIC:
1102 case MIX_CTRL_VOL_IN_W_LINE:
1103 case MIX_CTRL_VOL_IN_W_CD:
1104 case MIX_CTRL_VOL_IN_W_SPDIF:
1105 case MIX_CTRL_VOL_IN_W_VIDEO:
1106 case MIX_CTRL_VOL_IN_W_AUX:
1107 case MIX_CTRL_VOL_IN_W_PCM:
1108 case MIX_CTRL_VOL_IN_W_WAVETABLE:
1109 case MIX_CTRL_VOL_IN_W_MIDI:
1110 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1111 pctrl->Bounds.s.lMinimum = 0;
1112 pctrl->Bounds.s.lMaximum = 100;
1113 pctrl->Metrics.cSteps = 1;
1114 mixerDestInputs[MIXER_DEST_WAVEIN][nrWaveInInputs] = mixerSourceLineId[mixerWaveInVolToSource(dwControl)];
1115 nrWaveInInputs++;
1116 break;
1117
1118 case MIX_CTRL_MUTE_OUT_LINE:
1119 case MIX_CTRL_MUTE_IN_L_MONO:
1120 case MIX_CTRL_MUTE_IN_L_PHONE:
1121 case MIX_CTRL_MUTE_IN_L_MIC:
1122 case MIX_CTRL_MUTE_IN_L_LINE:
1123 case MIX_CTRL_MUTE_IN_L_CD:
1124 case MIX_CTRL_MUTE_IN_L_SPDIF:
1125 case MIX_CTRL_MUTE_IN_L_VIDEO:
1126 case MIX_CTRL_MUTE_IN_L_AUX:
1127 case MIX_CTRL_MUTE_IN_L_PCM:
1128 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1129 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
1130 pctrl->Bounds.s.lMinimum = 0;
1131 pctrl->Bounds.s.lMaximum = 1;
1132 pctrl->Metrics.cSteps = 0;
1133 break;
1134
1135 case MIX_CTRL_VOL_OUT_SPDIF:
1136 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1137 pctrl->Bounds.s.lMinimum = 0;
1138 pctrl->Bounds.s.lMaximum = 100;
1139 pctrl->Metrics.cSteps = 1;
1140 break;
1141
1142 case MIX_CTRL_MUTE_OUT_SPDIF:
1143 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1144 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
1145 pctrl->Bounds.s.lMinimum = 0;
1146 pctrl->Bounds.s.lMaximum = 1;
1147 pctrl->Metrics.cSteps = 0;
1148 break;
1149
1150 case MIX_CTRL_BOOST_IN_L_MIC:
1151 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1152 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_ONOFF;
1153 pctrl->Bounds.s.lMinimum = 0;
1154 pctrl->Bounds.s.lMaximum = 1;
1155 pctrl->Metrics.cSteps = 0;
1156 break;
1157
1158 case MIX_CTRL_OUT_L_3DDEPTH:
1159 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1160 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_FADER;
1161 pctrl->Bounds.s.lMinimum = 0;
1162 pctrl->Bounds.s.lMaximum = 100;
1163 pctrl->Metrics.cSteps = 1;
1164 break;
1165
1166 case MIX_CTRL_OUT_L_3DCENTER:
1167 pctrl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM;
1168 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_FADER;
1169 pctrl->Bounds.s.lMinimum = 0;
1170 pctrl->Bounds.s.lMaximum = 100;
1171 pctrl->Metrics.cSteps = 1;
1172 break;
1173
1174 case MIX_CTRL_MUX_IN_W_SRC:
1175 pctrl->fdwControl = MIXERCONTROL_CONTROLF_MULTIPLE | MIXERCONTROL_CONTROLF_UNIFORM;
1176 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;
1177 pctrl->Bounds.s.lMinimum = 0;
1178 pctrl->Bounds.s.lMaximum = 1;
1179 pctrl->Metrics.cSteps = 1;
1180 break;
1181
1182 case MIX_CTRL_OUT_L_TREBLE:
1183 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_TREBLE;
1184 pctrl->Bounds.s.lMinimum = 0;
1185 pctrl->Bounds.s.lMaximum = 100;
1186 pctrl->Metrics.cSteps = 1;
1187 break;
1188
1189 case MIX_CTRL_OUT_L_BASS:
1190 pctrl->dwControlType = MIXERCONTROL_CONTROLTYPE_BASS;
1191 pctrl->Bounds.s.lMinimum = 0;
1192 pctrl->Bounds.s.lMaximum = 100;
1193 pctrl->Metrics.cSteps = 1;
1194 break;
1195
1196 default:
1197 DebugInt3();
1198 return FALSE;
1199 }
1200 //increase nr of controls of corresponding destinateion line
1201 pDestLine->cControls++;
1202
1203 //add control to list of controls associated with source line
1204 for(int i=0;i<MAX_SOURCE_CONTROLS;i++) {
1205 if(mixerLineControls[pSrcLine->dwLineID][i] == -1) {
1206 mixerLineControls[pSrcLine->dwLineID][i] = pctrl->dwControlID;
1207 break;
1208 }
1209 }
1210 if(i == MAX_SOURCE_CONTROLS) {
1211 DebugInt3();
1212 }
1213
1214 strncpy(pctrl->szShortName, szCtrlName[dwControl][0], sizeof(pctrl->szShortName));
1215 strncpy(pctrl->szName, szCtrlName[dwControl][1], sizeof(pctrl->szName));
1216 nrControls++;
1217 dprintf(("Adding control %s (%s)", pctrl->szName, pctrl->szShortName));
1218 return TRUE;
1219}
1220/******************************************************************************/
1221/******************************************************************************/
1222
Note: See TracBrowser for help on using the repository browser.