Added Finnish resources.
[wine] / programs / winecfg / audio.c
1 /*
2  * Audio management UI code
3  *
4  * Copyright 2004 Chris Morgan
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winreg.h>
34 #include <wine/debug.h>
35 #include <shellapi.h>
36 #include <objbase.h>
37 #include <shlguid.h>
38 #include <shlwapi.h>
39 #include <shlobj.h>
40 #include <mmsystem.h>
41
42 #include "winecfg.h"
43 #include "resource.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
46
47 static const char* DSound_HW_Accels[] = {
48   "Full",
49   "Standard",
50   "Basic",
51   "Emulation",
52   NULL
53 };
54
55 /* Select the correct entry in the combobox based on drivername */
56 static void selectAudioDriver(HWND hDlg, const char *drivername)
57 {
58   int i;
59   const AUDIO_DRIVER *pAudioDrv = NULL;
60
61   if ((pAudioDrv = getAudioDrivers()))
62   {
63     for (i = 0; *pAudioDrv->szName; i++, pAudioDrv++)
64     {
65       if (!strcmp (pAudioDrv->szDriver, drivername))
66       {
67         set_reg_key(config_key, "Drivers", "Audio", (char *) pAudioDrv->szDriver);
68         SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM) hDlg, 0); /* enable apply button */
69         SendDlgItemMessage(hDlg, IDC_AUDIO_DRIVER, CB_SETCURSEL,
70                            (WPARAM) i, 0);
71       }
72     }
73   }
74 }
75
76 static void configureAudioDriver(HWND hDlg, const char *drivername)
77 {
78   int i;
79   const AUDIO_DRIVER *pAudioDrv = NULL;
80
81   if ((pAudioDrv = getAudioDrivers()))
82   {
83     for (i = 0; *pAudioDrv->szName; i++, pAudioDrv++)
84     {
85       if (!strcmp (pAudioDrv->szDriver, drivername))
86       {
87         if (strlen(pAudioDrv->szDriver) != 0)
88         {
89           HDRVR hdrvr;
90           char wine_driver[MAX_NAME_LENGTH + 8];
91           sprintf(wine_driver, "wine%s.drv", pAudioDrv->szDriver);
92           hdrvr = OpenDriverA(wine_driver, 0, 0);
93           if (hdrvr != 0)
94           {
95             if (SendDriverMessage(hdrvr, DRV_QUERYCONFIGURE, 0, 0) != 0)
96             {
97               DRVCONFIGINFO dci;
98               LONG lRes;
99               dci.dwDCISize = sizeof (dci);
100               dci.lpszDCISectionName = NULL;
101               dci.lpszDCIAliasName = NULL;
102               lRes = SendDriverMessage(hdrvr, DRV_CONFIGURE, 0, (LONG)&dci);
103             }
104             CloseDriver(hdrvr, 0, 0);
105           }
106           else
107           {
108             char str[1024];
109             sprintf(str, "Couldn't open %s!", wine_driver);
110             MessageBox(NULL, str, "Fixme", MB_OK | MB_ICONERROR);
111           }
112         }
113         break;
114       }
115     }
116   }
117 }
118
119 static void initAudioDlg (HWND hDlg)
120 {
121     char *curAudioDriver = get_reg_key(config_key, "Drivers", "Audio", "alsa");
122     const AUDIO_DRIVER *pAudioDrv = NULL;
123     int i;
124     char* buf = NULL;
125
126     WINE_TRACE("\n");
127
128     pAudioDrv = getAudioDrivers ();
129     for (i = 0; *pAudioDrv->szName; i++, pAudioDrv++) {
130         SendDlgItemMessage (hDlg, IDC_AUDIO_DRIVER, CB_ADDSTRING, 
131                 0, (LPARAM) pAudioDrv->szName);
132         if (!strcmp (pAudioDrv->szDriver, curAudioDriver)) {
133             SendDlgItemMessage(hDlg, IDC_AUDIO_DRIVER, CB_SETCURSEL, i, 0);
134         }
135     }
136
137
138     SendDlgItemMessage(hDlg, IDC_DSOUND_HW_ACCEL, CB_RESETCONTENT, 0, 0);
139     for (i = 0; NULL != DSound_HW_Accels[i]; ++i) {
140       SendDlgItemMessage(hDlg, IDC_DSOUND_HW_ACCEL, CB_ADDSTRING, 0, (LPARAM) DSound_HW_Accels[i]);
141     }    
142     buf = get_reg_key(config_key, keypath("DirectSound"), "HardwareAcceleration", "Full"); 
143     for (i = 0; NULL != DSound_HW_Accels[i]; ++i) {
144       if (strcmp(buf, DSound_HW_Accels[i]) == 0) {
145         SendDlgItemMessage(hDlg, IDC_DSOUND_HW_ACCEL, CB_SETCURSEL, i, 0);
146         break ;
147       }
148     }
149     if (NULL == DSound_HW_Accels[i]) {
150       WINE_ERR("Invalid Direct Sound HW Accel read from registry (%s)\n", buf);
151     }
152     HeapFree(GetProcessHeap(), 0, buf);
153
154     buf = get_reg_key(config_key, keypath("DirectSound"), "EmulDriver", "N");
155     if (IS_OPTION_TRUE(*buf))
156       CheckDlgButton(hDlg, IDC_DSOUND_DRV_EMUL, BST_CHECKED);
157     else
158       CheckDlgButton(hDlg, IDC_DSOUND_DRV_EMUL, BST_UNCHECKED);
159     HeapFree(GetProcessHeap(), 0, buf);
160
161 }
162
163 static const char *audioAutoDetect(void)
164 {
165   struct stat buf;
166   const char *argv_new[4];
167   int fd;
168
169   const char *driversFound[10];
170   const char *name[10];
171   int numFound = 0;
172
173   argv_new[0] = "/bin/sh";
174   argv_new[1] = "-c";
175   argv_new[3] = NULL;
176
177   /* try to detect oss */
178   fd = open("/dev/dsp", O_WRONLY | O_NONBLOCK);
179   if(fd)
180   {
181     close(fd);
182     driversFound[numFound] = "oss";
183     name[numFound] = "OSS";
184     numFound++;
185   }
186   
187     /* try to detect alsa */
188   if(!stat("/proc/asound", &buf))
189   {
190     driversFound[numFound] = "alsa";
191     name[numFound] = "ALSA";
192     numFound++;
193   }
194
195   /* try to detect arts */
196   argv_new[2] = "ps awx|grep artsd|grep -v grep|grep artsd > /dev/null";
197   if(!spawnvp(_P_WAIT, "/bin/sh", argv_new))
198   {
199     driversFound[numFound] = "arts";
200     name[numFound] = "aRts";
201     numFound++;
202   }
203
204   /* try to detect jack */
205   argv_new[2] = "ps awx|grep jackd|grep -v grep|grep jackd > /dev/null";
206   if(!spawnvp(_P_WAIT, "/bin/sh", argv_new))
207   {
208     driversFound[numFound] = "jack";
209     name[numFound] = "JACK";
210     numFound++;
211   }
212
213   /* try to detect EsounD */
214   argv_new[2] = "ps awx|grep esd|grep -v grep|grep esd > /dev/null";
215   if(!spawnvp(_P_WAIT, "/bin/sh", argv_new))
216   {
217     driversFound[numFound] = "esd";
218     name[numFound] = "EsounD";
219     numFound++;
220   }
221
222   /* try to detect nas */
223   /* TODO */
224
225   /* try to detect audioIO (solaris) */
226   /* TODO */
227
228   if(numFound == 0)
229   {
230     MessageBox(NULL, "Could not detect any audio devices/servers", "Failed", MB_OK);
231     return "";
232   }
233   else
234   {
235     /* TODO: possibly smarter handling of multiple drivers? */
236     char text[128];
237     snprintf(text, sizeof(text), "Found %s", name[0]);
238     MessageBox(NULL, (LPCTSTR)text, "Successful", MB_OK);
239     return driversFound[0];
240   }
241 }
242
243
244 INT_PTR CALLBACK
245 AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
246 {
247   switch (uMsg) {
248       case WM_COMMAND:
249         switch (LOWORD(wParam)) {
250            case IDC_AUDIO_AUTODETECT:
251               selectAudioDriver(hDlg, audioAutoDetect());
252               break;
253            case IDC_AUDIO_DRIVER:
254              if ((HIWORD(wParam) == CBN_SELCHANGE) ||
255                  (HIWORD(wParam) == CBN_SELCHANGE))
256              {
257                 const AUDIO_DRIVER *pAudioDrv = getAudioDrivers();
258                 int selected_driver = SendDlgItemMessage(hDlg, IDC_AUDIO_DRIVER, CB_GETCURSEL, 0, 0);
259                 selectAudioDriver(hDlg, (char*)pAudioDrv[selected_driver].szDriver);
260              }
261              break;
262           case IDC_AUDIO_CONFIGURE:
263              {
264                 const AUDIO_DRIVER *pAudioDrv = getAudioDrivers();
265                 int selected_driver = SendDlgItemMessage(hDlg, IDC_AUDIO_DRIVER, CB_GETCURSEL, 0, 0);
266                 configureAudioDriver(hDlg, (char*)pAudioDrv[selected_driver].szDriver);
267              }
268              break;
269           case IDC_AUDIO_CONTROL_PANEL:
270              MessageBox(NULL, "Launching audio control panel not implemented yet!", "Fixme", MB_OK | MB_ICONERROR);
271              break;
272           case IDC_DSOUND_HW_ACCEL:
273             if (HIWORD(wParam) == CBN_SELCHANGE) {
274               int selected_dsound_accel;
275               SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
276               selected_dsound_accel = SendDlgItemMessage(hDlg, IDC_DSOUND_HW_ACCEL, CB_GETCURSEL, 0, 0);
277               set_reg_key(config_key, keypath("DirectSound"), "HardwareAcceleration", DSound_HW_Accels[selected_dsound_accel]); 
278             }
279             break;
280           case IDC_DSOUND_DRV_EMUL:
281             if (HIWORD(wParam) == BN_CLICKED) {
282               SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0); 
283               if (IsDlgButtonChecked(hDlg, IDC_DSOUND_DRV_EMUL) == BST_CHECKED)
284                 set_reg_key(config_key, keypath("DirectSound"), "EmulDriver", "Y");
285               else
286                 set_reg_key(config_key, keypath("DirectSound"), "EmulDriver", "N");
287             }
288             break;
289         }
290         break;
291
292       case WM_SHOWWINDOW:
293         set_window_title(hDlg);
294         break;
295         
296       case WM_NOTIFY:
297         switch(((LPNMHDR)lParam)->code) {
298             case PSN_KILLACTIVE:
299               SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
300               break;
301             case PSN_APPLY:
302               apply();
303               SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
304               break;
305             case PSN_SETACTIVE:
306               break;
307         }
308         break;
309
310   case WM_INITDIALOG:
311     initAudioDlg(hDlg);
312     break;
313   }
314
315   return FALSE;
316 }