add playback.[ch]
[flac.git] / src / plugin_winamp2 / config.c
1 /* in_flac - Winamp2 FLAC input plugin\r
2  * Copyright (C) 2002,2003,2004  Josh Coalson\r
3  *\r
4  * This program is free software; you can redistribute it and/or\r
5  * modify it under the terms of the GNU General Public License\r
6  * as published by the Free Software Foundation; either version 2\r
7  * of the License, or (at your option) any later version.\r
8  *\r
9  * This program is distributed in the hope that it will be useful,\r
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
12  * GNU General Public License for more details.\r
13  *\r
14  * You should have received a copy of the GNU General Public License\r
15  * along with this program; if not, write to the Free Software\r
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
17  */\r
18 \r
19 #include <windows.h>\r
20 #include <commctrl.h>\r
21 #include <stdio.h>\r
22 #include "config.h"\r
23 #include "tagz.h"\r
24 #include "resource.h"\r
25 \r
26 \r
27 static char buffer[256];\r
28 static char ini_name[MAX_PATH];\r
29 \r
30 /*\r
31  *  Read/write config\r
32  */\r
33 \r
34 #define RI(x, def)          (x = GetPrivateProfileInt("FLAC", #x, def, ini_name))\r
35 #define WI(x)               WritePrivateProfileString("FLAC", #x, itoa(x, buffer, 10), ini_name)\r
36 #define RS(x, n, def)       GetPrivateProfileString("FLAC", #x, def, x, n, ini_name)\r
37 #define WS(x)               WritePrivateProfileString("FLAC", #x, x, ini_name)\r
38 \r
39 static const char default_format[] = "[%artist% - ]$if2(%title%,%filename%)";\r
40 static const char default_sep[] = ", ";\r
41 \r
42 void InitConfig()\r
43 {\r
44         char *p;\r
45 \r
46         GetModuleFileName(NULL, ini_name, sizeof(ini_name));\r
47         p = strrchr(ini_name, '.');\r
48         if (!p) p = ini_name + strlen(ini_name);\r
49         strcpy(p, ".ini");\r
50 \r
51         flac_cfg.title.tag_format_w = NULL;\r
52 }\r
53 \r
54 void ReadConfig()\r
55 {\r
56         RS(flac_cfg.title.tag_format, sizeof(flac_cfg.title.tag_format), default_format);\r
57         if (flac_cfg.title.tag_format_w)\r
58                 free(flac_cfg.title.tag_format_w);\r
59         flac_cfg.title.tag_format_w = FLAC_plugin__convert_ansi_to_wide(flac_cfg.title.tag_format);\r
60         /* @@@ FIXME: trailing spaces */\r
61         RS(flac_cfg.title.sep, sizeof(flac_cfg.title.sep), default_sep);\r
62         RI(flac_cfg.tag.reserve_space, 1);\r
63 \r
64         RI(flac_cfg.display.show_bps, 1);\r
65         RI(flac_cfg.output.misc.stop_err, 0);\r
66         RI(flac_cfg.output.replaygain.enable, 1);\r
67         RI(flac_cfg.output.replaygain.album_mode, 0);\r
68         RI(flac_cfg.output.replaygain.hard_limit, 0);\r
69         RI(flac_cfg.output.replaygain.preamp, 0);\r
70         RI(flac_cfg.output.resolution.normal.dither_24_to_16, 0);\r
71         RI(flac_cfg.output.resolution.replaygain.dither, 0);\r
72         RI(flac_cfg.output.resolution.replaygain.noise_shaping, 1);\r
73         RI(flac_cfg.output.resolution.replaygain.bps_out, 16);\r
74 }\r
75 \r
76 void WriteConfig()\r
77 {\r
78         WS(flac_cfg.title.tag_format);\r
79         WI(flac_cfg.tag.reserve_space);\r
80         WS(flac_cfg.title.sep);\r
81 \r
82         WI(flac_cfg.display.show_bps);\r
83         WI(flac_cfg.output.misc.stop_err);\r
84         WI(flac_cfg.output.replaygain.enable);\r
85         WI(flac_cfg.output.replaygain.album_mode);\r
86         WI(flac_cfg.output.replaygain.hard_limit);\r
87         WI(flac_cfg.output.replaygain.preamp);\r
88         WI(flac_cfg.output.resolution.normal.dither_24_to_16);\r
89         WI(flac_cfg.output.resolution.replaygain.dither);\r
90         WI(flac_cfg.output.resolution.replaygain.noise_shaping);\r
91         WI(flac_cfg.output.resolution.replaygain.bps_out);\r
92 }\r
93 \r
94 /*\r
95  *  Dialog\r
96  */\r
97 \r
98 #define PREAMP_RANGE            24\r
99 \r
100 #define Check(x,y)              CheckDlgButton(hwnd, x, y ? BST_CHECKED : BST_UNCHECKED)\r
101 #define GetCheck(x)             (IsDlgButtonChecked(hwnd, x)==BST_CHECKED)\r
102 #define GetSel(x)               SendDlgItemMessage(hwnd, x, CB_GETCURSEL, 0, 0)\r
103 #define GetPos(x)               SendDlgItemMessage(hwnd, x, TBM_GETPOS, 0, 0)\r
104 #define Enable(x,y)             EnableWindow(GetDlgItem(hwnd, x), y)\r
105 \r
106 static INT_PTR CALLBACK GeneralProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
107 {\r
108         switch (msg)\r
109         {\r
110         /* init */\r
111         case WM_INITDIALOG:\r
112                 SendDlgItemMessage(hwnd, IDC_TITLE, EM_LIMITTEXT, 255, 0);\r
113                 SendDlgItemMessage(hwnd, IDC_SEP, EM_LIMITTEXT, 15, 0);\r
114 \r
115                 SetDlgItemText(hwnd, IDC_TITLE, flac_cfg.title.tag_format);\r
116                 SetDlgItemText(hwnd, IDC_SEP, flac_cfg.title.sep);\r
117                 Check(IDC_ID3V1, 0);\r
118 /*!             Check(IDC_RESERVE, flac_cfg.tag.reserve_space); */\r
119                 Check(IDC_BPS, flac_cfg.display.show_bps);\r
120                 Check(IDC_ERRORS, flac_cfg.output.misc.stop_err);\r
121                 return TRUE;\r
122         /* commands */\r
123         case WM_COMMAND:\r
124                 switch (LOWORD(wParam))\r
125                 {\r
126                 /* ok */\r
127                 case IDOK:\r
128                         GetDlgItemText(hwnd, IDC_TITLE, flac_cfg.title.tag_format, sizeof(flac_cfg.title.tag_format));\r
129                         if (flac_cfg.title.tag_format_w)\r
130                                 free(flac_cfg.title.tag_format_w);\r
131                         GetDlgItemText(hwnd, IDC_SEP, flac_cfg.title.sep, sizeof(flac_cfg.title.sep));\r
132                         flac_cfg.title.tag_format_w = FLAC_plugin__convert_ansi_to_wide(flac_cfg.title.tag_format);\r
133 \r
134 /*!                     flac_cfg.tag.reserve_space = GetCheck(IDC_RESERVE); */\r
135                         flac_cfg.display.show_bps = GetCheck(IDC_BPS);\r
136                         flac_cfg.output.misc.stop_err = GetCheck(IDC_ERRORS);\r
137                         break;\r
138                 /* reset */\r
139                 case IDC_RESET:\r
140                         Check(IDC_ID3V1, 0);\r
141                         Check(IDC_RESERVE, 1);\r
142                         Check(IDC_BPS, 1);\r
143                         Check(IDC_ERRORS, 0);\r
144                         /* fall throught */\r
145                 /* default */\r
146                 case IDC_TAGZ_DEFAULT:\r
147                         SetDlgItemText(hwnd, IDC_TITLE, default_format);\r
148                         break;\r
149                 /* help */\r
150                 case IDC_TAGZ_HELP:\r
151                         MessageBox(hwnd, tagz_manual, "Help", 0);\r
152                         break;\r
153                 }\r
154                 break;\r
155         }\r
156 \r
157         return 0;\r
158 }\r
159 \r
160 \r
161 static void UpdatePreamp(HWND hwnd, HWND hamp)\r
162 {\r
163         int pos = SendMessage(hamp, TBM_GETPOS, 0, 0) - PREAMP_RANGE;\r
164         sprintf(buffer, "%d dB", pos);\r
165         SetDlgItemText(hwnd, IDC_PA, buffer);\r
166 }\r
167 \r
168 static void UpdateRG(HWND hwnd)\r
169 {\r
170         int on = GetCheck(IDC_ENABLE);\r
171         Enable(IDC_ALBUM, on);\r
172         Enable(IDC_LIMITER, on);\r
173         Enable(IDC_PREAMP, on);\r
174         Enable(IDC_PA, on);\r
175 }\r
176 \r
177 static void UpdateDither(HWND hwnd)\r
178 {\r
179         int on = GetCheck(IDC_DITHERRG);\r
180         Enable(IDC_SHAPE, on);\r
181 }\r
182 \r
183 static INT_PTR CALLBACK OutputProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
184 {\r
185         switch (msg)\r
186         {\r
187         /* init */\r
188         case WM_INITDIALOG:\r
189                 Check(IDC_ENABLE, flac_cfg.output.replaygain.enable);\r
190                 Check(IDC_ALBUM, flac_cfg.output.replaygain.album_mode);\r
191                 Check(IDC_LIMITER, flac_cfg.output.replaygain.hard_limit);\r
192                 Check(IDC_DITHER, flac_cfg.output.resolution.normal.dither_24_to_16);\r
193                 Check(IDC_DITHERRG, flac_cfg.output.resolution.replaygain.dither);\r
194                 /* prepare preamp slider */\r
195                 {\r
196                         HWND hamp = GetDlgItem(hwnd, IDC_PREAMP);\r
197                         SendMessage(hamp, TBM_SETRANGE, 1, MAKELONG(0, PREAMP_RANGE*2));\r
198                         SendMessage(hamp, TBM_SETPOS, 1, flac_cfg.output.replaygain.preamp+PREAMP_RANGE);\r
199                         UpdatePreamp(hwnd, hamp);\r
200                 }\r
201                 /* fill comboboxes */\r
202                 {\r
203                         HWND hlist = GetDlgItem(hwnd, IDC_TO);\r
204                         SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"16 bps");\r
205                         SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"24 bps");\r
206                         SendMessage(hlist, CB_SETCURSEL, flac_cfg.output.resolution.replaygain.bps_out/8 - 2, 0);\r
207 \r
208                         hlist = GetDlgItem(hwnd, IDC_SHAPE);\r
209                         SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"None");\r
210                         SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"Low");\r
211                         SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"Medium");\r
212                         SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"High");\r
213                         SendMessage(hlist, CB_SETCURSEL, flac_cfg.output.resolution.replaygain.noise_shaping, 0);\r
214                 }\r
215                 UpdateRG(hwnd);\r
216                 UpdateDither(hwnd);\r
217                 return TRUE;\r
218         /* commands */\r
219         case WM_COMMAND:\r
220                 switch (LOWORD(wParam))\r
221                 {\r
222                 /* ok */\r
223                 case IDOK:\r
224                         flac_cfg.output.replaygain.enable = GetCheck(IDC_ENABLE);\r
225                         flac_cfg.output.replaygain.album_mode = GetCheck(IDC_ALBUM);\r
226                         flac_cfg.output.replaygain.hard_limit = GetCheck(IDC_LIMITER);\r
227                         flac_cfg.output.replaygain.preamp = GetPos(IDC_PREAMP) - PREAMP_RANGE;\r
228                         flac_cfg.output.resolution.normal.dither_24_to_16 = GetCheck(IDC_DITHER);\r
229                         flac_cfg.output.resolution.replaygain.dither = GetCheck(IDC_DITHERRG);\r
230                         flac_cfg.output.resolution.replaygain.noise_shaping = GetSel(IDC_SHAPE);\r
231                         flac_cfg.output.resolution.replaygain.bps_out = (GetSel(IDC_TO)+2)*8;\r
232                         break;\r
233                 /* reset */\r
234                 case IDC_RESET:\r
235                         Check(IDC_ENABLE, 1);\r
236                         Check(IDC_ALBUM, 0);\r
237                         Check(IDC_LIMITER, 0);\r
238                         Check(IDC_DITHER, 0);\r
239                         Check(IDC_DITHERRG, 0);\r
240 \r
241                         SendDlgItemMessage(hwnd, IDC_PREAMP, TBM_SETPOS, 1, PREAMP_RANGE);\r
242                         SendDlgItemMessage(hwnd, IDC_TO, CB_SETCURSEL, 0, 0);\r
243                         SendDlgItemMessage(hwnd, IDC_SHAPE, CB_SETCURSEL, 1, 0);\r
244 \r
245                         UpdatePreamp(hwnd, GetDlgItem(hwnd, IDC_PREAMP));\r
246                         UpdateRG(hwnd);\r
247                         UpdateDither(hwnd);\r
248                         break;\r
249                 /* active check-boxes */\r
250                 case IDC_ENABLE:\r
251                         UpdateRG(hwnd);\r
252                         break;\r
253                 case IDC_DITHERRG:\r
254                         UpdateDither(hwnd);\r
255                         break;\r
256                 }\r
257                 break;\r
258         /* scroller */\r
259         case WM_HSCROLL:\r
260                 if (GetDlgCtrlID((HWND)lParam)==IDC_PREAMP)\r
261                         UpdatePreamp(hwnd, (HWND)lParam);\r
262                 return 0;\r
263         }\r
264 \r
265         return 0;\r
266 }\r
267 \r
268 #define NUM_PAGES       2\r
269 \r
270 typedef struct\r
271 {\r
272         HWND htab;\r
273         HWND hdlg;\r
274         RECT r;\r
275         HWND all[NUM_PAGES];\r
276 } LOCALDATA;\r
277 \r
278 static void ScreenToClientRect(HWND hwnd, RECT *rect)\r
279 {\r
280         POINT pt = { rect->left, rect->top };\r
281         ScreenToClient(hwnd, &pt);\r
282         rect->left = pt.x;\r
283         rect->top  = pt.y;\r
284 \r
285         pt.x = rect->right;\r
286         pt.y = rect->bottom;\r
287         ScreenToClient(hwnd, &pt);\r
288         rect->right  = pt.x;\r
289         rect->bottom = pt.y;\r
290 }\r
291 \r
292 static void SendCommand(HWND hwnd, int command)\r
293 {\r
294         LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);\r
295         SendMessage(data->hdlg, WM_COMMAND, command, 0);\r
296 }\r
297 \r
298 static void BroadcastCommand(HWND hwnd, int command)\r
299 {\r
300         LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);\r
301         int i;\r
302 \r
303         for (i=0; i<NUM_PAGES; i++)\r
304                 SendMessage(data->all[i], WM_COMMAND, command, 0);\r
305 }\r
306 \r
307 static void OnSelChange(HWND hwnd)\r
308 {\r
309         LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);\r
310         int index = TabCtrl_GetCurSel(data->htab);\r
311         if (index < 0) return;\r
312         /* hide previous */\r
313         if (data->hdlg)\r
314                 ShowWindow(data->hdlg, SW_HIDE);\r
315         /* display */\r
316         data->hdlg = data->all[index];\r
317         SetWindowPos(data->hdlg, HWND_TOP, data->r.left, data->r.top, data->r.right-data->r.left, data->r.bottom-data->r.top, SWP_SHOWWINDOW);\r
318         SetFocus(hwnd);\r
319 }\r
320 \r
321 static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
322 {\r
323         static activePage = 0;\r
324 \r
325         switch (msg)\r
326         {\r
327         /* init */\r
328         case WM_INITDIALOG:\r
329                 {\r
330                         LOCALDATA *data = LocalAlloc(LPTR, sizeof(LOCALDATA));\r
331                         HINSTANCE inst = (HINSTANCE)lParam;\r
332                         TCITEM item;\r
333 \r
334                         /* init */\r
335                         SetWindowLong(hwnd, GWL_USERDATA, (LONG)data);\r
336                         data->htab = GetDlgItem(hwnd, IDC_TABS);\r
337                         data->hdlg = NULL;\r
338                         /* add pages */\r
339                         item.mask = TCIF_TEXT;\r
340                         data->all[0] = CreateDialog(inst, MAKEINTRESOURCE(IDD_CONFIG_GENERAL), hwnd, GeneralProc);\r
341                         item.pszText = "General";\r
342                         TabCtrl_InsertItem(data->htab, 0, &item);\r
343 \r
344                         data->all[1] = CreateDialog(inst, MAKEINTRESOURCE(IDD_CONFIG_OUTPUT), hwnd, OutputProc);\r
345                         item.pszText = "Output";\r
346                         TabCtrl_InsertItem(data->htab, 1, &item);\r
347                         /* get rect (after adding pages) */\r
348                         GetWindowRect(data->htab, &data->r);\r
349                         ScreenToClientRect(hwnd, &data->r);\r
350                         TabCtrl_AdjustRect(data->htab, 0, &data->r);\r
351                         /* simulate item change */\r
352                         TabCtrl_SetCurSel(data->htab, activePage);\r
353                         OnSelChange(hwnd);\r
354                 }\r
355                 return TRUE;\r
356         /* destory */\r
357         case WM_DESTROY:\r
358                 {\r
359                         LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);\r
360                         int i;\r
361 \r
362                         activePage = TabCtrl_GetCurSel(data->htab);\r
363 \r
364                         for (i=0; i<NUM_PAGES; i++)\r
365                                 DestroyWindow(data->all[i]);\r
366 \r
367                         LocalFree(data);\r
368                 }\r
369                 break;\r
370         /* commands */\r
371         case WM_COMMAND:\r
372                 switch (LOWORD(wParam))\r
373                 {\r
374                 /* ok/cancel */\r
375                 case IDOK:\r
376                         BroadcastCommand(hwnd, IDOK);\r
377                         /* fall through */\r
378                 case IDCANCEL:\r
379                         EndDialog(hwnd, LOWORD(wParam));\r
380                         return TRUE;\r
381                 case IDC_RESET:\r
382                         SendCommand(hwnd, IDC_RESET);\r
383                         break;\r
384                 }\r
385                 break;\r
386         /* notification */\r
387         case WM_NOTIFY:\r
388                 if (LOWORD(wParam) == IDC_TABS)\r
389                 {\r
390                         NMHDR *hdr = (NMHDR*)lParam;\r
391 \r
392                         switch (hdr->code)\r
393                         {\r
394                         case TCN_SELCHANGE:\r
395                                 OnSelChange(hwnd);\r
396                                 break;\r
397                         }\r
398                 }\r
399                 break;\r
400         }\r
401 \r
402         return 0;\r
403 }\r
404 \r
405 \r
406 int DoConfig(HINSTANCE inst, HWND parent)\r
407 {\r
408         return DialogBoxParam(inst, MAKEINTRESOURCE(IDD_CONFIG), parent, DialogProc, (LONG)inst) == IDOK;\r
409 }\r