2 * Sample MIXER Wine Driver for Linux
4 * Copyright 1997 Marcus Meissner
11 #include <sys/ioctl.h>
18 #ifdef HAVE_SYS_SOUNDCARD_H
19 # include <sys/soundcard.h>
21 #ifdef HAVE_MACHINE_SOUNDCARD_H
22 # include <machine/soundcard.h>
25 #define MIXER_DEV "/dev/mixer"
28 #define IOCTL(a,b,c) ioctl(a,b,&c)
30 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
34 /**************************************************************************
35 * MIX_GetDevCaps [internal]
37 static DWORD
MIX_GetDevCaps(WORD wDevID
, LPMIXERCAPS16 lpCaps
, DWORD dwSize
)
42 TRACE(mmaux
,"(%04X, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
43 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
44 if ((mixer
= open(MIXER_DEV
, O_RDWR
)) < 0) {
45 WARN(mmaux
, "mixer device not available !\n");
46 return MMSYSERR_NOTENABLED
;
50 lpCaps
->vDriverVersion
= 0x0100;
51 strcpy(lpCaps
->szPname
,"WINE Generic Mixer");
52 if (ioctl(mixer
, SOUND_MIXER_READ_DEVMASK
, &mask
) == -1) {
54 perror("ioctl mixer SOUND_MIXER_DEVMASK");
55 return MMSYSERR_NOTENABLED
;
57 /* FIXME: can the Linux Mixer differ between multiple mixertargets? */
58 lpCaps
->cDestinations
= 1;
59 lpCaps
->fdwSupport
= 0; /* No bits defined yet */
62 return MMSYSERR_NOERROR
;
64 return MMSYSERR_NOTENABLED
;
69 static char *sdlabels
[SOUND_MIXER_NRDEVICES
] = SOUND_DEVICE_LABELS
;
70 static char *sdnames
[SOUND_MIXER_NRDEVICES
] = SOUND_DEVICE_NAMES
;
73 /**************************************************************************
74 * MIX_GetLineInfo [internal]
76 static DWORD
MIX_GetLineInfo(WORD wDevID
, LPMIXERLINE16 lpml
, DWORD fdwInfo
)
79 int mixer
,i
,j
,devmask
,recsrc
,recmask
;
81 TRACE(mmaux
,"(%04X, %p, %lu);\n", wDevID
, lpml
, fdwInfo
);
82 if (lpml
== NULL
) return MMSYSERR_NOTENABLED
;
83 if ((mixer
= open(MIXER_DEV
, O_RDWR
)) < 0)
84 return MMSYSERR_NOTENABLED
;
86 if (ioctl(mixer
, SOUND_MIXER_READ_DEVMASK
, &devmask
) == -1) {
88 perror("ioctl mixer SOUND_MIXER_DEVMASK");
89 return MMSYSERR_NOTENABLED
;
91 if (ioctl(mixer
, SOUND_MIXER_READ_RECSRC
, &recsrc
) == -1) {
93 perror("ioctl mixer SOUND_MIXER_RECSRC");
94 return MMSYSERR_NOTENABLED
;
96 if (ioctl(mixer
, SOUND_MIXER_READ_RECMASK
, &recmask
) == -1) {
98 perror("ioctl mixer SOUND_MIXER_RECMASK");
99 return MMSYSERR_NOTENABLED
;
101 lpml
->cbStruct
= sizeof(MIXERLINE16
);
102 /* FIXME: set all the variables correctly... the lines below
105 lpml
->fdwLine
= MIXERLINE_LINEF_ACTIVE
;
108 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
109 case MIXER_GETLINEINFOF_DESTINATION
:
110 /* FIXME: Linux doesn't seem to support multiple outputs?
111 * So we have only one outputtype, Speaker.
113 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
;
114 /* we have all connections found in the devmask */
115 lpml
->cConnections
= 0;
117 if (devmask
& (1<<j
))
118 lpml
->cConnections
++;
120 case MIXER_GETLINEINFOF_SOURCE
:
121 for (i
=j
=0;j
<31;j
++) {
122 if (devmask
& (1<<j
)) {
123 if (lpml
->dwSource
== i
)
128 strcpy(lpml
->szShortName
,sdlabels
[i
]);
129 strcpy(lpml
->szName
,sdnames
[i
]);
132 case SOUND_MIXER_SYNTH
:
133 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER
;
134 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
137 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC
;
138 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
140 case SOUND_MIXER_LINE
:
141 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_LINE
;
142 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
144 case SOUND_MIXER_MIC
:
145 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE
;
146 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
148 case SOUND_MIXER_PCM
:
149 lpml
->dwComponentType
= MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT
;
150 lpml
->fdwLine
|= MIXERLINE_LINEF_SOURCE
;
153 ERR(mmaux
,"Mixertype %d not handle.\n",i
);
157 case MIXER_GETLINEINFOF_LINEID
:
158 FIXME(mmaux
,"_LINEID (%ld) not implemented yet.\n",lpml
->dwLineID
);
160 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
161 FIXME(mmaux
," _COMPONENTTYPE not implemented yet.\n");
163 case MIXER_GETLINEINFOF_TARGETTYPE
:
164 FIXME(mmaux
,"_TARGETTYPE not implemented yet.\n");
167 lpml
->Target
.dwType
= MIXERLINE_TARGETTYPE_AUX
;
169 return MMSYSERR_NOERROR
;
171 return MMSYSERR_NOTENABLED
;
175 /**************************************************************************
176 * MIX_GetLineInfo [internal]
178 static DWORD
MIX_Open(WORD wDevID
, LPMIXEROPENDESC lpmod
, DWORD flags
)
182 TRACE(mmaux
,"(%04X, %p, %lu);\n",wDevID
,lpmod
,flags
);
183 if (lpmod
== NULL
) return MMSYSERR_NOTENABLED
;
184 /* hmm. We don't keep the mixer device open. So just pretend it works */
185 return MMSYSERR_NOERROR
;
187 return MMSYSERR_NOTENABLED
;
191 /**************************************************************************
192 * mixMessage [sample driver]
194 DWORD
mixMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
195 DWORD dwParam1
, DWORD dwParam2
)
197 TRACE(mmaux
,"(%04X, %04X, %08lX, %08lX, %08lX);\n",
198 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
200 case MXDM_GETDEVCAPS
:
201 return MIX_GetDevCaps(wDevID
,(LPMIXERCAPS16
)dwParam1
,dwParam2
);
202 case MXDM_GETLINEINFO
:
203 return MIX_GetLineInfo(wDevID
,(LPMIXERLINE16
)dwParam1
,dwParam2
);
204 case MXDM_GETNUMDEVS
:
205 TRACE(mmsys
,"return 1;\n");
208 return MIX_Open(wDevID
,(LPMIXEROPENDESC
)dwParam1
,dwParam2
);
210 WARN(mmaux
,"unknown message %d!\n",wMsg
);
212 return MMSYSERR_NOTSUPPORTED
;