2 * Sample MIXER Wine Driver for Linux
4 * Copyright 1997 Marcus Meissner
10 #include <sys/ioctl.h>
14 #include "multimedia.h"
17 #define MIXER_DEV "/dev/mixer"
19 /**************************************************************************
20 * MIX_GetDevCaps [internal]
22 static DWORD
MIX_GetDevCaps(WORD wDevID
, LPMIXERCAPS16 lpCaps
, DWORD dwSize
)
27 TRACE(mmaux
, "(%04X, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
28 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
29 if ((mixer
= open(MIXER_DEV
, O_RDWR
)) < 0) {
30 WARN(mmaux
, "mixer device not available !\n");
31 return MMSYSERR_NOTENABLED
;
35 lpCaps
->vDriverVersion
= 0x0100;
36 strcpy(lpCaps
->szPname
, "WINE Generic Mixer");
37 if (ioctl(mixer
, SOUND_MIXER_READ_DEVMASK
, &mask
) == -1) {
39 perror("ioctl mixer SOUND_MIXER_DEVMASK");
40 return MMSYSERR_NOTENABLED
;
42 /* FIXME: can the Linux Mixer differ between multiple mixertargets? */
43 lpCaps
->cDestinations
= 1;
44 lpCaps
->fdwSupport
= 0; /* No bits defined yet */
47 return MMSYSERR_NOERROR
;
49 return MMSYSERR_NOTENABLED
;
54 static char *sdlabels
[SOUND_MIXER_NRDEVICES
] = SOUND_DEVICE_LABELS
;
55 static char *sdnames
[SOUND_MIXER_NRDEVICES
] = SOUND_DEVICE_NAMES
;
57 static void MIX_GetLineInfoFromIndex(LPMIXERLINE16 lpml
, int devmask
, DWORD idx
)
59 strcpy(lpml
->szShortName
, sdlabels
[idx
]);
60 strcpy(lpml
->szName
, sdnames
[idx
]);
62 lpml
->dwDestination
= 0; /* index for speakers */
63 lpml
->cConnections
= 1;
66 case SOUND_MIXER_SYNTH
:
67 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER
;
68 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
71 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC
;
72 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
74 case SOUND_MIXER_LINE
:
75 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_LINE
;
76 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
79 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE
;
80 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
83 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT
;
84 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
87 ERR(mmaux
, "Index %ld not handled.\n", idx
);
93 /**************************************************************************
94 * MIX_GetLineInfo [internal]
96 static DWORD
MIX_GetLineInfo(WORD wDevID
, LPMIXERLINE16 lpml
, DWORD fdwInfo
)
99 int mixer
, i
, j
, devmask
, recsrc
, recmask
;
100 DWORD ret
= MMSYSERR_NOERROR
;
102 TRACE(mmaux
, "(%04X, %p, %lu);\n", wDevID
, lpml
, fdwInfo
);
103 if (lpml
== NULL
|| lpml
->cbStruct
!= sizeof(*lpml
))
104 return MMSYSERR_INVALPARAM
;
105 if ((mixer
= open(MIXER_DEV
, O_RDWR
)) < 0)
106 return MMSYSERR_NOTENABLED
;
108 if (ioctl(mixer
, SOUND_MIXER_READ_DEVMASK
, &devmask
) == -1) {
110 perror("ioctl mixer SOUND_MIXER_DEVMASK");
111 return MMSYSERR_NOTENABLED
;
113 if (ioctl(mixer
, SOUND_MIXER_READ_RECSRC
, &recsrc
) == -1) {
115 perror("ioctl mixer SOUND_MIXER_RECSRC");
116 return MMSYSERR_NOTENABLED
;
118 if (ioctl(mixer
, SOUND_MIXER_READ_RECMASK
, &recmask
) == -1) {
120 perror("ioctl mixer SOUND_MIXER_RECMASK");
121 return MMSYSERR_NOTENABLED
;
124 /* FIXME: set all the variables correctly... the lines below
127 lpml
->fdwLine
= MIXERLINE_LINEF_ACTIVE
;
130 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
131 case MIXER_GETLINEINFOF_DESTINATION
:
132 /* FIXME: Linux doesn't seem to support multiple outputs?
133 * So we have only one outputtype, Speaker.
135 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
;
136 /* we have all connections found in the devmask */
137 lpml
->cConnections
= 0;
139 if (devmask
& (1<<j
))
140 lpml
->cConnections
++;
142 case MIXER_GETLINEINFOF_SOURCE
:
143 for (i
= j
= 0; j
< 31; j
++) {
144 if (devmask
& (1 << j
)) {
145 if (lpml
->dwSource
== i
)
150 MIX_GetLineInfoFromIndex(lpml
, devmask
, i
);
152 case MIXER_GETLINEINFOF_LINEID
:
153 MIX_GetLineInfoFromIndex(lpml
, devmask
, lpml
->dwLineID
);
155 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
156 TRACE(mmaux
, "Getting component type (%08lx)\n", lpml
->dwComponentType
);
157 switch (lpml
->dwComponentType
) {
158 case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
:
161 case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER
:
162 i
= SOUND_MIXER_SYNTH
;
164 case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC
:
167 case MIXERLINE_COMPONENTTYPE_SRC_LINE
:
168 i
= SOUND_MIXER_LINE
;
170 case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE
:
173 case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT
:
177 FIXME(mmaux
, "Unhandled component type (%08lx)\n", lpml
->dwComponentType
);
178 return MMSYSERR_INVALPARAM
;
180 if (i
!= -1 && (devmask
& (1 << i
))) {
181 strcpy(lpml
->szShortName
, sdlabels
[i
]);
182 strcpy(lpml
->szName
, sdnames
[i
]);
184 lpml
->fdwLine
= MIXERLINE_LINEF_SOURCE
;
186 lpml
->cConnections
= 0;
188 if (devmask
& (1<<j
))
189 lpml
->cConnections
++;
193 case MIXER_GETLINEINFOF_TARGETTYPE
:
194 FIXME(mmaux
, "_TARGETTYPE not implemented yet.\n");
197 lpml
->Target
.dwType
= MIXERLINE_TARGETTYPE_AUX
;
201 return MMSYSERR_NOTENABLED
;
205 /**************************************************************************
206 * MIX_GetLineInfo [internal]
208 static DWORD
MIX_Open(WORD wDevID
, LPMIXEROPENDESC lpmod
, DWORD flags
)
212 TRACE(mmaux
, "(%04X, %p, %lu);\n", wDevID
,lpmod
,flags
);
213 if (lpmod
== NULL
) return MMSYSERR_INVALPARAM
;
214 /* hmm. We don't keep the mixer device open. So just pretend it works */
215 return MMSYSERR_NOERROR
;
217 return MMSYSERR_NOTENABLED
;
221 /**************************************************************************
222 * mixMessage [sample driver]
224 DWORD WINAPI
mixMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
225 DWORD dwParam1
, DWORD dwParam2
)
227 TRACE(mmaux
, "(%04X, %04X, %08lX, %08lX, %08lX);\n",
228 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
231 case MXDM_GETDEVCAPS
:
232 return MIX_GetDevCaps(wDevID
, (LPMIXERCAPS16
)dwParam1
, dwParam2
);
233 case MXDM_GETLINEINFO
:
234 return MIX_GetLineInfo(wDevID
, (LPMIXERLINE16
)dwParam1
, dwParam2
);
235 case MXDM_GETNUMDEVS
:
236 TRACE(mmaux
, "return 1;\n");
239 return MIX_Open(wDevID
, (LPMIXEROPENDESC
)dwParam1
, dwParam2
);
241 return MMSYSERR_NOERROR
;
243 WARN(mmaux
, "unknown message %d!\n", wMsg
);
245 return MMSYSERR_NOTSUPPORTED
;