SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
SDL/open_dialog/gtk.c
1 #include "open_dialog.h"
2 #include <SDL.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <dlfcn.h>
6 #include <stdbool.h>
7 #include <string.h>
8
9 #define GTK_FILE_CHOOSER_ACTION_OPEN 0
10 #define GTK_FILE_CHOOSER_ACTION_SAVE 1
11 #define GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER 2
12 #define GTK_RESPONSE_ACCEPT -3
13 #define GTK_RESPONSE_CANCEL -6
14
15
16 void *_gtk_file_chooser_dialog_new (const char *title,
17 void *parent,
18 int action,
19 const char *first_button_text,
20 ...);
21 bool _gtk_init_check (int *argc, char ***argv);
22 int _gtk_dialog_run(void *);
23 void _g_free(void *);
24 void _gtk_widget_destroy(void *);
25 char *_gtk_file_chooser_get_filename(void *);
26 void _g_log_set_default_handler (void *function, void *data);
27 void *_gtk_file_filter_new(void);
28 void _gtk_file_filter_add_pattern(void *filter, const char *pattern);
29 void _gtk_file_filter_set_name(void *filter, const char *name);
30 void _gtk_file_chooser_add_filter(void *dialog, void *filter);
31 void _gtk_main_iteration(void);
32 bool _gtk_events_pending(void);
33 unsigned long _g_signal_connect_data(void *instance,
34 const char *detailed_signal,
35 void *c_handler,
36 void *data,
37 void *destroy_data,
38 unsigned connect_flags);
39 void _gtk_file_chooser_set_current_name(void *dialog,
40 const char *name);
41 void *_gtk_file_chooser_get_filter(void *dialog);
42 const char *_gtk_file_filter_get_name (void *dialog);
43 #define g_signal_connect(instance, detailed_signal, c_handler, data) \
44 g_signal_connect_data((instance), (detailed_signal), (c_handler), (data), NULL, 0)
45
46
47
48 #define LAZY(symbol) static typeof(_##symbol) *symbol = NULL;\
49 if (symbol == NULL) symbol = dlsym(handle, #symbol);\
50 if (symbol == NULL) goto lazy_error
51 #define TRY_DLOPEN(name) handle = handle? handle : dlopen(name, RTLD_NOW)
52
53 void nop(void){}
54
55 static void wait_mouse_up(void)
56 {
57 while (true) {
58 if (!(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT))) break;
59 SDL_Event event;
60 SDL_PollEvent(&event);
61 }
62 }
63
64 char *do_open_rom_dialog(void)
65 {
66 wait_mouse_up();
67 static void *handle = NULL;
68
69 TRY_DLOPEN("libgtk-3.so");
70 TRY_DLOPEN("libgtk-3.so.0");
71 TRY_DLOPEN("libgtk-2.so");
72 TRY_DLOPEN("libgtk-2.so.0");
73
74 if (!handle) {
75 goto lazy_error;
76 }
77
78
79 LAZY(gtk_init_check);
80 LAZY(gtk_file_chooser_dialog_new);
81 LAZY(gtk_dialog_run);
82 LAZY(g_free);
83 LAZY(gtk_widget_destroy);
84 LAZY(gtk_file_chooser_get_filename);
85 LAZY(g_log_set_default_handler);
86 LAZY(gtk_file_filter_new);
87 LAZY(gtk_file_filter_add_pattern);
88 LAZY(gtk_file_filter_set_name);
89 LAZY(gtk_file_chooser_add_filter);
90 LAZY(gtk_events_pending);
91 LAZY(gtk_main_iteration);
92
93 /* Shut up GTK */
94 g_log_set_default_handler(nop, NULL);
95
96 gtk_init_check(0, 0);
97
98
99 void *dialog = gtk_file_chooser_dialog_new("Open ROM",
100 0,
101 GTK_FILE_CHOOSER_ACTION_OPEN,
102 "_Cancel", GTK_RESPONSE_CANCEL,
103 "_Open", GTK_RESPONSE_ACCEPT,
104 NULL );
105
106
107 void *filter = gtk_file_filter_new();
108 gtk_file_filter_add_pattern(filter, "*.gb");
109 gtk_file_filter_add_pattern(filter, "*.gbc");
110 gtk_file_filter_add_pattern(filter, "*.sgb");
111 gtk_file_filter_add_pattern(filter, "*.isx");
112 gtk_file_filter_set_name(filter, "Game Boy ROMs");
113 gtk_file_chooser_add_filter(dialog, filter);
114
115 int res = gtk_dialog_run(dialog);
116 char *ret = NULL;
117
118 if (res == GTK_RESPONSE_ACCEPT) {
119 char *filename;
120 filename = gtk_file_chooser_get_filename(dialog);
121 ret = strdup(filename);
122 g_free(filename);
123 }
124
125 while (gtk_events_pending()) {
126 gtk_main_iteration();
127 }
128
129 gtk_widget_destroy(dialog);
130
131 while (gtk_events_pending()) {
132 gtk_main_iteration();
133 }
134 return ret;
135
136 lazy_error:
137 fprintf(stderr, "Failed to display GTK dialog\n");
138 return NULL;
139 }
140
141 char *do_open_folder_dialog(void)
142 {
143 wait_mouse_up();
144 static void *handle = NULL;
145
146 TRY_DLOPEN("libgtk-3.so");
147 TRY_DLOPEN("libgtk-3.so.0");
148 TRY_DLOPEN("libgtk-2.so");
149 TRY_DLOPEN("libgtk-2.so.0");
150
151 if (!handle) {
152 goto lazy_error;
153 }
154
155
156 LAZY(gtk_init_check);
157 LAZY(gtk_file_chooser_dialog_new);
158 LAZY(gtk_dialog_run);
159 LAZY(g_free);
160 LAZY(gtk_widget_destroy);
161 LAZY(gtk_file_chooser_get_filename);
162 LAZY(g_log_set_default_handler);
163 LAZY(gtk_file_filter_new);
164 LAZY(gtk_file_filter_add_pattern);
165 LAZY(gtk_file_filter_set_name);
166 LAZY(gtk_file_chooser_add_filter);
167 LAZY(gtk_events_pending);
168 LAZY(gtk_main_iteration);
169
170 /* Shut up GTK */
171 g_log_set_default_handler(nop, NULL);
172
173 gtk_init_check(0, 0);
174
175
176 void *dialog = gtk_file_chooser_dialog_new("Select Boot ROMs Folder",
177 0,
178 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
179 "_Cancel", GTK_RESPONSE_CANCEL,
180 "_Open", GTK_RESPONSE_ACCEPT,
181 NULL );
182
183
184 int res = gtk_dialog_run(dialog);
185 char *ret = NULL;
186
187 if (res == GTK_RESPONSE_ACCEPT) {
188 char *filename;
189 filename = gtk_file_chooser_get_filename(dialog);
190 ret = strdup(filename);
191 g_free(filename);
192 }
193
194 while (gtk_events_pending()) {
195 gtk_main_iteration();
196 }
197
198 gtk_widget_destroy(dialog);
199
200 while (gtk_events_pending()) {
201 gtk_main_iteration();
202 }
203 return ret;
204
205 lazy_error:
206 fprintf(stderr, "Failed to display GTK dialog\n");
207 return NULL;
208 }
209
210 static void filter_changed(void *dialog,
211 void *unused,
212 void *unused2)
213 {
214 static void *handle = NULL;
215
216 TRY_DLOPEN("libgtk-3.so");
217 TRY_DLOPEN("libgtk-3.so.0");
218 TRY_DLOPEN("libgtk-2.so");
219 TRY_DLOPEN("libgtk-2.so.0");
220
221 if (!handle) {
222 goto lazy_error;
223 }
224
225 LAZY(gtk_file_chooser_get_filename);
226 LAZY(gtk_file_chooser_set_current_name);
227 LAZY(g_free);
228 LAZY(gtk_file_chooser_get_filter);
229 LAZY(gtk_file_filter_get_name);
230
231 char *filename = gtk_file_chooser_get_filename(dialog);
232 if (!filename) return;
233 char *temp = filename + strlen(filename);
234 char *basename = filename;
235 bool deleted_extension = false;
236 while (temp != filename) {
237 temp--;
238 if (*temp == '.' && !deleted_extension) {
239 *temp = 0;
240 deleted_extension = true;
241 }
242 else if (*temp == '/') {
243 basename = temp + 1;
244 break;
245 }
246 }
247
248 char *new_filename = NULL;
249
250 switch (gtk_file_filter_get_name(gtk_file_chooser_get_filter(dialog))[1]) {
251 case 'p':
252 default:
253 asprintf(&new_filename, "%s.aiff", basename);
254 break;
255 case 'I':
256 asprintf(&new_filename, "%s.wav", basename);
257 break;
258 case 'a':
259 asprintf(&new_filename, "%s.raw", basename);
260 break;
261 }
262
263
264 gtk_file_chooser_set_current_name(dialog, new_filename);
265 free(new_filename);
266 g_free(filename);
267 return;
268
269 lazy_error:
270 fprintf(stderr, "Failed updating the file extension\n");
271 }
272
273
274 char *do_save_recording_dialog(unsigned frequency)
275 {
276 wait_mouse_up();
277 static void *handle = NULL;
278
279 TRY_DLOPEN("libgtk-3.so");
280 TRY_DLOPEN("libgtk-3.so.0");
281 TRY_DLOPEN("libgtk-2.so");
282 TRY_DLOPEN("libgtk-2.so.0");
283
284 if (!handle) {
285 goto lazy_error;
286 }
287
288
289 LAZY(gtk_init_check);
290 LAZY(gtk_file_chooser_dialog_new);
291 LAZY(gtk_dialog_run);
292 LAZY(g_free);
293 LAZY(gtk_widget_destroy);
294 LAZY(gtk_file_chooser_get_filename);
295 LAZY(g_log_set_default_handler);
296 LAZY(gtk_file_filter_new);
297 LAZY(gtk_file_filter_add_pattern);
298 LAZY(gtk_file_filter_set_name);
299 LAZY(gtk_file_chooser_add_filter);
300 LAZY(gtk_events_pending);
301 LAZY(gtk_main_iteration);
302 LAZY(g_signal_connect_data);
303 LAZY(gtk_file_chooser_set_current_name);
304
305 /* Shut up GTK */
306 g_log_set_default_handler(nop, NULL);
307
308 gtk_init_check(0, 0);
309
310
311 void *dialog = gtk_file_chooser_dialog_new("Audio recording save location",
312 0,
313 GTK_FILE_CHOOSER_ACTION_SAVE,
314 "_Cancel", GTK_RESPONSE_CANCEL,
315 "_Save", GTK_RESPONSE_ACCEPT,
316 NULL );
317
318
319 void *filter = gtk_file_filter_new();
320 gtk_file_filter_add_pattern(filter, "*.aiff");
321 gtk_file_filter_add_pattern(filter, "*.aif");
322 gtk_file_filter_add_pattern(filter, "*.aifc");
323 gtk_file_filter_set_name(filter, "Apple AIFF");
324 gtk_file_chooser_add_filter(dialog, filter);
325
326 filter = gtk_file_filter_new();
327 gtk_file_filter_add_pattern(filter, "*.wav");
328 gtk_file_filter_set_name(filter, "RIFF WAVE");
329 gtk_file_chooser_add_filter(dialog, filter);
330
331 filter = gtk_file_filter_new();
332 gtk_file_filter_add_pattern(filter, "*.raw");
333 gtk_file_filter_add_pattern(filter, "*.pcm");
334 static char raw_name[40];
335 #ifdef GB_BIG_ENDIAN
336 sprintf(raw_name, "Raw PCM (Stereo %dHz, 16-bit BE)", frequency);
337 #else
338 sprintf(raw_name, "Raw PCM (Stereo %dHz, 16-bit LE)", frequency);
339 #endif
340 gtk_file_filter_set_name(filter, raw_name);
341 gtk_file_chooser_add_filter(dialog, filter);
342
343 g_signal_connect(dialog, "notify::filter", filter_changed, NULL);
344 gtk_file_chooser_set_current_name(dialog, "Untitled.aiff");
345
346 int res = gtk_dialog_run(dialog);
347 char *ret = NULL;
348
349 if (res == GTK_RESPONSE_ACCEPT) {
350 char *filename;
351 filename = gtk_file_chooser_get_filename(dialog);
352 ret = strdup(filename);
353 g_free(filename);
354 }
355
356 while (gtk_events_pending()) {
357 gtk_main_iteration();
358 }
359
360 gtk_widget_destroy(dialog);
361
362 while (gtk_events_pending()) {
363 gtk_main_iteration();
364 }
365 return ret;
366
367 lazy_error:
368 fprintf(stderr, "Failed to display GTK dialog\n");
369 return NULL;
370 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.