Added support for MCI AVI driver
[wine] / multimedia / mixer.c
1 /*
2  * Sample MIXER Wine Driver for Linux
3  *
4  * Copyright 1997 Marcus Meissner
5  */
6
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <sys/ioctl.h>
11 #include "windows.h"
12 #include "user.h"
13 #include "driver.h"
14 #include "multimedia.h"
15 #include "debug.h"
16
17 #define MIXER_DEV "/dev/mixer"
18
19 /**************************************************************************
20  *                              MIX_GetDevCaps                  [internal]
21  */
22 static DWORD MIX_GetDevCaps(WORD wDevID, LPMIXERCAPS16 lpCaps, DWORD dwSize)
23 {
24 #ifdef HAVE_OSS
25         int             mixer,mask;
26
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;
32         }
33         lpCaps->wMid = 0xAA;
34         lpCaps->wPid = 0x55;
35         lpCaps->vDriverVersion = 0x0100;
36         strcpy(lpCaps->szPname, "WINE Generic Mixer");
37         if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &mask) == -1) {
38                 close(mixer);
39                 perror("ioctl mixer SOUND_MIXER_DEVMASK");
40                 return MMSYSERR_NOTENABLED;
41         }
42         /* FIXME: can the Linux Mixer differ between multiple mixertargets? */
43         lpCaps->cDestinations = 1;
44         lpCaps->fdwSupport = 0; /* No bits defined yet */
45
46         close(mixer);
47         return MMSYSERR_NOERROR;
48 #else
49         return MMSYSERR_NOTENABLED;
50 #endif
51 }
52
53 #ifdef HAVE_OSS
54 static char *sdlabels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
55 static char *sdnames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
56
57 static  void    MIX_GetLineInfoFromIndex(LPMIXERLINE16 lpml, int devmask, DWORD idx)
58 {
59         strcpy(lpml->szShortName, sdlabels[idx]);
60         strcpy(lpml->szName, sdnames[idx]);
61         lpml->dwLineID = idx;
62         lpml->dwDestination = 0; /* index for speakers */
63         lpml->cConnections = 1;
64         lpml->cControls = 1;
65         switch (idx) {
66         case SOUND_MIXER_SYNTH:
67                 lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
68                 lpml->fdwLine   |= MIXERLINE_LINEF_SOURCE;
69                 break;
70         case SOUND_MIXER_CD:
71                 lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
72                 lpml->fdwLine   |= MIXERLINE_LINEF_SOURCE;
73                 break;
74         case SOUND_MIXER_LINE:
75                 lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE;
76                 lpml->fdwLine   |= MIXERLINE_LINEF_SOURCE;
77                 break;
78         case SOUND_MIXER_MIC:
79                 lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
80                 lpml->fdwLine   |= MIXERLINE_LINEF_SOURCE;
81                 break;
82         case SOUND_MIXER_PCM:
83                 lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
84                 lpml->fdwLine   |= MIXERLINE_LINEF_SOURCE;
85                 break;
86         default:
87                 ERR(mmaux, "Index %ld not handled.\n", idx);
88                 break;
89         }
90 }
91 #endif
92
93 /**************************************************************************
94  *                              MIX_GetLineInfo                 [internal]
95  */
96 static DWORD MIX_GetLineInfo(WORD wDevID, LPMIXERLINE16 lpml, DWORD fdwInfo)
97 {
98 #ifdef HAVE_OSS
99         int             mixer, i, j, devmask, recsrc, recmask;
100         DWORD           ret = MMSYSERR_NOERROR;
101
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;
107
108         if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
109                 close(mixer);
110                 perror("ioctl mixer SOUND_MIXER_DEVMASK");
111                 return MMSYSERR_NOTENABLED;
112         }
113         if (ioctl(mixer, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) {
114                 close(mixer);
115                 perror("ioctl mixer SOUND_MIXER_RECSRC");
116                 return MMSYSERR_NOTENABLED;
117         }
118         if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1) {
119                 close(mixer);
120                 perror("ioctl mixer SOUND_MIXER_RECMASK");
121                 return MMSYSERR_NOTENABLED;
122         }
123
124         /* FIXME: set all the variables correctly... the lines below
125          * are very wrong...
126          */
127         lpml->fdwLine    = MIXERLINE_LINEF_ACTIVE;
128         lpml->cChannels = 2;
129
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.
134                  */
135                 lpml->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
136                 /* we have all connections found in the devmask */
137                 lpml->cConnections = 0;
138                 for (j=0;j<31;j++)
139                         if (devmask & (1<<j))
140                                 lpml->cConnections++;
141                 break;
142         case MIXER_GETLINEINFOF_SOURCE:
143                 for (i = j = 0; j < 31; j++) {
144                         if (devmask & (1 << j)) {
145                                 if (lpml->dwSource == i)
146                                         break;
147                                 i++;
148                         }
149                 }
150                 MIX_GetLineInfoFromIndex(lpml, devmask, i);
151                 break;
152         case MIXER_GETLINEINFOF_LINEID:
153                 MIX_GetLineInfoFromIndex(lpml, devmask, lpml->dwLineID);
154                 break;
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:
159                         i = -1;
160                         break;
161                 case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER:
162                         i = SOUND_MIXER_SYNTH;
163                         break;
164                 case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC:
165                         i = SOUND_MIXER_CD;
166                         break;
167                 case MIXERLINE_COMPONENTTYPE_SRC_LINE:
168                         i = SOUND_MIXER_LINE;
169                         break;
170                 case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE:
171                         i = SOUND_MIXER_MIC;
172                         break;
173                 case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT:
174                         i = SOUND_MIXER_PCM;
175                         break;
176                 default:
177                         FIXME(mmaux, "Unhandled component type (%08lx)\n", lpml->dwComponentType);
178                         return MMSYSERR_INVALPARAM;
179                 }
180                 if (i != -1 && (devmask & (1 << i))) {
181                         strcpy(lpml->szShortName, sdlabels[i]);
182                         strcpy(lpml->szName, sdnames[i]);
183                         lpml->dwLineID = i;
184                         lpml->fdwLine = MIXERLINE_LINEF_SOURCE;
185                 } else {
186                         lpml->cConnections = 0;
187                         for (j=0;j<31;j++)
188                                 if (devmask & (1<<j))
189                                         lpml->cConnections++;
190                         lpml->dwLineID = 32;
191                 }
192                 break;
193         case MIXER_GETLINEINFOF_TARGETTYPE:
194                 FIXME(mmaux, "_TARGETTYPE not implemented yet.\n");
195                 break;
196         }
197         lpml->Target.dwType = MIXERLINE_TARGETTYPE_AUX;
198         close(mixer);
199         return ret;
200 #else
201         return MMSYSERR_NOTENABLED;
202 #endif
203 }
204
205 /**************************************************************************
206  *                              MIX_GetLineInfo                 [internal]
207  */
208 static DWORD MIX_Open(WORD wDevID, LPMIXEROPENDESC lpmod, DWORD flags)
209 {
210 #ifdef HAVE_OSS
211
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;
216 #else
217         return MMSYSERR_NOTENABLED;
218 #endif
219 }
220
221 /**************************************************************************
222  *                              mixMessage                      [sample driver]
223  */
224 DWORD WINAPI mixMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
225                                                                 DWORD dwParam1, DWORD dwParam2)
226 {
227         TRACE(mmaux, "(%04X, %04X, %08lX, %08lX, %08lX);\n", 
228                         wDevID, wMsg, dwUser, dwParam1, dwParam2);
229
230         switch(wMsg) {
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");
237                 return 1;
238         case MXDM_OPEN:
239                 return MIX_Open(wDevID, (LPMIXEROPENDESC)dwParam1, dwParam2);
240         case MXDM_CLOSE:
241                 return MMSYSERR_NOERROR;
242         default:
243                 WARN(mmaux, "unknown message %d!\n", wMsg);
244         }
245         return MMSYSERR_NOTSUPPORTED;
246 }
247