pcsxr-1.9.92
[pcsx_rearmed.git] / plugins / dfinput / cfg-gtk2.c
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 }