1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
4 * Sample MIXER Wine Driver for Linux
6 * Copyright 1997 Marcus Meissner
14 #include <sys/ioctl.h>
18 #include "multimedia.h"
22 #define MIXER_DEV "/dev/mixer"
24 #define WINE_MIXER_MANUF_ID 0xAA
25 #define WINE_MIXER_PRODUCT_ID 0x55
26 #define WINE_MIXER_VERSION 0x0100
27 #define WINE_MIXER_NAME "WINE OSS Mixer"
29 /**************************************************************************
30 * MIX_GetDevCaps [internal]
32 static DWORD
MIX_GetDevCaps(WORD wDevID
, LPMIXERCAPSA lpCaps
, DWORD dwSize
)
36 TRACE(mmaux
, "(%04X, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
38 if (wDevID
!= 0) return MMSYSERR_BADDEVICEID
;
39 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
41 if ((mixer
= open(MIXER_DEV
, O_RDWR
)) < 0) {
42 WARN(mmaux
, "mixer device not available !\n");
43 return MMSYSERR_NOTENABLED
;
45 lpCaps
->wMid
= WINE_MIXER_MANUF_ID
;
46 lpCaps
->wPid
= WINE_MIXER_PRODUCT_ID
;
47 lpCaps
->vDriverVersion
= WINE_MIXER_VERSION
;
48 strcpy(lpCaps
->szPname
, WINE_MIXER_NAME
);
49 if (ioctl(mixer
, SOUND_MIXER_READ_DEVMASK
, &mask
) == -1) {
51 perror("ioctl mixer SOUND_MIXER_DEVMASK");
52 return MMSYSERR_NOTENABLED
;
55 /* FIXME: can the Linux Mixer differ between multiple mixer targets ? */
56 lpCaps
->cDestinations
= 1;
57 lpCaps
->fdwSupport
= 0; /* No bits defined yet */
60 return MMSYSERR_NOERROR
;
63 static char *sdlabels
[SOUND_MIXER_NRDEVICES
] = SOUND_DEVICE_LABELS
;
64 static char *sdnames
[SOUND_MIXER_NRDEVICES
] = SOUND_DEVICE_NAMES
;
66 static void MIX_GetLineInfoFromIndex(LPMIXERLINEA lpMl
, int devmask
, DWORD idx
)
68 strcpy(lpMl
->szShortName
, sdlabels
[idx
]);
69 strcpy(lpMl
->szName
, sdnames
[idx
]);
71 lpMl
->dwDestination
= 0; /* index for speakers */
72 lpMl
->cConnections
= 1;
75 case SOUND_MIXER_SYNTH
:
76 lpMl
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER
;
77 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
80 lpMl
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC
;
81 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
83 case SOUND_MIXER_LINE
:
84 lpMl
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_LINE
;
85 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
88 lpMl
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE
;
89 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
92 lpMl
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT
;
93 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
96 ERR(mmaux
, "Index %ld not handled.\n", idx
);
101 /**************************************************************************
102 * MIX_GetLineInfo [internal]
104 static DWORD
MIX_GetLineInfo(WORD wDevID
, LPMIXERLINEA lpMl
, DWORD fdwInfo
)
106 int mixer
, i
, j
, devmask
, recsrc
, recmask
;
108 DWORD ret
= MMSYSERR_NOERROR
;
110 TRACE(mmaux
, "(%04X, %p, %lu);\n", wDevID
, lpMl
, fdwInfo
);
111 if (lpMl
== NULL
|| lpMl
->cbStruct
!= sizeof(*lpMl
))
112 return MMSYSERR_INVALPARAM
;
113 if ((mixer
= open(MIXER_DEV
, O_RDWR
)) < 0)
114 return MMSYSERR_NOTENABLED
;
116 if (ioctl(mixer
, SOUND_MIXER_READ_DEVMASK
, &devmask
) == -1) {
118 perror("ioctl mixer SOUND_MIXER_DEVMASK");
119 return MMSYSERR_NOTENABLED
;
121 if (ioctl(mixer
, SOUND_MIXER_READ_RECSRC
, &recsrc
) == -1) {
123 perror("ioctl mixer SOUND_MIXER_RECSRC");
124 return MMSYSERR_NOTENABLED
;
126 if (ioctl(mixer
, SOUND_MIXER_READ_RECMASK
, &recmask
) == -1) {
128 perror("ioctl mixer SOUND_MIXER_RECMASK");
129 return MMSYSERR_NOTENABLED
;
132 /* FIXME: set all the variables correctly... the lines below
135 lpMl
->fdwLine
= MIXERLINE_LINEF_ACTIVE
;
140 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
141 case MIXER_GETLINEINFOF_DESTINATION
:
142 /* FIXME: Linux doesn't seem to support multiple outputs?
143 * So we have only one output type: Speaker.
145 lpMl
->dwComponentType
= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
;
146 lpMl
->dwDestination
= 0;
147 lpMl
->dwSource
= 0xFFFFFFFF;
148 lpMl
->dwLineID
= SOUND_MIXER_SPEAKER
;
149 strcpy(lpMl
->szShortName
, sdlabels
[SOUND_MIXER_SPEAKER
]);
150 strcpy(lpMl
->szName
, sdnames
[SOUND_MIXER_SPEAKER
]);
152 /* we have all connections found in the devmask */
153 lpMl
->cConnections
= 0;
154 for (j
= 0; j
< 31; j
++)
155 if (devmask
& (1 << j
))
156 lpMl
->cConnections
++;
158 case MIXER_GETLINEINFOF_SOURCE
:
159 for (i
= j
= 0; j
< 31; j
++) {
160 if (devmask
& (1 << j
)) {
161 if (lpMl
->dwSource
== i
)
166 MIX_GetLineInfoFromIndex(lpMl
, devmask
, i
);
168 case MIXER_GETLINEINFOF_LINEID
:
169 MIX_GetLineInfoFromIndex(lpMl
, devmask
, lpMl
->dwLineID
);
171 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
172 TRACE(mmaux
, "Getting component type (%08lx)\n", lpMl
->dwComponentType
);
174 switch (lpMl
->dwComponentType
) {
175 case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
:
176 i
= SOUND_MIXER_SPEAKER
;
177 lpMl
->dwDestination
= 0;
178 lpMl
->dwSource
= 0xFFFFFFFF;
181 case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER
:
182 i
= SOUND_MIXER_SYNTH
;
183 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
185 case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC
:
187 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
189 case MIXERLINE_COMPONENTTYPE_SRC_LINE
:
190 i
= SOUND_MIXER_LINE
;
191 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
193 case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE
:
195 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
197 case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT
:
199 lpMl
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
202 FIXME(mmaux
, "Unhandled component type (%08lx)\n", lpMl
->dwComponentType
);
203 return MMSYSERR_INVALPARAM
;
206 if (devmask
& (1 << i
)) {
207 strcpy(lpMl
->szShortName
, sdlabels
[i
]);
208 strcpy(lpMl
->szName
, sdnames
[i
]);
211 lpMl
->cConnections
= 0;
213 for (j
= 0; j
< 31; j
++)
214 if (devmask
& (1 << j
))
215 lpMl
->cConnections
++;
216 /* lpMl->dwLineID = 32;*/
219 case MIXER_GETLINEINFOF_TARGETTYPE
:
220 FIXME(mmaux
, "_TARGETTYPE not implemented yet.\n");
224 lpMl
->Target
.dwType
= MIXERLINE_TARGETTYPE_AUX
;
225 lpMl
->Target
.dwDeviceID
= 0xFFFFFFFF;
226 lpMl
->Target
.wMid
= WINE_MIXER_MANUF_ID
;
227 lpMl
->Target
.wPid
= WINE_MIXER_PRODUCT_ID
;
228 lpMl
->Target
.vDriverVersion
= WINE_MIXER_VERSION
;
229 strcpy(lpMl
->Target
.szPname
, WINE_MIXER_NAME
);
235 /**************************************************************************
236 * MIX_GetLineInfo [internal]
238 static DWORD
MIX_Open(WORD wDevID
, LPMIXEROPENDESC lpMod
, DWORD flags
)
240 TRACE(mmaux
, "(%04X, %p, %lu);\n", wDevID
, lpMod
, flags
);
241 if (lpMod
== NULL
) return MMSYSERR_INVALPARAM
;
242 /* hmm. We don't keep the mixer device open. So just pretend it works */
243 return MMSYSERR_NOERROR
;
246 static DWORD
MIX_GetLineControls(WORD wDevID
, LPMIXERLINECONTROLSA lpMlc
, DWORD flags
)
248 TRACE(mmaux
, "(%04X, %p, %lu);\n", wDevID
, lpMlc
, flags
);
250 if (lpMlc
== NULL
) return MMSYSERR_INVALPARAM
;
252 return MMSYSERR_NOERROR
;
256 /**************************************************************************
257 * mixMessage [sample driver]
259 DWORD WINAPI
mixMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
260 DWORD dwParam1
, DWORD dwParam2
)
262 TRACE(mmaux
, "(%04X, %04X, %08lX, %08lX, %08lX);\n",
263 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
267 case MXDM_GETDEVCAPS
:
268 return MIX_GetDevCaps(wDevID
, (LPMIXERCAPSA
)dwParam1
, dwParam2
);
269 case MXDM_GETLINEINFO
:
270 return MIX_GetLineInfo(wDevID
, (LPMIXERLINEA
)dwParam1
, dwParam2
);
271 case MXDM_GETNUMDEVS
:
272 TRACE(mmaux
, "return 1;\n");
275 return MIX_Open(wDevID
, (LPMIXEROPENDESC
)dwParam1
, dwParam2
);
277 return MMSYSERR_NOERROR
;
278 case MXDM_GETLINECONTROLS
:
279 return MIX_GetLineControls(wDevID
, (LPMIXERLINECONTROLSA
)dwParam1
, dwParam2
);
281 WARN(mmaux
, "unknown message %d!\n", wMsg
);
283 return MMSYSERR_NOTSUPPORTED
;
285 return MMSYSERR_NOTENABLED
;