Commit | Line | Data |
---|---|---|
ef79bbde P |
1 | /* |
2 | * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, see <http://www.gnu.org/licenses>. | |
17 | */ | |
18 | ||
19 | #include "cfg.c" | |
20 | ||
21 | #include <time.h> | |
22 | #include <gdk/gdk.h> | |
23 | #include <gtk/gtk.h> | |
24 | #include <glade/glade.h> | |
25 | ||
26 | GtkWidget *MainWindow; | |
27 | ||
28 | const int DPad[DKEY_TOTAL] = { | |
29 | DKEY_UP, | |
30 | DKEY_DOWN, | |
31 | DKEY_LEFT, | |
32 | DKEY_RIGHT, | |
33 | DKEY_CROSS, | |
34 | DKEY_CIRCLE, | |
35 | DKEY_SQUARE, | |
36 | DKEY_TRIANGLE, | |
37 | DKEY_L1, | |
38 | DKEY_R1, | |
39 | DKEY_L2, | |
40 | DKEY_R2, | |
41 | DKEY_SELECT, | |
42 | DKEY_START, | |
43 | DKEY_L3, | |
44 | DKEY_R3 | |
45 | }; | |
46 | ||
47 | const char *DPadText[DKEY_TOTAL] = { | |
48 | N_("D-Pad Up"), | |
49 | N_("D-Pad Down"), | |
50 | N_("D-Pad Left"), | |
51 | N_("D-Pad Right"), | |
52 | N_("Cross"), | |
53 | N_("Circle"), | |
54 | N_("Square"), | |
55 | N_("Triangle"), | |
56 | N_("L1"), | |
57 | N_("R1"), | |
58 | N_("L2"), | |
59 | N_("R2"), | |
60 | N_("Select"), | |
61 | N_("Start"), | |
62 | N_("L3"), | |
63 | N_("R3") | |
64 | }; | |
65 | ||
66 | const char *AnalogText[] = { | |
67 | N_("L-Stick Right"), | |
68 | N_("L-Stick Left"), | |
69 | N_("L-Stick Down"), | |
70 | N_("L-Stick Up"), | |
71 | N_("R-Stick Right"), | |
72 | N_("R-Stick Left"), | |
73 | N_("R-Stick Down"), | |
74 | N_("R-Stick Up") | |
75 | }; | |
76 | ||
77 | static int GetSelectedKeyIndex(int padnum) { | |
78 | GladeXML *xml; | |
79 | GtkTreeSelection *selection; | |
80 | GtkTreeIter iter; | |
81 | GtkTreeModel *model; | |
82 | GtkTreePath *path; | |
83 | gboolean selected; | |
84 | int i; | |
85 | ||
86 | xml = glade_get_widget_tree(MainWindow); | |
87 | ||
88 | selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(glade_xml_get_widget(xml, padnum == 0 ? "treeview1" : "treeview2"))); | |
89 | selected = gtk_tree_selection_get_selected(selection, &model, &iter); | |
90 | ||
91 | if (!selected) { | |
92 | return -1; | |
93 | } | |
94 | ||
95 | path = gtk_tree_model_get_path(model, &iter); | |
96 | i = *gtk_tree_path_get_indices(path); | |
97 | gtk_tree_path_free(path); | |
98 | ||
99 | return i; | |
100 | } | |
101 | ||
102 | static void GetKeyDescription(char *buf, int joynum, int key) { | |
103 | const char *hatname[16] = {_("Centered"), _("Up"), _("Right"), _("Rightup"), | |
104 | _("Down"), "", _("Rightdown"), "", _("Left"), _("Leftup"), "", "", | |
105 | _("Leftdown"), "", "", ""}; | |
106 | ||
107 | switch (g.cfg.PadDef[joynum].KeyDef[key].JoyEvType) { | |
108 | case BUTTON: | |
109 | sprintf(buf, _("Joystick: Button %d"), g.cfg.PadDef[joynum].KeyDef[key].J.Button); | |
110 | break; | |
111 | ||
112 | case AXIS: | |
113 | sprintf(buf, _("Joystick: Axis %d%c"), abs(g.cfg.PadDef[joynum].KeyDef[key].J.Axis) - 1, | |
114 | g.cfg.PadDef[joynum].KeyDef[key].J.Axis > 0 ? '+' : '-'); | |
115 | break; | |
116 | ||
117 | case HAT: | |
118 | sprintf(buf, _("Joystick: Hat %d %s"), (g.cfg.PadDef[joynum].KeyDef[key].J.Hat >> 8), | |
119 | hatname[g.cfg.PadDef[joynum].KeyDef[key].J.Hat & 0x0F]); | |
120 | break; | |
121 | ||
122 | case NONE: | |
123 | default: | |
124 | buf[0] = '\0'; | |
125 | break; | |
126 | } | |
127 | ||
128 | if (g.cfg.PadDef[joynum].KeyDef[key].Key != 0) { | |
129 | if (buf[0] != '\0') { | |
130 | strcat(buf, " / "); | |
131 | } | |
132 | ||
133 | strcat(buf, _("Keyboard:")); | |
134 | strcat(buf, " "); | |
135 | strcat(buf, XKeysymToString(g.cfg.PadDef[joynum].KeyDef[key].Key)); | |
136 | } else if (buf[0] == '\0') { | |
137 | strcpy(buf, _("(Not Set)")); | |
138 | } | |
139 | } | |
140 | ||
141 | static void GetAnalogDescription(char *buf, int joynum, int analognum, int dir) { | |
142 | const char *hatname[16] = {_("Centered"), _("Up"), _("Right"), _("Rightup"), | |
143 | _("Down"), "", _("Rightdown"), "", _("Left"), _("Leftup"), "", "", | |
144 | _("Leftdown"), "", "", ""}; | |
145 | ||
146 | switch (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].JoyEvType) { | |
147 | case BUTTON: | |
148 | sprintf(buf, _("Joystick: Button %d"), g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Button); | |
149 | break; | |
150 | ||
151 | case AXIS: | |
152 | sprintf(buf, _("Joystick: Axis %d%c"), abs(g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Axis) - 1, | |
153 | g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Axis > 0 ? '+' : '-'); | |
154 | break; | |
155 | ||
156 | case HAT: | |
157 | sprintf(buf, _("Joystick: Hat %d %s"), (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Hat >> 8), | |
158 | hatname[g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Hat & 0x0F]); | |
159 | break; | |
160 | ||
161 | case NONE: | |
162 | default: | |
163 | buf[0] = '\0'; | |
164 | break; | |
165 | } | |
166 | ||
167 | if (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].Key != 0) { | |
168 | if (buf[0] != '\0') { | |
169 | strcat(buf, " / "); | |
170 | } | |
171 | ||
172 | strcat(buf, _("Keyboard:")); | |
173 | strcat(buf, " "); | |
174 | strcat(buf, XKeysymToString(g.cfg.PadDef[joynum].AnalogDef[analognum][dir].Key)); | |
175 | } else if (buf[0] == '\0') { | |
176 | strcpy(buf, _("(Not Set)")); | |
177 | } | |
178 | } | |
179 | ||
180 | static void UpdateKeyList() { | |
181 | const char *widgetname[2] = {"treeview1", "treeview2"}; | |
182 | ||
183 | GladeXML *xml; | |
184 | GtkWidget *widget; | |
185 | GtkListStore *store; | |
186 | GtkTreeIter iter; | |
187 | int i, j; | |
188 | char buf[256]; | |
189 | ||
190 | xml = glade_get_widget_tree(MainWindow); | |
191 | ||
192 | for (i = 0; i < 2; i++) { | |
193 | int total; | |
194 | ||
195 | if (g.cfg.PadDef[i].Type == PSE_PAD_TYPE_ANALOGPAD) { | |
196 | total = DKEY_TOTAL; | |
197 | } else { | |
198 | total = DKEY_TOTAL - 2; | |
199 | } | |
200 | ||
201 | widget = glade_xml_get_widget(xml, widgetname[i]); | |
202 | ||
203 | store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); | |
204 | ||
205 | for (j = 0; j < total; j++) { | |
206 | gtk_list_store_append(store, &iter); | |
207 | GetKeyDescription(buf, i, DPad[j]); | |
208 | gtk_list_store_set(store, &iter, 0, _(DPadText[j]), 1, buf, -1); | |
209 | } | |
210 | ||
211 | if (g.cfg.PadDef[i].Type == PSE_PAD_TYPE_ANALOGPAD) { | |
212 | for (j = 0; j < 8; j++) { | |
213 | gtk_list_store_append(store, &iter); | |
214 | GetAnalogDescription(buf, i, j / 4, j % 4); | |
215 | gtk_list_store_set(store, &iter, 0, _(AnalogText[j]), 1, buf, -1); | |
216 | } | |
217 | } | |
218 | ||
219 | gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store)); | |
220 | g_object_unref(G_OBJECT(store)); | |
221 | gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widget), TRUE); | |
222 | gtk_widget_show(widget); | |
223 | } | |
224 | } | |
225 | ||
226 | static void UpdateKey() { | |
227 | const char *widgetname[2] = {"treeview1", "treeview2"}; | |
228 | int i, index; | |
229 | GladeXML *xml; | |
230 | GtkWidget *widget; | |
231 | GtkTreeModel *model; | |
232 | GtkTreeIter iter; | |
233 | GValue value = {0, }; | |
234 | char buf[256]; | |
235 | ||
236 | xml = glade_get_widget_tree(MainWindow); | |
237 | ||
238 | for (i = 0; i < 2; i++) { | |
239 | index = GetSelectedKeyIndex(i); | |
240 | if (index == -1) continue; | |
241 | ||
242 | widget = glade_xml_get_widget(xml, widgetname[i]); | |
243 | gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)), &model, &iter); | |
244 | ||
245 | if (index < DKEY_TOTAL) { | |
246 | GetKeyDescription(buf, i, DPad[index]); | |
247 | } else { | |
248 | GetAnalogDescription(buf, i, (index - DKEY_TOTAL) / 4, (index - DKEY_TOTAL) % 4); | |
249 | } | |
250 | ||
251 | g_value_init(&value, G_TYPE_STRING); | |
252 | g_value_set_string(&value, buf); | |
253 | gtk_list_store_set_value(GTK_LIST_STORE(model), &iter, 1, &value); | |
254 | } | |
255 | } | |
256 | ||
257 | static void OnConfigExit(GtkWidget *widget, gpointer user_data) { | |
258 | SavePADConfig(); | |
259 | ||
260 | gtk_widget_destroy(widget); | |
261 | SDL_Quit(); | |
262 | ||
263 | gtk_exit(0); | |
264 | } | |
265 | ||
266 | static void TreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) { | |
267 | GladeXML *xml; | |
268 | GtkTreeIter iter; | |
269 | GtkTreeModel *model; | |
270 | GtkTreePath *path; | |
271 | ||
272 | gboolean selected; | |
273 | int i; | |
274 | ||
275 | selected = gtk_tree_selection_get_selected(selection, &model, &iter); | |
276 | ||
277 | if (selected) { | |
278 | path = gtk_tree_model_get_path(model, &iter); | |
279 | i = *gtk_tree_path_get_indices(path); | |
280 | gtk_tree_path_free(path); | |
281 | ||
282 | // If a row was selected, and the row is not blank, we can now enable | |
283 | // some of the disabled widgets | |
284 | xml = glade_get_widget_tree(MainWindow); | |
285 | ||
286 | if ((int)user_data == 0) { | |
287 | gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnchange1")), TRUE); | |
288 | gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnreset1")), TRUE); | |
289 | } else { | |
290 | gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnchange2")), TRUE); | |
291 | gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnreset2")), TRUE); | |
292 | } | |
293 | } else { | |
294 | xml = glade_get_widget_tree(MainWindow); | |
295 | ||
296 | if ((int)user_data == 0) { | |
297 | gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnchange1")), FALSE); | |
298 | gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnreset1")), FALSE); | |
299 | } else { | |
300 | gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnchange2")), FALSE); | |
301 | gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnreset2")), FALSE); | |
302 | } | |
303 | } | |
304 | } | |
305 | ||
306 | static void OnDeviceChanged(GtkWidget *widget, gpointer user_data) { | |
307 | int n = (int)user_data, current = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); | |
308 | current--; | |
309 | g.cfg.PadDef[n].DevNum = current; | |
310 | } | |
311 | ||
312 | static void OnTypeChanged(GtkWidget *widget, gpointer user_data) { | |
313 | int n = (int)user_data, current = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); | |
314 | g.cfg.PadDef[n].Type = (current == 0 ? PSE_PAD_TYPE_STANDARD : PSE_PAD_TYPE_ANALOGPAD); | |
315 | ||
316 | UpdateKeyList(); | |
317 | } | |
318 | ||
319 | static void OnThreadedToggled(GtkWidget *widget, gpointer user_data) { | |
320 | g.cfg.Threaded = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
321 | } | |
322 | ||
323 | static void ReadDKeyEvent(int padnum, int key) { | |
324 | SDL_Joystick *js; | |
325 | time_t t; | |
326 | GdkEvent *ge; | |
327 | int i; | |
328 | Sint16 axis, numAxes = 0, InitAxisPos[256], PrevAxisPos[256]; | |
329 | ||
330 | if (g.cfg.PadDef[padnum].DevNum >= 0) { | |
331 | js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum); | |
332 | SDL_JoystickEventState(SDL_IGNORE); | |
333 | ||
334 | SDL_JoystickUpdate(); | |
335 | ||
336 | numAxes = SDL_JoystickNumAxes(js); | |
337 | if (numAxes > 256) numAxes = 256; | |
338 | ||
339 | for (i = 0; i < numAxes; i++) { | |
340 | InitAxisPos[i] = PrevAxisPos[i] = SDL_JoystickGetAxis(js, i); | |
341 | } | |
342 | } else { | |
343 | js = NULL; | |
344 | } | |
345 | ||
346 | t = time(NULL); | |
347 | ||
348 | while (time(NULL) < t + 10) { | |
349 | // check joystick events | |
350 | if (js != NULL) { | |
351 | SDL_JoystickUpdate(); | |
352 | ||
353 | for (i = 0; i < SDL_JoystickNumButtons(js); i++) { | |
354 | if (SDL_JoystickGetButton(js, i)) { | |
355 | g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = BUTTON; | |
356 | g.cfg.PadDef[padnum].KeyDef[key].J.Button = i; | |
357 | goto end; | |
358 | } | |
359 | } | |
360 | ||
361 | for (i = 0; i < numAxes; i++) { | |
362 | axis = SDL_JoystickGetAxis(js, i); | |
363 | if (abs(axis) > 16383 && (abs(axis - InitAxisPos[i]) > 4096 || abs(axis - PrevAxisPos[i]) > 4096)) { | |
364 | g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = AXIS; | |
365 | g.cfg.PadDef[padnum].KeyDef[key].J.Axis = (i + 1) * (axis > 0 ? 1 : -1); | |
366 | goto end; | |
367 | } | |
368 | PrevAxisPos[i] = axis; | |
369 | } | |
370 | ||
371 | for (i = 0; i < SDL_JoystickNumHats(js); i++) { | |
372 | axis = SDL_JoystickGetHat(js, i); | |
373 | if (axis != SDL_HAT_CENTERED) { | |
374 | g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = HAT; | |
375 | ||
376 | if (axis & SDL_HAT_UP) { | |
377 | g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_UP); | |
378 | } else if (axis & SDL_HAT_DOWN) { | |
379 | g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_DOWN); | |
380 | } else if (axis & SDL_HAT_LEFT) { | |
381 | g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_LEFT); | |
382 | } else if (axis & SDL_HAT_RIGHT) { | |
383 | g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_RIGHT); | |
384 | } | |
385 | ||
386 | goto end; | |
387 | } | |
388 | } | |
389 | } | |
390 | ||
391 | // check keyboard events | |
392 | while ((ge = gdk_event_get()) != NULL) { | |
393 | if (ge->type == GDK_KEY_PRESS) { | |
394 | if (ge->key.keyval != XK_Escape) { | |
395 | g.cfg.PadDef[padnum].KeyDef[key].Key = ge->key.keyval; | |
396 | } | |
397 | gdk_event_free(ge); | |
398 | goto end; | |
399 | } | |
400 | gdk_event_free(ge); | |
401 | } | |
402 | ||
403 | usleep(5000); | |
404 | } | |
405 | ||
406 | end: | |
407 | if (js != NULL) { | |
408 | SDL_JoystickClose(js); | |
409 | } | |
410 | } | |
411 | ||
412 | static void ReadAnalogEvent(int padnum, int analognum, int analogdir) { | |
413 | SDL_Joystick *js; | |
414 | time_t t; | |
415 | GdkEvent *ge; | |
416 | int i; | |
417 | Sint16 axis, numAxes = 0, InitAxisPos[256], PrevAxisPos[256]; | |
418 | ||
419 | if (g.cfg.PadDef[padnum].DevNum >= 0) { | |
420 | js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum); | |
421 | SDL_JoystickEventState(SDL_IGNORE); | |
422 | ||
423 | SDL_JoystickUpdate(); | |
424 | ||
425 | numAxes = SDL_JoystickNumAxes(js); | |
426 | if (numAxes > 256) numAxes = 256; | |
427 | ||
428 | for (i = 0; i < SDL_JoystickNumAxes(js); i++) { | |
429 | InitAxisPos[i] = PrevAxisPos[i] = SDL_JoystickGetAxis(js, i); | |
430 | } | |
431 | } else { | |
432 | js = NULL; | |
433 | } | |
434 | ||
435 | t = time(NULL); | |
436 | ||
437 | while (time(NULL) < t + 10) { | |
438 | // check joystick events | |
439 | if (js != NULL) { | |
440 | SDL_JoystickUpdate(); | |
441 | ||
442 | for (i = 0; i < SDL_JoystickNumButtons(js); i++) { | |
443 | if (SDL_JoystickGetButton(js, i)) { | |
444 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = BUTTON; | |
445 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Button = i; | |
446 | goto end; | |
447 | } | |
448 | } | |
449 | ||
450 | for (i = 0; i < numAxes; i++) { | |
451 | axis = SDL_JoystickGetAxis(js, i); | |
452 | if (abs(axis) > 16383 && (abs(axis - InitAxisPos[i]) > 4096 || abs(axis - PrevAxisPos[i]) > 4096)) { | |
453 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = AXIS; | |
454 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Axis = (i + 1) * (axis > 0 ? 1 : -1); | |
455 | goto end; | |
456 | } | |
457 | PrevAxisPos[i] = axis; | |
458 | } | |
459 | ||
460 | for (i = 0; i < SDL_JoystickNumHats(js); i++) { | |
461 | axis = SDL_JoystickGetHat(js, i); | |
462 | if (axis != SDL_HAT_CENTERED) { | |
463 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = HAT; | |
464 | ||
465 | if (axis & SDL_HAT_UP) { | |
466 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_UP); | |
467 | } else if (axis & SDL_HAT_DOWN) { | |
468 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_DOWN); | |
469 | } else if (axis & SDL_HAT_LEFT) { | |
470 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_LEFT); | |
471 | } else if (axis & SDL_HAT_RIGHT) { | |
472 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_RIGHT); | |
473 | } | |
474 | ||
475 | goto end; | |
476 | } | |
477 | } | |
478 | } | |
479 | ||
480 | // check keyboard events | |
481 | while ((ge = gdk_event_get()) != NULL) { | |
482 | if (ge->type == GDK_KEY_PRESS) { | |
483 | if (ge->key.keyval != XK_Escape) { | |
484 | g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].Key = ge->key.keyval; | |
485 | } | |
486 | gdk_event_free(ge); | |
487 | goto end; | |
488 | } | |
489 | gdk_event_free(ge); | |
490 | } | |
491 | ||
492 | usleep(5000); | |
493 | } | |
494 | ||
495 | end: | |
496 | if (js != NULL) { | |
497 | SDL_JoystickClose(js); | |
498 | } | |
499 | } | |
500 | ||
501 | static void OnChangeClicked(GtkWidget *widget, gpointer user_data) { | |
502 | int pad = (int)user_data; | |
503 | int index = GetSelectedKeyIndex(pad); | |
504 | ||
505 | if (index == -1) return; | |
506 | ||
507 | if (index < DKEY_TOTAL) { | |
508 | ReadDKeyEvent(pad, DPad[index]); | |
509 | } else { | |
510 | index -= DKEY_TOTAL; | |
511 | ReadAnalogEvent(pad, index / 4, index % 4); | |
512 | } | |
513 | ||
514 | UpdateKey(); | |
515 | } | |
516 | ||
517 | static void OnResetClicked(GtkWidget *widget, gpointer user_data) { | |
518 | int pad = (int)user_data; | |
519 | int index = GetSelectedKeyIndex(pad); | |
520 | ||
521 | if (index == -1) return; | |
522 | ||
523 | if (index < DKEY_TOTAL) { | |
524 | g.cfg.PadDef[pad].KeyDef[DPad[index]].Key = 0; | |
525 | g.cfg.PadDef[pad].KeyDef[DPad[index]].JoyEvType = NONE; | |
526 | g.cfg.PadDef[pad].KeyDef[DPad[index]].J.Button = 0; | |
527 | } else { | |
528 | index -= DKEY_TOTAL; | |
529 | g.cfg.PadDef[pad].AnalogDef[index / 4][index % 4].Key = 0; | |
530 | g.cfg.PadDef[pad].AnalogDef[index / 4][index % 4].JoyEvType = NONE; | |
531 | g.cfg.PadDef[pad].AnalogDef[index / 4][index % 4].J.Button = 0; | |
532 | } | |
533 | ||
534 | UpdateKey(); | |
535 | } | |
536 | ||
537 | static void PopulateDevList() { | |
538 | const char *widgetname[2] = {"combodev1", "combodev2"}; | |
539 | int i, j, n; | |
540 | GtkWidget *widget; | |
541 | GladeXML *xml; | |
542 | GtkTreeIter iter; | |
543 | GtkListStore *store; | |
544 | GtkCellRenderer *renderer; | |
545 | char buf[256]; | |
546 | ||
547 | xml = glade_get_widget_tree(MainWindow); | |
548 | ||
549 | for (i = 0; i < 2; i++) { | |
550 | widget = glade_xml_get_widget(xml, widgetname[i]); | |
551 | ||
552 | renderer = gtk_cell_renderer_text_new(); | |
553 | gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, FALSE); | |
554 | gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0); | |
555 | ||
556 | store = gtk_list_store_new(1, G_TYPE_STRING); | |
557 | ||
558 | gtk_list_store_append(store, &iter); | |
559 | gtk_list_store_set(store, &iter, 0, _("None"), -1); | |
560 | ||
561 | n = SDL_NumJoysticks(); | |
562 | for (j = 0; j < n; j++) { | |
563 | sprintf(buf, "%d: %s", j + 1, SDL_JoystickName(j)); | |
564 | gtk_list_store_append(store, &iter); | |
565 | gtk_list_store_set(store, &iter, 0, buf, -1); | |
566 | } | |
567 | ||
568 | gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store)); | |
569 | ||
570 | n = g.cfg.PadDef[i].DevNum + 1; | |
571 | if (n > SDL_NumJoysticks()) { | |
572 | n = 0; | |
573 | g.cfg.PadDef[i].DevNum = -1; | |
574 | } | |
575 | ||
576 | gtk_combo_box_set_active(GTK_COMBO_BOX(widget), n); | |
577 | } | |
578 | } | |
579 | ||
580 | long PADconfigure() { | |
581 | GladeXML *xml; | |
582 | GtkWidget *widget; | |
583 | GtkTreeSelection *treesel; | |
584 | GtkTreeViewColumn *column; | |
585 | GtkCellRenderer *renderer; | |
586 | ||
587 | if (SDL_Init(SDL_INIT_JOYSTICK) == -1) { | |
588 | fprintf(stderr, "Failed to initialize SDL!\n"); | |
589 | return -1; | |
590 | } | |
591 | ||
592 | LoadPADConfig(); | |
593 | ||
594 | xml = glade_xml_new(DATADIR "dfinput.glade2", "CfgWnd", NULL); | |
595 | if (xml == NULL) { | |
596 | g_warning("We could not load the interface!"); | |
597 | return -1; | |
598 | } | |
599 | ||
600 | MainWindow = glade_xml_get_widget(xml, "CfgWnd"); | |
601 | gtk_window_set_title(GTK_WINDOW(MainWindow), _("Gamepad/Keyboard Input Configuration")); | |
602 | ||
603 | widget = glade_xml_get_widget(xml, "treeview1"); | |
604 | ||
605 | // column for key | |
606 | renderer = gtk_cell_renderer_text_new(); | |
607 | column = gtk_tree_view_column_new_with_attributes(_("Key"), | |
608 | renderer, "text", 0, NULL); | |
609 | gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); | |
610 | ||
611 | // column for button | |
612 | renderer = gtk_cell_renderer_text_new(); | |
613 | column = gtk_tree_view_column_new_with_attributes(_("Button"), | |
614 | renderer, "text", 1, NULL); | |
615 | gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); | |
616 | ||
617 | treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
618 | gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); | |
619 | ||
620 | g_signal_connect_data(G_OBJECT(treesel), "changed", | |
621 | G_CALLBACK(TreeSelectionChanged), (gpointer)0, NULL, G_CONNECT_AFTER); | |
622 | ||
623 | widget = glade_xml_get_widget(xml, "treeview2"); | |
624 | ||
625 | // column for key | |
626 | renderer = gtk_cell_renderer_text_new(); | |
627 | column = gtk_tree_view_column_new_with_attributes(_("Key"), | |
628 | renderer, "text", 0, NULL); | |
629 | gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); | |
630 | ||
631 | // column for button | |
632 | renderer = gtk_cell_renderer_text_new(); | |
633 | column = gtk_tree_view_column_new_with_attributes(_("Button"), | |
634 | renderer, "text", 1, NULL); | |
635 | gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); | |
636 | ||
637 | treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
638 | gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); | |
639 | ||
640 | g_signal_connect_data(G_OBJECT(treesel), "changed", | |
641 | G_CALLBACK(TreeSelectionChanged), (gpointer)1, NULL, G_CONNECT_AFTER); | |
642 | ||
643 | widget = glade_xml_get_widget(xml, "CfgWnd"); | |
644 | g_signal_connect_data(GTK_OBJECT(widget), "delete_event", | |
645 | GTK_SIGNAL_FUNC(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); | |
646 | ||
647 | widget = glade_xml_get_widget(xml, "btnclose"); | |
648 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
649 | GTK_SIGNAL_FUNC(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); | |
650 | ||
651 | PopulateDevList(); | |
652 | UpdateKeyList(); | |
653 | ||
654 | widget = glade_xml_get_widget(xml, "checkmt"); | |
655 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), g.cfg.Threaded); | |
656 | g_signal_connect_data(GTK_OBJECT(widget), "toggled", | |
657 | GTK_SIGNAL_FUNC(OnThreadedToggled), NULL, NULL, G_CONNECT_AFTER); | |
658 | ||
659 | widget = glade_xml_get_widget(xml, "combodev1"); | |
660 | g_signal_connect_data(GTK_OBJECT(widget), "changed", | |
661 | GTK_SIGNAL_FUNC(OnDeviceChanged), (gpointer)0, NULL, G_CONNECT_AFTER); | |
662 | ||
663 | widget = glade_xml_get_widget(xml, "combodev2"); | |
664 | g_signal_connect_data(GTK_OBJECT(widget), "changed", | |
665 | GTK_SIGNAL_FUNC(OnDeviceChanged), (gpointer)1, NULL, G_CONNECT_AFTER); | |
666 | ||
667 | widget = glade_xml_get_widget(xml, "combotype1"); | |
668 | gtk_combo_box_set_active(GTK_COMBO_BOX(widget), | |
669 | g.cfg.PadDef[0].Type == PSE_PAD_TYPE_ANALOGPAD ? 1 : 0); | |
670 | g_signal_connect_data(GTK_OBJECT(widget), "changed", | |
671 | GTK_SIGNAL_FUNC(OnTypeChanged), (gpointer)0, NULL, G_CONNECT_AFTER); | |
672 | ||
673 | widget = glade_xml_get_widget(xml, "combotype2"); | |
674 | gtk_combo_box_set_active(GTK_COMBO_BOX(widget), | |
675 | g.cfg.PadDef[1].Type == PSE_PAD_TYPE_ANALOGPAD ? 1 : 0); | |
676 | g_signal_connect_data(GTK_OBJECT(widget), "changed", | |
677 | GTK_SIGNAL_FUNC(OnTypeChanged), (gpointer)1, NULL, G_CONNECT_AFTER); | |
678 | ||
679 | widget = glade_xml_get_widget(xml, "btnchange1"); | |
680 | gtk_widget_set_sensitive(widget, FALSE); | |
681 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
682 | GTK_SIGNAL_FUNC(OnChangeClicked), (gpointer)0, NULL, G_CONNECT_AFTER); | |
683 | ||
684 | widget = glade_xml_get_widget(xml, "btnreset1"); | |
685 | gtk_widget_set_sensitive(widget, FALSE); | |
686 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
687 | GTK_SIGNAL_FUNC(OnResetClicked), (gpointer)0, NULL, G_CONNECT_AFTER); | |
688 | ||
689 | widget = glade_xml_get_widget(xml, "btnchange2"); | |
690 | gtk_widget_set_sensitive(widget, FALSE); | |
691 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
692 | GTK_SIGNAL_FUNC(OnChangeClicked), (gpointer)1, NULL, G_CONNECT_AFTER); | |
693 | ||
694 | widget = glade_xml_get_widget(xml, "btnreset2"); | |
695 | gtk_widget_set_sensitive(widget, FALSE); | |
696 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
697 | GTK_SIGNAL_FUNC(OnResetClicked), (gpointer)1, NULL, G_CONNECT_AFTER); | |
698 | ||
699 | gtk_widget_show(MainWindow); | |
700 | gtk_main(); | |
701 | ||
702 | return 0; | |
703 | } | |
704 | ||
705 | void PADabout() { | |
706 | const char *authors[]= {"Wei Mingzhi <weimingzhi@gmail.com>", NULL}; | |
707 | GtkWidget *widget; | |
708 | ||
709 | widget = gtk_about_dialog_new(); | |
710 | gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "Gamepad/Keyboard Input"); | |
711 | gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "1.1"); | |
712 | gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); | |
713 | gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://www.codeplex.com/pcsxr/"); | |
714 | ||
715 | gtk_dialog_run(GTK_DIALOG(widget)); | |
716 | gtk_widget_destroy(widget); | |
717 | } | |
718 | ||
719 | int main(int argc, char *argv[]) { | |
720 | #ifdef ENABLE_NLS | |
721 | setlocale(LC_ALL, ""); | |
722 | bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); | |
723 | bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); | |
724 | textdomain(GETTEXT_PACKAGE); | |
725 | #endif | |
726 | ||
727 | gtk_set_locale(); | |
728 | gtk_init(&argc, &argv); | |
729 | ||
730 | if (argc > 1 && !strcmp(argv[1], "-about")) { | |
731 | PADabout(); | |
732 | } else { | |
733 | PADconfigure(); | |
734 | } | |
735 | ||
736 | gtk_exit(0); | |
737 | return 0; | |
738 | } |