- clean-up of texture 'loading'
[wine.git] / multimedia / mixer.c
blobdc95558b88e3a136209379cd7adf87b5b4005983
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * Sample MIXER Wine Driver for Linux
6 * Copyright 1997 Marcus Meissner
7 * 1999 Eric Pouech
8 */
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <sys/ioctl.h>
15 #include "windef.h"
16 #include "user.h"
17 #include "driver.h"
18 #include "multimedia.h"
19 #include "debug.h"
21 #ifdef HAVE_OSS
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)
34 int mixer, mask;
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) {
50 close(mixer);
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 */
59 close(mixer);
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]);
70 lpMl->dwLineID = idx;
71 lpMl->dwDestination = 0; /* index for speakers */
72 lpMl->cConnections = 1;
73 lpMl->cControls = 1;
74 switch (idx) {
75 case SOUND_MIXER_SYNTH:
76 lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
77 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
78 break;
79 case SOUND_MIXER_CD:
80 lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
81 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
82 break;
83 case SOUND_MIXER_LINE:
84 lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE;
85 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
86 break;
87 case SOUND_MIXER_MIC:
88 lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
89 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
90 break;
91 case SOUND_MIXER_PCM:
92 lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
93 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
94 break;
95 default:
96 ERR(mmaux, "Index %ld not handled.\n", idx);
97 break;
101 /**************************************************************************
102 * MIX_GetLineInfo [internal]
104 static DWORD MIX_GetLineInfo(WORD wDevID, LPMIXERLINEA lpMl, DWORD fdwInfo)
106 int mixer, i, j, devmask, recsrc, recmask;
107 BOOL isDst = FALSE;
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) {
117 close(mixer);
118 perror("ioctl mixer SOUND_MIXER_DEVMASK");
119 return MMSYSERR_NOTENABLED;
121 if (ioctl(mixer, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) {
122 close(mixer);
123 perror("ioctl mixer SOUND_MIXER_RECSRC");
124 return MMSYSERR_NOTENABLED;
126 if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1) {
127 close(mixer);
128 perror("ioctl mixer SOUND_MIXER_RECMASK");
129 return MMSYSERR_NOTENABLED;
132 /* FIXME: set all the variables correctly... the lines below
133 * are very wrong...
135 lpMl->fdwLine = MIXERLINE_LINEF_ACTIVE;
136 lpMl->cChannels = 2;
137 lpMl->dwUser = 0;
138 lpMl->cControls = 1;
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++;
157 break;
158 case MIXER_GETLINEINFOF_SOURCE:
159 for (i = j = 0; j < 31; j++) {
160 if (devmask & (1 << j)) {
161 if (lpMl->dwSource == i)
162 break;
163 i++;
166 MIX_GetLineInfoFromIndex(lpMl, devmask, i);
167 break;
168 case MIXER_GETLINEINFOF_LINEID:
169 MIX_GetLineInfoFromIndex(lpMl, devmask, lpMl->dwLineID);
170 break;
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;
179 isDst = TRUE;
180 break;
181 case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER:
182 i = SOUND_MIXER_SYNTH;
183 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
184 break;
185 case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC:
186 i = SOUND_MIXER_CD;
187 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
188 break;
189 case MIXERLINE_COMPONENTTYPE_SRC_LINE:
190 i = SOUND_MIXER_LINE;
191 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
192 break;
193 case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE:
194 i = SOUND_MIXER_MIC;
195 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
196 break;
197 case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT:
198 i = SOUND_MIXER_PCM;
199 lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE;
200 break;
201 default:
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]);
209 lpMl->dwLineID = i;
211 lpMl->cConnections = 0;
212 if (isDst) {
213 for (j = 0; j < 31; j++)
214 if (devmask & (1 << j))
215 lpMl->cConnections++;
216 /* lpMl->dwLineID = 32;*/
218 break;
219 case MIXER_GETLINEINFOF_TARGETTYPE:
220 FIXME(mmaux, "_TARGETTYPE not implemented yet.\n");
221 break;
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);
231 close(mixer);
232 return ret;
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;
254 #endif
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);
265 #ifdef HAVE_OSS
266 switch(wMsg) {
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");
273 return 1;
274 case MXDM_OPEN:
275 return MIX_Open(wDevID, (LPMIXEROPENDESC)dwParam1, dwParam2);
276 case MXDM_CLOSE:
277 return MMSYSERR_NOERROR;
278 case MXDM_GETLINECONTROLS:
279 return MIX_GetLineControls(wDevID, (LPMIXERLINECONTROLSA)dwParam1, dwParam2);
280 default:
281 WARN(mmaux, "unknown message %d!\n", wMsg);
283 return MMSYSERR_NOTSUPPORTED;
284 #endif
285 return MMSYSERR_NOTENABLED;