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

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

more mixer changes/fixes

File size: 15.2 KB
Line 
1/* $Id: mixeros2.cpp,v 1.4 2002-05-25 17:19:41 sandervl Exp $ */
2
3/*
4 * OS/2 Mixer multimedia
5 *
6 * Copyright 2002 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13#define INCL_BASE
14#define INCL_DOSERRORS
15#define INCL_DOSDEVIOCTL
16#define INCL_DOSFILEMGR
17#define INCL_OS2MM
18#include <os2wrap.h>
19#include <os2mewrap.h>
20#include <stdlib.h>
21#include <string.h>
22#include <dbglog.h>
23#include <ioctl90.h>
24
25#include "initwinmm.h"
26#include "mixeros2.h"
27
28static BOOL GetAudioPDDName (char *pszPDDName);
29static HFILE DevOpen (char *ddName);
30static BOOL mixerapiIOCTL90 (HFILE hPdd, ULONG ulFunc, PVOID pData, ULONG cbDataSize);
31
32static HFILE hPDDMix = 0;
33static char mixerApiMap[256] = {0};
34
35/******************************************************************************/
36/******************************************************************************/
37BOOL OSLibMixerOpen()
38{
39 char szPDDName[128] = "\\DEV\\";
40
41 if(GetAudioPDDName(&szPDDName[5]) == FALSE) {
42 return FALSE;
43 }
44
45 dprintf(("OSLibMixerOpen: PDD name %s", szPDDName));
46
47 hPDDMix = DevOpen(szPDDName);
48 if(hPDDMix == 0) {
49 dprintf(("Unable to open PDD %s", szPDDName));
50 return FALSE;
51 }
52 if(mixerapiIOCTL90(hPDDMix, GETAPIMAP, mixerApiMap, sizeof(mixerApiMap)) == FALSE) {
53 dprintf(("GETAPIMAP failed!!"));
54 DosClose(hPDDMix);
55 return FALSE;
56 }
57
58 return TRUE;
59}
60/******************************************************************************/
61/******************************************************************************/
62void OSLibMixerClose()
63{
64 if(hPDDMix) {
65 DosClose(hPDDMix);
66 }
67}
68/******************************************************************************/
69/******************************************************************************/
70static DWORD OSLibMixGetIndex(DWORD dwControl)
71{
72 DWORD idx;
73
74 switch(dwControl) {
75 case MIX_CTRL_VOL_IN_L_MONO:
76 case MIX_CTRL_MUTE_IN_L_MONO:
77 idx = MONOINSET;
78 break;
79 case MIX_CTRL_VOL_IN_L_PHONE:
80 case MIX_CTRL_MUTE_IN_L_PHONE:
81 idx = PHONESET;
82 break;
83 case MIX_CTRL_VOL_IN_L_MIC:
84 case MIX_CTRL_MUTE_IN_L_MIC:
85 idx = MICSET;
86 break;
87 case MIX_CTRL_VOL_IN_L_LINE:
88 case MIX_CTRL_MUTE_IN_L_LINE:
89 idx = LINESET;
90 break;
91 case MIX_CTRL_VOL_IN_L_CD:
92 case MIX_CTRL_MUTE_IN_L_CD:
93 idx = CDSET;
94 break;
95 case MIX_CTRL_VOL_IN_L_VIDEO:
96 case MIX_CTRL_MUTE_IN_L_VIDEO:
97 idx = VIDEOSET;
98 break;
99 case MIX_CTRL_VOL_IN_L_AUX:
100 case MIX_CTRL_MUTE_IN_L_AUX:
101 idx = AUXSET;
102 break;
103 case MIX_CTRL_OUT_L_BASS:
104 case MIX_CTRL_OUT_L_TREBLE:
105 idx = BASSTREBLESET;
106 break;
107 case MIX_CTRL_OUT_L_3DCENTER:
108 case MIX_CTRL_OUT_L_3DDEPTH:
109 idx = THREEDSET;
110 break;
111 case MIX_CTRL_VOL_IN_L_PCM:
112 case MIX_CTRL_MUTE_IN_L_PCM:
113 idx = STREAMVOLSET;
114 break;
115 case MIX_CTRL_MUX_IN_W_SRC:
116 idx = RECORDSRCSET;
117 break;
118 case MIX_CTRL_VOL_IN_W_MONO:
119 case MIX_CTRL_VOL_IN_W_PHONE:
120 case MIX_CTRL_VOL_IN_W_MIC:
121 case MIX_CTRL_VOL_IN_W_LINE:
122 case MIX_CTRL_VOL_IN_W_CD:
123 case MIX_CTRL_VOL_IN_W_VIDEO:
124 case MIX_CTRL_VOL_IN_W_AUX:
125 case MIX_CTRL_VOL_IN_W_PCM:
126 idx = RECORDGAINSET;
127 break;
128
129 default:
130 return -1;
131 }
132 return idx & 0xF;
133}
134/******************************************************************************/
135/******************************************************************************/
136BOOL OSLibMixIsControlPresent(DWORD dwControl)
137{
138 DWORD idx;
139
140 idx = OSLibMixGetIndex(dwControl);
141 if(idx == -1) {
142 return FALSE;
143 }
144 idx += MONOINSET;
145 return mixerApiMap[idx] != 0;
146}
147/******************************************************************************/
148/******************************************************************************/
149BOOL OSLibMixSetVolume(DWORD dwControl, BOOL fMute, DWORD dwVolLeft, DWORD dwVolRight)
150{
151 DWORD dwFunc;
152 MIXSTRUCT mixstruct;
153
154 //TODO: implement master volume with MMPM2
155 if(dwControl == MIX_CTRL_VOL_OUT_LINE || dwControl == MIX_CTRL_MUTE_OUT_LINE) {
156 return TRUE;
157 }
158
159 dwFunc = OSLibMixGetIndex(dwControl);
160 if(dwFunc == -1) {
161 return FALSE;
162 }
163 dwFunc += MONOINSET;
164
165 if(dwVolLeft > MIXER_IOCTL90_MAX_VOLUME || dwVolRight > MIXER_IOCTL90_MAX_VOLUME) {
166 dprintf(("OSLibMixSetVolume: Volume (%d,%d) out of RANGE!!", dwVolLeft, dwVolRight));
167 return FALSE;
168 }
169 mixstruct.Mute = fMute;
170 mixstruct.VolumeL = WIN32_TO_IOCTL90_VOLUME(dwVolLeft);
171 mixstruct.VolumeR = WIN32_TO_IOCTL90_VOLUME(dwVolRight);
172
173 if(mixerapiIOCTL90(hPDDMix, dwFunc, &mixstruct, sizeof(mixstruct)) == TRUE) {
174 return TRUE;
175 }
176 dprintf(("OSLibMixSetVolume: mixerapiIOCTL90 %d failed!!", dwFunc));
177 return FALSE;
178}
179/******************************************************************************/
180/******************************************************************************/
181BOOL OSLibMixGetVolume(DWORD dwControl, BOOL *pfMute, DWORD *pdwVolLeft, DWORD *pdwVolRight)
182{
183 DWORD dwFunc;
184 MIXSTRUCT mixstruct;
185
186 //TODO: implement master volume with MMPM2
187 if(dwControl == MIX_CTRL_VOL_OUT_LINE || dwControl == MIX_CTRL_MUTE_OUT_LINE) {
188 if(pfMute) *pfMute = 0;
189 if(pdwVolLeft) *pdwVolLeft = 50000;
190 if(pdwVolRight) *pdwVolRight = 50000;
191 return TRUE;
192 }
193
194 dwFunc = OSLibMixGetIndex(dwControl);
195 if(dwFunc == -1) {
196 return FALSE;
197 }
198 dwFunc += MONOINQUERY;
199
200 if(mixerapiIOCTL90(hPDDMix, dwFunc, &mixstruct, sizeof(mixstruct)) == FALSE) {
201 return FALSE;
202 }
203 if(mixstruct.VolumeL > MIXER_IOCTL90_MAX_VOLUME || mixstruct.VolumeR > MIXER_IOCTL90_MAX_VOLUME) {
204 dprintf(("OSLibMixGetVolume: Volume (%d,%d) out of RANGE!!", mixstruct.VolumeL, mixstruct.VolumeR));
205 }
206 mixstruct.VolumeL = min(MIXER_IOCTL90_MAX_VOLUME, mixstruct.VolumeL);
207 mixstruct.VolumeR = min(MIXER_IOCTL90_MAX_VOLUME, mixstruct.VolumeR);
208
209 if(pfMute) *pfMute = mixstruct.Mute;
210 if(pdwVolLeft) *pdwVolLeft = IOCTL90_TO_WIN32_VOLUME(mixstruct.VolumeL);
211 if(pdwVolRight) *pdwVolRight = IOCTL90_TO_WIN32_VOLUME(mixstruct.VolumeR);
212
213 return TRUE;
214}
215/******************************************************************************/
216/******************************************************************************/
217BOOL OSLibMixGetCtrlCaps(DWORD dwControl, LONG *plMinimum, LONG *plMaximum, DWORD *pcSteps)
218{
219 switch(dwControl) {
220 case MIX_CTRL_VOL_OUT_LINE:
221 *plMinimum = MIXER_WIN32_MIN_VOLUME;
222 *plMaximum = MIXER_WIN32_MAX_VOLUME;
223 *pcSteps = MIXER_WIN32_CSTEP_VOLUME;
224 break;
225
226 case MIX_CTRL_VOL_IN_L_MONO:
227 case MIX_CTRL_VOL_IN_L_PHONE:
228 case MIX_CTRL_VOL_IN_L_MIC:
229 case MIX_CTRL_VOL_IN_L_LINE:
230 case MIX_CTRL_VOL_IN_L_CD:
231 case MIX_CTRL_VOL_IN_L_VIDEO:
232 case MIX_CTRL_VOL_IN_L_AUX:
233 case MIX_CTRL_VOL_IN_L_PCM:
234 *plMinimum = MIXER_WIN32_MIN_VOLUME;
235 *plMaximum = MIXER_WIN32_MAX_VOLUME;
236 *pcSteps = MIXER_WIN32_CSTEP_VOLUME;
237 break;
238
239 case MIX_CTRL_VOL_IN_W_MONO:
240 case MIX_CTRL_VOL_IN_W_PHONE:
241 case MIX_CTRL_VOL_IN_W_MIC:
242 case MIX_CTRL_VOL_IN_W_LINE:
243 case MIX_CTRL_VOL_IN_W_CD:
244 case MIX_CTRL_VOL_IN_W_VIDEO:
245 case MIX_CTRL_VOL_IN_W_AUX:
246 case MIX_CTRL_VOL_IN_W_PCM:
247 *plMinimum = MIXER_WIN32_MIN_VOLUME;
248 *plMaximum = MIXER_WIN32_MAX_VOLUME;
249 *pcSteps = MIXER_WIN32_CSTEP_VOLUME;
250 break;
251
252 case MIX_CTRL_OUT_L_BASS:
253 case MIX_CTRL_OUT_L_TREBLE:
254 *plMinimum = MIXER_WIN32_MIN_VOLUME;
255 *plMaximum = MIXER_WIN32_MAX_VOLUME;
256 *pcSteps = MIXER_WIN32_CSTEP_VOLUME;
257 break;
258
259 case MIX_CTRL_OUT_L_3DCENTER:
260 case MIX_CTRL_OUT_L_3DDEPTH:
261 *plMinimum = MIXER_WIN32_MIN_VOLUME;
262 *plMaximum = MIXER_WIN32_MAX_VOLUME;
263 *pcSteps = MIXER_WIN32_CSTEP_VOLUME;
264 break;
265 default:
266 DebugInt3();
267 return FALSE;
268 }
269 return TRUE;
270}
271/******************************************************************************/
272/******************************************************************************/
273BOOL OSLibMixIsRecSourcePresent(DWORD dwRecSrc)
274{
275 DWORD dwOldRecSrc, dwVolL, dwVolR;
276
277 if(OSLibMixGetRecSource(&dwOldRecSrc, &dwVolL, &dwVolR) == FALSE) {
278 return FALSE;
279 }
280 if(OSLibMixSetRecSource(dwRecSrc, dwVolL, dwVolR) == FALSE) {
281 return FALSE;
282 }
283 OSLibMixSetRecSource(dwOldRecSrc, dwVolL, dwVolR);
284 return TRUE;
285}
286/******************************************************************************/
287/******************************************************************************/
288BOOL OSLibMixSetRecSource(DWORD dwRecSrc, DWORD dwVolL, DWORD dwVolR)
289{
290 DWORD idx;
291 MIXSTRUCT mixstruct;
292
293 switch(dwRecSrc) {
294 case MIX_CTRL_VOL_IN_W_MIC:
295 idx = I90SRC_MIC;
296 break;
297 case MIX_CTRL_VOL_IN_W_CD:
298 idx = I90SRC_CD;
299 break;
300 case MIX_CTRL_VOL_IN_W_VIDEO:
301 idx = I90SRC_VIDEO;
302 break;
303 case MIX_CTRL_VOL_IN_W_AUX:
304 idx = I90SRC_AUX;
305 break;
306 case MIX_CTRL_VOL_IN_W_LINE:
307 idx = I90SRC_LINE;
308 break;
309 case MIX_CTRL_VOL_IN_W_PHONE:
310 idx = I90SRC_PHONE;
311 break;
312 default:
313 return FALSE;
314 }
315 mixstruct.Mute = 0;
316 mixstruct.VolumeL = idx;
317
318 if(mixerapiIOCTL90(hPDDMix, RECORDSRCSET, &mixstruct, sizeof(mixstruct)) == FALSE) {
319 dprintf(("OSLibMixSetRecSource: mixerapiIOCTL90 RECORDSRCSET failed!!"));
320 return FALSE;
321 }
322
323 mixstruct.Mute = 0;
324 mixstruct.VolumeL = WIN32_TO_IOCTL90_VOLUME(dwVolL);
325 mixstruct.VolumeR = WIN32_TO_IOCTL90_VOLUME(dwVolR);
326 if(mixerapiIOCTL90(hPDDMix, RECORDGAINSET, &mixstruct, sizeof(mixstruct)) == FALSE) {
327 dprintf(("OSLibMixSetRecSource: mixerapiIOCTL90 RECORDGAINSET failed!!"));
328 return FALSE;
329 }
330 return TRUE;
331}
332/******************************************************************************/
333/******************************************************************************/
334BOOL OSLibMixGetRecSource(DWORD *pdwRecSrc, DWORD *pdwVolL, DWORD *pdwVolR)
335{
336 DWORD idx;
337 MIXSTRUCT mixstruct;
338
339 if(mixerapiIOCTL90(hPDDMix, RECORDSRCQUERY, &mixstruct, sizeof(mixstruct)) == FALSE) {
340 dprintf(("OSLibMixSetRecSource: mixerapiIOCTL90 RECORDSRCGET failed!!"));
341 return FALSE;
342 }
343 switch(mixstruct.VolumeL) {
344 case I90SRC_MIC:
345 idx = MIX_CTRL_VOL_IN_W_MIC;
346 break;
347 case I90SRC_CD:
348 idx = MIX_CTRL_VOL_IN_W_CD;
349 break;
350 case I90SRC_VIDEO:
351 idx = MIX_CTRL_VOL_IN_W_VIDEO;
352 break;
353 case I90SRC_AUX:
354 idx = MIX_CTRL_VOL_IN_W_AUX;
355 break;
356 case I90SRC_LINE:
357 idx = MIX_CTRL_VOL_IN_W_LINE;
358 break;
359 case I90SRC_PHONE:
360 idx = MIX_CTRL_VOL_IN_W_PHONE;
361 break;
362 default:
363 DebugInt3();
364 return FALSE;
365 }
366 if(pdwRecSrc) {
367 *pdwRecSrc = idx;
368 }
369 if(mixerapiIOCTL90(hPDDMix, RECORDGAINQUERY, &mixstruct, sizeof(mixstruct)) == FALSE) {
370 dprintf(("OSLibMixSetRecSource: mixerapiIOCTL90 RECORDGAINQUERY failed!!"));
371 return FALSE;
372 }
373 if(pdwVolL) {
374 *pdwVolL = IOCTL90_TO_WIN32_VOLUME(mixstruct.VolumeL);
375 }
376 if(pdwVolR) {
377 *pdwVolR = IOCTL90_TO_WIN32_VOLUME(mixstruct.VolumeR);
378 }
379 return TRUE;
380}
381/******************************************************************************/
382// OS/2 32-bit program to query the Physical Device Driver name
383// for the default MMPM/2 WaveAudio device. Joe Nord 10-Mar-1999
384/******************************************************************************/
385static HFILE DevOpen (char *ddName)
386{
387 ULONG ulRC;
388 ULONG OpenFlags;
389 ULONG OpenMode;
390 ULONG ulFileSize = 0;
391 ULONG ulFileAttribute = 0;
392 ULONG ulActionTaken = 0;
393 HFILE hPdd = NULL;
394
395 OpenFlags = OPEN_ACTION_OPEN_IF_EXISTS; // Do not create file
396
397 OpenMode = OPEN_ACCESS_READWRITE + // Read/Write file
398 OPEN_SHARE_DENYNONE + // Non-exclusive access
399 OPEN_FLAGS_FAIL_ON_ERROR; // No system popups on errors
400
401 ulRC = DosOpen (ddName, // in
402 &hPdd, // out (handle)
403 &ulActionTaken, // out
404 ulFileSize, // in
405 ulFileAttribute, // in
406 OpenFlags, // in
407 OpenMode, // in
408 NULL); // in
409
410 if (ulRC != 0)
411 hPdd = NULL;
412
413 return (hPdd);
414}
415/******************************************************************************/
416/******************************************************************************/
417static BOOL mixerapiIOCTL90 (HFILE hPdd, ULONG ulFunc, PVOID pData, ULONG cbDataSize)
418{
419 ULONG ulRC;
420
421 ulRC = DosDevIOCtl
422 (hPdd, // Device Handle
423 0x90, // Category (user defined >= 0x80)
424 ulFunc, // Function Use defines in .H file
425 NULL, // in Address of parm data (not used)
426 0, // in Max size of parm data structure
427 NULL, // in out Actual size of parm data structure
428 pData, // in Address of command data
429 cbDataSize, // in Maximum size of command data
430 &cbDataSize); // in out Size of command data
431
432 return ulRC == NO_ERROR;
433}
434/******************************************************************************/
435// OS/2 32-bit program to query the Physical Device Driver name
436// for the default MMPM/2 WaveAudio device. Joe Nord 10-Mar-1999
437/******************************************************************************/
438static BOOL GetAudioPDDName (char *pszPDDName)
439{
440 ULONG ulRC;
441 char szAmpMix[9] = "AMPMIX01";
442
443 MCI_SYSINFO_PARMS SysInfo;
444 MCI_SYSINFO_LOGDEVICE SysInfoParm;
445 MCI_SYSINFO_QUERY_NAME QueryNameParm;
446
447 memset (&SysInfo, '\0', sizeof(SysInfo));
448 memset (&SysInfoParm, '\0', sizeof(SysInfoParm));
449 memset (&QueryNameParm, '\0', sizeof(QueryNameParm));
450
451 SysInfo.ulItem = MCI_SYSINFO_QUERY_NAMES;
452 SysInfo.usDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
453 SysInfo.pSysInfoParm = &QueryNameParm;
454
455 strcpy (QueryNameParm.szLogicalName, szAmpMix);
456
457 ulRC = mymciSendCommand (0,
458 MCI_SYSINFO,
459 MCI_SYSINFO_ITEM | MCI_WAIT,
460 (PVOID) &SysInfo,
461 0);
462 if (ulRC != 0) return FALSE;
463
464 // Get PDD associated with our AmpMixer
465 // Device name is in pSysInfoParm->szPDDName
466
467 SysInfo.ulItem = MCI_SYSINFO_QUERY_DRIVER;
468 SysInfo.usDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
469 SysInfo.pSysInfoParm = &SysInfoParm;
470
471 strcpy (SysInfoParm.szInstallName, QueryNameParm.szInstallName);
472
473 ulRC = mymciSendCommand (0,
474 MCI_SYSINFO,
475 MCI_SYSINFO_ITEM | MCI_WAIT,
476 (PVOID) &SysInfo,
477 0);
478 if (ulRC != 0) return FALSE;
479
480 strcpy (pszPDDName, SysInfoParm.szPDDName);
481
482 return TRUE;
483}
484/******************************************************************************/
485/******************************************************************************/
486
Note: See TracBrowser for help on using the repository browser.