configure: Use errno.h instead of the non-standard sys/errno.h header.
[wine] / dlls / wineoss.drv / mmaux.c
1 /*
2  * Sample AUXILIARY Wine Driver
3  *
4  * Copyright 1994 Martin Ayotte
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <fcntl.h>
31 #ifdef HAVE_SYS_IOCTL_H
32 # include <sys/ioctl.h>
33 #endif
34 #include <sys/soundcard.h>
35
36 #include "windef.h"
37 #include "winbase.h"
38 #include "mmddk.h"
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(mmaux);
43
44 #define MIXER_DEV "/dev/mixer"
45
46 static int      NumDev = 6;
47
48 /*-----------------------------------------------------------------------*/
49
50 static LRESULT OSS_AuxInit(void)
51 {
52     int mixer;
53     TRACE("()\n");
54
55     if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) {
56         WARN("mixer device not available !\n");
57         NumDev = 0;
58     } else {
59         close(mixer);
60         NumDev = 6;
61     }
62     return 0;
63 }
64
65 /*-----------------------------------------------------------------------*/
66
67 static LRESULT OSS_AuxExit(void)
68 {
69     TRACE("()\n");
70     return 0;
71 }
72
73 /**************************************************************************
74  *                              AUX_GetDevCaps                  [internal]
75  */
76 static DWORD AUX_GetDevCaps(WORD wDevID, LPAUXCAPSW lpCaps, DWORD dwSize)
77 {
78     int         mixer, volume;
79     static const WCHAR ini[] = {'O','S','S',' ','A','u','x',' ','#','0',0};
80
81     TRACE("(%04X, %p, %u);\n", wDevID, lpCaps, dwSize);
82     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
83     if (wDevID >= NumDev) return MMSYSERR_BADDEVICEID;
84     if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) {
85         WARN("mixer device not available !\n");
86         return MMSYSERR_NOTENABLED;
87     }
88     if (ioctl(mixer, SOUND_MIXER_READ_LINE, &volume) == -1) {
89         close(mixer);
90         WARN("unable to read mixer !\n");
91         return MMSYSERR_NOTENABLED;
92     }
93     close(mixer);
94     lpCaps->wMid = 0xAA;
95     lpCaps->wPid = 0x55 + wDevID;
96     lpCaps->vDriverVersion = 0x0100;
97     strcpyW(lpCaps->szPname, ini);
98     lpCaps->szPname[9] = '0' + wDevID; /* 6  at max */
99     lpCaps->wTechnology = wDevID == 2 ? AUXCAPS_CDAUDIO : AUXCAPS_AUXIN;
100     lpCaps->dwSupport = AUXCAPS_VOLUME | AUXCAPS_LRVOLUME;
101
102     return MMSYSERR_NOERROR;
103 }
104
105
106 /**************************************************************************
107  *                              AUX_GetVolume                   [internal]
108  */
109 static DWORD AUX_GetVolume(WORD wDevID, LPDWORD lpdwVol)
110 {
111     int         mixer, volume, left, right, cmd;
112
113     TRACE("(%04X, %p);\n", wDevID, lpdwVol);
114     if (lpdwVol == NULL) return MMSYSERR_NOTENABLED;
115     if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) {
116         WARN("mixer device not available !\n");
117         return MMSYSERR_NOTENABLED;
118     }
119     switch(wDevID) {
120     case 0:
121         TRACE("SOUND_MIXER_READ_PCM !\n");
122         cmd = SOUND_MIXER_READ_PCM;
123         break;
124     case 1:
125         TRACE("SOUND_MIXER_READ_SYNTH !\n");
126         cmd = SOUND_MIXER_READ_SYNTH;
127         break;
128     case 2:
129         TRACE("SOUND_MIXER_READ_CD !\n");
130         cmd = SOUND_MIXER_READ_CD;
131         break;
132     case 3:
133         TRACE("SOUND_MIXER_READ_LINE !\n");
134         cmd = SOUND_MIXER_READ_LINE;
135         break;
136     case 4:
137         TRACE("SOUND_MIXER_READ_MIC !\n");
138         cmd = SOUND_MIXER_READ_MIC;
139         break;
140     case 5:
141         TRACE("SOUND_MIXER_READ_VOLUME !\n");
142         cmd = SOUND_MIXER_READ_VOLUME;
143         break;
144     default:
145         WARN("invalid device id=%04X !\n", wDevID);
146         close(mixer);
147         return MMSYSERR_NOTENABLED;
148     }
149     if (ioctl(mixer, cmd, &volume) == -1) {
150         WARN("unable to read mixer !\n");
151         close(mixer);
152         return MMSYSERR_NOTENABLED;
153     }
154     close(mixer);
155     left  = LOBYTE(LOWORD(volume));
156     right = HIBYTE(LOWORD(volume));
157     TRACE("left=%d right=%d !\n", left, right);
158     *lpdwVol = MAKELONG((left * 0xFFFFL) / 100, (right * 0xFFFFL) / 100);
159     return MMSYSERR_NOERROR;
160 }
161
162 /**************************************************************************
163  *                              AUX_SetVolume                   [internal]
164  */
165 static DWORD AUX_SetVolume(WORD wDevID, DWORD dwParam)
166 {
167     int         mixer;
168     int         volume, left, right;
169     int         cmd;
170
171     TRACE("(%04X, %08X);\n", wDevID, dwParam);
172
173     left   = (LOWORD(dwParam) * 100) >> 16;
174     right  = (HIWORD(dwParam) * 100) >> 16;
175     volume = (right << 8) | left;
176
177     if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) {
178         WARN("mixer device not available !\n");
179         return MMSYSERR_NOTENABLED;
180     }
181
182     switch(wDevID) {
183     case 0:
184         TRACE("SOUND_MIXER_WRITE_PCM !\n");
185         cmd = SOUND_MIXER_WRITE_PCM;
186         break;
187     case 1:
188         TRACE("SOUND_MIXER_WRITE_SYNTH !\n");
189         cmd = SOUND_MIXER_WRITE_SYNTH;
190         break;
191     case 2:
192         TRACE("SOUND_MIXER_WRITE_CD !\n");
193         cmd = SOUND_MIXER_WRITE_CD;
194         break;
195     case 3:
196         TRACE("SOUND_MIXER_WRITE_LINE !\n");
197         cmd = SOUND_MIXER_WRITE_LINE;
198         break;
199     case 4:
200         TRACE("SOUND_MIXER_WRITE_MIC !\n");
201         cmd = SOUND_MIXER_WRITE_MIC;
202         break;
203     case 5:
204         TRACE("SOUND_MIXER_WRITE_VOLUME !\n");
205         cmd = SOUND_MIXER_WRITE_VOLUME;
206         break;
207     default:
208         WARN("invalid device id=%04X !\n", wDevID);
209         close(mixer);
210         return MMSYSERR_NOTENABLED;
211     }
212     if (ioctl(mixer, cmd, &volume) == -1) {
213         WARN("unable to set mixer !\n");
214         close(mixer);
215         return MMSYSERR_NOTENABLED;
216     }
217     close(mixer);
218     return MMSYSERR_NOERROR;
219 }
220
221 /**************************************************************************
222  *              auxMessage (WINEOSS.2)
223  */
224 DWORD WINAPI OSS_auxMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
225                             DWORD_PTR dwParam1, DWORD_PTR dwParam2)
226 {
227     TRACE("(%04X, %04X, %08lX, %08lX, %08lX);\n",
228           wDevID, wMsg, dwUser, dwParam1, dwParam2);
229
230     switch (wMsg) {
231     case DRVM_INIT:
232         return OSS_AuxInit();
233     case DRVM_EXIT:
234         return OSS_AuxExit();
235     case DRVM_ENABLE:
236     case DRVM_DISABLE:
237         /* FIXME: Pretend this is supported */
238         return 0;
239     case AUXDM_GETDEVCAPS:
240         return AUX_GetDevCaps(wDevID, (LPAUXCAPSW)dwParam1, dwParam2);
241     case AUXDM_GETNUMDEVS:
242         TRACE("return %d;\n", NumDev);
243         return NumDev;
244     case AUXDM_GETVOLUME:
245         return AUX_GetVolume(wDevID, (LPDWORD)dwParam1);
246     case AUXDM_SETVOLUME:
247         return AUX_SetVolume(wDevID, dwParam1);
248     default:
249         WARN("unknown message !\n");
250     }
251     return MMSYSERR_NOTSUPPORTED;
252 }