redesigned fremantle launcher
[drnoksnes] / gui / plugin.c
1 /*
2 * This file is part of DrNokSnes
3 *
4 * Copyright (C) 2005 INdT - Instituto Nokia de Tecnologia
5 * http://www.indt.org/maemo
6 * Copyright (C) 2009 Javier S. Pedro <maemo@javispedro.com>
7 *
8 * This software is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This software is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this software; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <gtk/gtk.h>
28 #include <startup_plugin.h>
29 #include <gconf/gconf.h>
30 #include <gconf/gconf-client.h>
31 #include <hildon/hildon-file-chooser-dialog.h>
32 #include <hildon/hildon-note.h>
33 #include <hildon/hildon-defines.h>
34
35 #if MAEMO_VERSION >= 5
36 #include <hildon/hildon-button.h>
37 #include <hildon/hildon-check-button.h>
38 #include <hildon/hildon-picker-button.h>
39 #include <hildon/hildon-touch-selector.h>
40 #include <hildon/hildon-gtk.h>
41 #else
42 #include <hildon/hildon-caption.h>
43 #endif
44
45 #include "../platform/hgw.h"
46 #include "plugin.h"
47
48 static GtkWidget * load_plugin(void);
49 static void unload_plugin(void);
50 static void write_config(void);
51 static GtkWidget ** load_menu(guint *);
52 static void update_menu(void);
53 static void plugin_callback(GtkWidget * menu_item, gpointer data);
54
55 GConfClient * gcc = NULL;
56 static GameStartupInfo gs;
57 static GtkWidget * menu_items[4];
58
59 static StartupPluginInfo plugin_info = {
60         load_plugin,
61         unload_plugin,
62         write_config,
63         load_menu,
64         update_menu,
65         plugin_callback
66 };
67
68 STARTUP_INIT_PLUGIN(plugin_info, gs, FALSE, TRUE)
69
70 gchar* current_rom_file = 0;
71 gboolean current_rom_file_exists = FALSE;
72
73 #if MAEMO_VERSION >= 5
74 static HildonButton* select_rom_btn;
75 static HildonCheckButton* audio_check;
76 static HildonPickerButton* framerate_picker;
77 static HildonCheckButton* display_fps_check;
78 static HildonCheckButton* turbo_check;
79 // speedhacks=no and accuracy=yes in fremantle
80 #else
81 static GtkLabel* rom_label;
82 static GtkCheckButton* audio_check;
83 static GtkCheckButton* turbo_check;
84 static GtkComboBox* framerate_combo;
85 static GtkCheckButton* accu_check;
86 static GtkCheckButton* display_fps_check;
87 static GtkComboBox* speedhacks_combo;
88 #endif
89
90 static void set_rom(const char * rom_file)
91 {
92         if (current_rom_file) g_free(current_rom_file);
93         if (!rom_file) {
94                 current_rom_file = NULL;
95                 return;
96         }
97
98         current_rom_file = g_strdup(rom_file);
99
100         gchar * utf8_filename = g_filename_display_basename(rom_file);
101 #if MAEMO_VERSION >= 5
102         hildon_button_set_value(select_rom_btn, utf8_filename);
103 #else
104         gtk_label_set_text(GTK_LABEL(rom_label), utf8_filename);
105 #endif
106         g_free(utf8_filename);
107
108         current_rom_file_exists = g_file_test(current_rom_file,
109                 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR);
110
111         game_state_update();
112         save_clear();
113 }
114
115 static inline GtkWindow* get_parent_window() {
116         return GTK_WINDOW(gs.ui->hildon_appview);
117 }
118
119 static void select_rom_callback(GtkWidget * button, gpointer data)
120 {
121         GtkWidget * dialog;
122         GtkFileFilter * filter;
123         gchar * filename = NULL;
124
125         filter = gtk_file_filter_new();
126         gtk_file_filter_add_pattern(filter, "*.smc");
127         gtk_file_filter_add_pattern(filter, "*.sfc");
128         gtk_file_filter_add_pattern(filter, "*.fig");
129         gtk_file_filter_add_pattern(filter, "*.smc.gz");
130         gtk_file_filter_add_pattern(filter, "*.sfc.gz");
131         gtk_file_filter_add_pattern(filter, "*.fig.gz");
132
133         dialog = hildon_file_chooser_dialog_new_with_properties(
134                 get_parent_window(),
135                 "action", GTK_FILE_CHOOSER_ACTION_OPEN,
136                 "local-only", TRUE,
137                 "filter", filter,
138                 NULL);
139         hildon_file_chooser_dialog_set_show_upnp(HILDON_FILE_CHOOSER_DIALOG(dialog),
140                 FALSE);
141
142         if (current_rom_file_exists) {
143                 // By default open showing the last selected file
144                 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), 
145                         current_rom_file);
146         }
147
148         gtk_widget_show_all(GTK_WIDGET(dialog));
149         if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
150                 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
151         }
152
153         gtk_widget_destroy(dialog);
154
155         if (filename) {
156                 set_rom(filename);
157                 g_free(filename);
158         }
159 }
160
161 static void controls_item_callback(GtkWidget * button, gpointer data)
162 {
163         controls_setup();
164         controls_dialog(get_parent_window());
165 }
166
167 static void about_item_callback(GtkWidget * button, gpointer data)
168 {
169         about_dialog(get_parent_window());
170 }
171
172 static GtkWidget * load_plugin(void)
173 {
174         g_type_init();
175         gcc = gconf_client_get_default();
176
177         GtkWidget* parent = gtk_vbox_new(FALSE, HILDON_MARGIN_DEFAULT);
178
179
180 /* Select ROM button */
181 #if MAEMO_VERSION >= 5
182         select_rom_btn = HILDON_BUTTON(hildon_button_new_with_text(
183                 HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT,
184                 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
185                 "ROM",
186                 NULL));
187         gtk_box_pack_start(GTK_BOX(parent), GTK_WIDGET(select_rom_btn), FALSE, FALSE, 0);
188 #else
189 {
190         GtkWidget* rom_hbox = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT);
191         GtkWidget* select_rom_btn = gtk_button_new_with_label("Select ROM...");
192         gtk_widget_set_size_request(GTK_WIDGET(select_rom_btn), 180, 46);
193         rom_label = GTK_LABEL(gtk_label_new(NULL));
194
195         gtk_box_pack_start(GTK_BOX(rom_hbox), GTK_WIDGET(select_rom_btn), FALSE, FALSE, 0);
196         gtk_box_pack_start(GTK_BOX(rom_hbox), GTK_WIDGET(rom_label), TRUE, TRUE, 0);
197         gtk_box_pack_start(GTK_BOX(parent), rom_hbox, FALSE, FALSE, 0);
198 }
199 #endif
200
201 /* First row of widgets */
202 #if MAEMO_VERSION >= 5
203 {
204         GtkBox* opt_hbox1 = GTK_BOX(gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT));
205         audio_check =
206                 HILDON_CHECK_BUTTON(hildon_check_button_new(HILDON_SIZE_AUTO));
207         gtk_button_set_label(GTK_BUTTON(audio_check), "Sound");
208
209         framerate_picker = HILDON_PICKER_BUTTON(hildon_picker_button_new(
210                 HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_HORIZONTAL));
211         hildon_button_set_title(HILDON_BUTTON(framerate_picker), "Target framerate");
212
213         HildonTouchSelector* framerate_sel =
214                 HILDON_TOUCH_SELECTOR(hildon_touch_selector_new_text());
215         hildon_touch_selector_append_text(framerate_sel, "Auto");
216         for (int i = 1; i < 10; i++) {
217                 gchar buffer[20];
218                 sprintf(buffer, "%d-%d", 50/i, 60/i);
219                 hildon_touch_selector_append_text(framerate_sel, buffer);
220         }
221         hildon_picker_button_set_selector(framerate_picker, framerate_sel);
222
223         GtkBox* framerate_sel_box = GTK_BOX(gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT));
224
225         display_fps_check =
226                 HILDON_CHECK_BUTTON(hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT));
227         gtk_button_set_label(GTK_BUTTON(display_fps_check),
228                 "Show while in game");
229         turbo_check =
230                 HILDON_CHECK_BUTTON(hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT));
231         gtk_button_set_label(GTK_BUTTON(turbo_check),
232                 "Turbo mode");
233
234         gtk_box_pack_start_defaults(framerate_sel_box, GTK_WIDGET(display_fps_check));
235         gtk_box_pack_start_defaults(framerate_sel_box, GTK_WIDGET(turbo_check));
236         gtk_box_pack_start(GTK_BOX(framerate_sel), GTK_WIDGET(framerate_sel_box), FALSE, FALSE, 0);
237         gtk_widget_show_all(GTK_WIDGET(framerate_sel_box));
238
239         gtk_box_pack_start_defaults(opt_hbox1, GTK_WIDGET(audio_check));
240         gtk_box_pack_start_defaults(opt_hbox1, GTK_WIDGET(framerate_picker));
241         gtk_box_pack_start(GTK_BOX(parent), GTK_WIDGET(opt_hbox1), FALSE, FALSE, 0);
242 }
243 #else
244 {
245         GtkBox* opt_hbox1 = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT);
246         audio_check =
247                 GTK_CHECK_BUTTON(gtk_check_button_new_with_label("Audio"));
248
249         turbo_check =
250                 GTK_CHECK_BUTTON(gtk_check_button_new_with_label("Turbo mode"));
251         display_fps_check =
252                 GTK_CHECK_BUTTON(gtk_check_button_new_with_label("Display framerate"));
253         speedhacks_combo =
254                 GTK_COMBO_BOX(gtk_combo_box_new_text());
255
256         gtk_box_pack_start(opt_hbox1, GTK_WIDGET(audio_check), FALSE, FALSE, 0);
257         gtk_box_pack_start(opt_hbox1, GTK_WIDGET(display_fps_check), TRUE, FALSE, 0);
258         gtk_box_pack_start(opt_hbox1, GTK_WIDGET(turbo_check), FALSE, FALSE, 0);
259         gtk_box_pack_start(GTK_BOX(parent), opt_hbox1, FALSE, FALSE, 0);
260 }
261 #endif
262
263 #if 0
264         GtkBox* framerate_box = GTK_BOX(gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT));
265         GtkWidget* framerate_label = gtk_label_new("Framerate:");
266         gtk_box_pack_start(framerate_box, framerate_label, FALSE, FALSE, 0);
267         gtk_box_pack_start(framerate_box, GTK_WIDGET(framerate_combo), FALSE, FALSE, 0);
268 #endif
269
270 /* Second row of widgets */
271 #if MAEMO_VERSION >= 5
272 #else
273 {
274         GtkBox* opt_hbox2 = GTK_BOX(gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT));
275
276         accu_check =
277                 GTK_CHECK_BUTTON(gtk_check_button_new_with_label("Accurate graphics"));
278
279         framerate_combo =
280                 GTK_COMBO_BOX(gtk_combo_box_new_text());
281         GtkWidget* framerate_box = hildon_caption_new(NULL, "Framerate:",
282                 GTK_WIDGET(framerate_combo), NULL, HILDON_CAPTION_OPTIONAL);
283
284         gtk_combo_box_append_text(framerate_combo, "Auto");
285         for (int i = 1; i < 10; i++) {
286                 gchar buffer[20];
287                 sprintf(buffer, "%d-%d", 50/i, 60/i);
288                 gtk_combo_box_append_text(framerate_combo, buffer);
289         }
290         gtk_combo_box_append_text(speedhacks_combo, "No speedhacks");
291         gtk_combo_box_append_text(speedhacks_combo, "Safe hacks only");
292         gtk_combo_box_append_text(speedhacks_combo, "All speedhacks");
293
294         gtk_box_pack_start(opt_hbox2, GTK_WIDGET(accu_check), FALSE, FALSE, 0);
295         gtk_box_pack_start(opt_hbox2, GTK_WIDGET(framerate_box), TRUE, FALSE, 0);
296         gtk_box_pack_start(opt_hbox2, GTK_WIDGET(speedhacks_combo), FALSE, FALSE, 0);
297         gtk_box_pack_start(GTK_BOX(parent), GTK_WIDGET(opt_hbox2), FALSE, FALSE, 0);
298 }
299 #endif
300
301 /* Load current configuration from GConf */
302 #if MAEMO_VERSION >= 5
303         hildon_check_button_set_active(audio_check,
304                 !gconf_client_get_bool(gcc, kGConfDisableAudio, NULL));
305         hildon_picker_button_set_active(framerate_picker,
306                 gconf_client_get_int(gcc, kGConfFrameskip, NULL));
307         hildon_check_button_set_active(turbo_check,
308                 gconf_client_get_bool(gcc, kGConfTurboMode, NULL));
309         hildon_check_button_set_active(display_fps_check,
310                 gconf_client_get_int(gcc, kGConfDisplayFramerate, NULL));
311 #else
312         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(audio_check),
313                 !gconf_client_get_bool(gcc, kGConfDisableAudio, NULL));
314         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(turbo_check),
315                 gconf_client_get_bool(gcc, kGConfTurboMode, NULL));
316         gtk_combo_box_set_active(framerate_combo,
317                 gconf_client_get_int(gcc, kGConfFrameskip, NULL));
318         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(accu_check),
319                 gconf_client_get_bool(gcc, kGConfTransparency, NULL));
320         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(display_fps_check),
321                 gconf_client_get_int(gcc, kGConfDisplayFramerate, NULL));
322         gtk_combo_box_set_active(speedhacks_combo,
323                 gconf_client_get_int(gcc, kGConfSpeedhacks, NULL));
324 #endif
325
326         set_rom(gconf_client_get_string(gcc, kGConfRomFile, NULL));
327
328         // Connect signals
329         g_signal_connect(G_OBJECT(select_rom_btn), "clicked",
330                                         G_CALLBACK(select_rom_callback), NULL);
331 printf("ui done\n");
332         return parent;
333 }
334
335 static void unload_plugin(void)
336 {
337         if (current_rom_file) {
338                 g_free(current_rom_file);
339                 current_rom_file = 0;
340         }
341         game_state_clear();
342         save_clear();
343         g_object_unref(gcc);
344 }
345
346 static void write_config(void)
347 {
348 /* Write current settings to gconf */
349 #if MAEMO_VERSION >= 5
350         gconf_client_set_bool(gcc, kGConfDisableAudio,
351                 !hildon_check_button_get_active(audio_check), NULL);
352         gconf_client_set_int(gcc, kGConfFrameskip,
353                 hildon_picker_button_get_active(framerate_picker), NULL);
354         gconf_client_set_bool(gcc, kGConfDisplayFramerate,
355                 hildon_check_button_get_active(display_fps_check), NULL);
356         gconf_client_set_bool(gcc, kGConfTurboMode,
357                 hildon_check_button_get_active(turbo_check), NULL);
358
359         // For now, transparencies are always enabled in Fremantle
360         gconf_client_set_bool(gcc, kGConfTransparency, TRUE, NULL);
361         // Speedhacks always disabled
362         gconf_client_set_int(gcc, kGConfSpeedhacks,     FALSE, NULL);
363 #else
364         gconf_client_set_bool(gcc, kGConfDisableAudio,
365                 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(audio_check)), NULL);
366         gconf_client_set_bool(gcc, kGConfTurboMode,
367                 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(turbo_check)), NULL);
368         gconf_client_set_int(gcc, kGConfFrameskip,
369                 gtk_combo_box_get_active(framerate_combo), NULL);
370         gconf_client_set_bool(gcc, kGConfTransparency,
371                 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(accu_check)), NULL);
372         gconf_client_set_bool(gcc, kGConfDisplayFramerate,
373                 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(display_fps_check)), NULL);
374         gconf_client_set_int(gcc, kGConfSpeedhacks,
375                 gtk_combo_box_get_active(speedhacks_combo), NULL);
376 #endif
377
378         if (current_rom_file) {
379                 gconf_client_set_string(gcc, kGConfRomFile, current_rom_file, NULL);
380         }
381
382         controls_setup();
383 }
384
385 static GtkWidget **load_menu(guint *nitems)
386 {
387 #if MAEMO_VERSION >= 5
388         const HildonSizeType button_size =
389                 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH;
390         menu_items[0] = hildon_gtk_button_new(button_size);
391         gtk_button_set_label(GTK_BUTTON(menu_items[0]), "Placeholder");
392         menu_items[1] = hildon_gtk_button_new(button_size);
393         gtk_button_set_label(GTK_BUTTON(menu_items[1]), "Controls…");
394         menu_items[2] = hildon_gtk_button_new(button_size);
395         gtk_button_set_label(GTK_BUTTON(menu_items[2]), "About…");
396         *nitems = 3;
397
398         g_signal_connect(G_OBJECT(menu_items[1]), "clicked",
399                                         G_CALLBACK(controls_item_callback), NULL);
400         g_signal_connect(G_OBJECT(menu_items[2]), "clicked",
401                                         G_CALLBACK(about_item_callback), NULL);
402 #else
403         menu_items[0] = gtk_menu_item_new_with_label("Settings");
404         menu_items[1] = gtk_menu_item_new_with_label("About…");
405         *nitems = 2;
406
407         GtkMenu* settings_menu = GTK_MENU(gtk_menu_new());
408         GtkMenuItem* controls_item =
409                 GTK_MENU_ITEM(gtk_menu_item_new_with_label("Controls…"));
410         
411         gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_items[0]),
412                 GTK_WIDGET(settings_menu));
413         gtk_menu_append(GTK_MENU(settings_menu), GTK_WIDGET(controls_item));
414
415         g_signal_connect(G_OBJECT(controls_item), "activate",
416                                         G_CALLBACK(controls_item_callback), NULL);
417         g_signal_connect(G_OBJECT(menu_items[1]), "activate",
418                                         G_CALLBACK(about_item_callback), NULL);
419 #endif
420
421         return menu_items;
422 }
423
424 static void update_menu(void)
425 {
426         // Nothing to update in the current menu
427 }
428
429 static void plugin_callback(GtkWidget * menu_item, gpointer data)
430 {
431         switch ((gint) data) {
432                 case 20:        // ME_GAME_OPEN
433                         save_load(get_parent_window());
434                         break;
435                 case 21:        // ME_GAME_SAVE
436                         save_save(get_parent_window());
437                         break;
438                 case 22:        // ME_GAME_SAVE_AS
439                         save_save_as(get_parent_window());
440                         break;
441                 case 30:        // MA_GAME_PLAYING_START
442                         if (!menu_item) {
443                                 // Avoid duplicate message
444                                 break;
445                         }
446                         if (!current_rom_file) {
447                                 GtkWidget* note = hildon_note_new_information(get_parent_window(),
448                                         "No ROM selected");
449                                 gtk_dialog_run(GTK_DIALOG(note));
450                                 gtk_widget_destroy(note);
451                         } else if (!current_rom_file_exists) {
452                                 GtkWidget* note = hildon_note_new_information(get_parent_window(),
453                                         "ROM file does not exist");
454                                 gtk_dialog_run(GTK_DIALOG(note));
455                                 gtk_widget_destroy(note);
456                         }
457                         break;
458         }
459 }
460