Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/gtk/yuiwindow.c
2 views
1
/* Copyright 2006 Guillaume Duhamel
2
3
This file is part of Yabause.
4
5
Yabause 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
Yabause 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 Yabause; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
*/
19
20
#include <gtk/gtk.h>
21
#include <gdk/gdkkeysyms.h>
22
23
#include "yuiwindow.h"
24
#include "gtkglwidget.h"
25
#include "../yabause.h"
26
27
#include "settings.h"
28
29
static void yui_window_class_init (YuiWindowClass * klass);
30
static void yui_window_init (YuiWindow * yfe);
31
static gboolean yui_window_keypress(GtkWidget *widget, GdkEventKey *event, gpointer user_data);
32
static gboolean yui_window_keyrelease(GtkWidget *widget, GdkEventKey *event, gpointer user_data);
33
static void yui_window_keep_clean(GtkWidget * widget, GdkEventExpose * event, YuiWindow * yui);
34
static void yui_window_toggle_fullscreen(GtkWidget * w, YuiWindow * yui);
35
static void yui_window_toggle_frameskip(GtkWidget * w, YuiWindow * yui);
36
37
static void yui_window_create_actions(YuiWindow * yw) {
38
GtkAction * action;
39
GtkToggleAction * taction;
40
41
action = gtk_action_new("run", _("Run"), _("start emulation"), "gtk-media-play");
42
gtk_action_group_add_action_with_accel(yw->action_group, action, "<Ctrl>r");
43
g_signal_connect_swapped(action, "activate", G_CALLBACK(yui_window_run), yw);
44
45
action = gtk_action_new("pause", _("Pause"), _("pause emulation"), "gtk-media-pause");
46
gtk_action_group_add_action_with_accel(yw->action_group, action, "<Ctrl>p");
47
g_signal_connect_swapped(action, "activate", G_CALLBACK(yui_window_pause), yw);
48
49
action = gtk_action_new("reset", _("Reset"), _("reset emulation"), NULL);
50
gtk_action_group_add_action_with_accel(yw->action_group, action, NULL);
51
g_signal_connect_swapped(action, "activate", G_CALLBACK(yui_window_reset), yw);
52
53
taction = gtk_toggle_action_new("fullscreen", _("Fullscreen"), NULL, "gtk-fullscreen");
54
gtk_action_group_add_action_with_accel(yw->action_group, GTK_ACTION(taction), "<Ctrl>f");
55
g_signal_connect(taction, "activate", G_CALLBACK(yui_window_toggle_fullscreen), yw);
56
57
taction = gtk_toggle_action_new("frameskip", _("Frame Skip/Limiter"), NULL, NULL);
58
gtk_action_group_add_action_with_accel(yw->action_group, GTK_ACTION(taction), NULL);
59
g_signal_connect(taction, "activate", G_CALLBACK(yui_window_toggle_frameskip), yw);
60
61
action = gtk_action_new("quit", _("Quit"), NULL, "gtk-quit");
62
gtk_action_group_add_action_with_accel(yw->action_group, action, "<Ctrl>q");
63
g_signal_connect(action, "activate", G_CALLBACK(gtk_main_quit), yw);
64
65
taction = gtk_toggle_action_new("toggle_vdp1", _("VDP1"), NULL, NULL);
66
gtk_toggle_action_set_active(taction, TRUE);
67
gtk_action_group_add_action_with_accel(yw->action_group, GTK_ACTION(taction), NULL);
68
g_signal_connect(taction, "activate", G_CALLBACK(ToggleVDP1), NULL);
69
70
taction = gtk_toggle_action_new("toggle_nbg0", _("NBG0"), NULL, NULL);
71
gtk_toggle_action_set_active(taction, TRUE);
72
gtk_action_group_add_action_with_accel(yw->action_group, GTK_ACTION(taction), NULL);
73
g_signal_connect(taction, "activate", G_CALLBACK(ToggleNBG0), NULL);
74
75
taction = gtk_toggle_action_new("toggle_nbg1", _("NBG1"), NULL, NULL);
76
gtk_toggle_action_set_active(taction, TRUE);
77
gtk_action_group_add_action_with_accel(yw->action_group, GTK_ACTION(taction), NULL);
78
g_signal_connect(taction, "activate", G_CALLBACK(ToggleNBG1), NULL);
79
80
taction = gtk_toggle_action_new("toggle_nbg2", _("NBG2"), NULL, NULL);
81
gtk_toggle_action_set_active(taction, TRUE);
82
gtk_action_group_add_action_with_accel(yw->action_group, GTK_ACTION(taction), NULL);
83
g_signal_connect(taction, "activate", G_CALLBACK(ToggleNBG2), NULL);
84
85
taction = gtk_toggle_action_new("toggle_nbg3", _("NBG3"), NULL, NULL);
86
gtk_toggle_action_set_active(taction, TRUE);
87
gtk_action_group_add_action_with_accel(yw->action_group, GTK_ACTION(taction), NULL);
88
g_signal_connect(taction, "activate", G_CALLBACK(ToggleNBG3), NULL);
89
90
taction = gtk_toggle_action_new("toggle_rbg0", _("RBG0"), NULL, NULL);
91
gtk_toggle_action_set_active(taction, TRUE);
92
gtk_action_group_add_action_with_accel(yw->action_group, GTK_ACTION(taction), NULL);
93
g_signal_connect(taction, "activate", G_CALLBACK(ToggleRBG0), NULL);
94
}
95
96
GType yui_window_get_type (void) {
97
static GType yfe_type = 0;
98
99
if (!yfe_type)
100
{
101
static const GTypeInfo yfe_info =
102
{
103
sizeof (YuiWindowClass),
104
NULL, /* base_init */
105
NULL, /* base_finalize */
106
(GClassInitFunc) yui_window_class_init,
107
NULL, /* class_finalize */
108
NULL, /* class_data */
109
sizeof (YuiWindow),
110
0,
111
(GInstanceInitFunc) yui_window_init,
112
NULL,
113
};
114
115
yfe_type = g_type_register_static(GTK_TYPE_WINDOW, "YuiWindow", &yfe_info, 0);
116
}
117
118
return yfe_type;
119
}
120
121
enum { YUI_WINDOW_RUNNING_SIGNAL, YUI_WINDOW_PAUSED_SIGNAL, LAST_SIGNAL };
122
123
static guint yui_window_signals[LAST_SIGNAL] = { 0, 0 };
124
125
static void yui_window_class_init (YuiWindowClass * klass) {
126
yui_window_signals[YUI_WINDOW_RUNNING_SIGNAL] = g_signal_new ("running", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
127
G_STRUCT_OFFSET(YuiWindowClass, yui_window_running), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
128
yui_window_signals[YUI_WINDOW_PAUSED_SIGNAL] = g_signal_new ("paused", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
129
G_STRUCT_OFFSET(YuiWindowClass, yui_window_paused), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
130
}
131
132
static void yui_set_accel_group(gpointer action, gpointer group) {
133
gtk_action_set_accel_group(action, group);
134
}
135
136
static gboolean yui_window_log_delete(GtkWidget *widget, GdkEvent *event, YuiWindow *yw ) {
137
138
yui_window_show_log( yw );
139
140
return TRUE; /* hide instead of killing */
141
}
142
143
extern gchar * inifile;
144
145
static void yui_window_destroy(GtkWidget * window) {
146
gint x, y;
147
char buffer[512];
148
149
gtk_window_get_position(GTK_WINDOW(window), &x, &y);
150
151
sprintf(buffer, "%d", x);
152
g_key_file_set_value(keyfile, "Gtk", "X", buffer);
153
sprintf(buffer, "%d", y);
154
g_key_file_set_value(keyfile, "Gtk", "Y", buffer);
155
156
g_file_set_contents(inifile, g_key_file_to_data(keyfile, 0, 0), -1, 0);
157
gtk_main_quit();
158
}
159
160
static void yui_window_init (YuiWindow * yw) {
161
GtkAccelGroup * accel_group = gtk_accel_group_new();
162
GtkWidget * scroll;
163
164
yw->action_group = gtk_action_group_new("yui");
165
yui_window_create_actions(yw);
166
gtk_action_set_sensitive(gtk_action_group_get_action(yw->action_group, "pause"), FALSE);
167
gtk_action_set_sensitive(gtk_action_group_get_action(yw->action_group, "reset"), FALSE);
168
{
169
GList * list = gtk_action_group_list_actions(yw->action_group);
170
g_list_foreach(list, yui_set_accel_group, accel_group);
171
}
172
gtk_window_add_accel_group(GTK_WINDOW(yw), accel_group);
173
174
{
175
const gchar * const * data_dir;
176
gboolean pngfound = FALSE;
177
gchar * pngfile;
178
179
data_dir = g_get_system_data_dirs();
180
while (!pngfound && (*data_dir != NULL)) {
181
pngfile = g_build_filename(*data_dir, "pixmaps", "yabause.png", NULL);
182
if (g_file_test(pngfile, G_FILE_TEST_EXISTS)) {
183
gtk_window_set_icon(GTK_WINDOW(yw), gdk_pixbuf_new_from_file(pngfile, NULL));
184
pngfound = TRUE;
185
}
186
data_dir++;
187
}
188
189
if (!pngfound) {
190
gtk_window_set_icon(GTK_WINDOW(yw), gdk_pixbuf_new_from_file("yabause.png", NULL));
191
}
192
}
193
194
gtk_window_set_title (GTK_WINDOW(yw), "Yabause");
195
196
yw->box = gtk_vbox_new(FALSE, 0);
197
gtk_container_add(GTK_CONTAINER(yw), yw->box);
198
199
yw->menu = create_menu(yw);
200
gtk_box_pack_start(GTK_BOX(yw->box), yw->menu, FALSE, FALSE, 0);
201
202
yw->area = yui_gl_new();
203
gtk_box_pack_start(GTK_BOX(yw->box), yw->area, TRUE, TRUE, 0);
204
gtk_widget_set_size_request(GTK_WIDGET(yw->area), 320, 224);
205
206
g_signal_connect(G_OBJECT(yw), "delete-event", G_CALLBACK(yui_window_destroy), NULL);
207
g_signal_connect(G_OBJECT(yw), "key-press-event", G_CALLBACK(yui_window_keypress), yw);
208
g_signal_connect(G_OBJECT(yw), "key-release-event", G_CALLBACK(yui_window_keyrelease), yw);
209
210
yw->logpopup = gtk_window_new(GTK_WINDOW_TOPLEVEL);
211
gtk_window_set_title( GTK_WINDOW( yw->logpopup ), "Yabause Logs" );
212
gtk_widget_set_size_request( yw->logpopup, 500, 300 );
213
scroll = gtk_scrolled_window_new(NULL, NULL);
214
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
215
gtk_container_add(GTK_CONTAINER(yw->logpopup), scroll);
216
g_signal_connect(G_OBJECT(yw->logpopup), "delete-event", G_CALLBACK(yui_window_log_delete), yw);
217
218
yw->log = gtk_text_view_new();
219
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), yw->log);
220
221
gtk_widget_show(yw->box);
222
gtk_widget_show_all(yw->menu);
223
gtk_widget_show(yw->area);
224
225
yw->clean_handler = g_signal_connect(yw->area, "expose-event", G_CALLBACK(yui_window_keep_clean), yw);
226
yw->state = 0;
227
}
228
229
GtkWidget * yui_window_new(YuiAction * act, GCallback ifunc, gpointer idata,
230
GSourceFunc rfunc, GCallback resetfunc) {
231
GtkWidget * widget;
232
YuiWindow * yw;
233
234
widget = GTK_WIDGET(g_object_new(yui_window_get_type(), NULL));
235
yw = YUI_WINDOW(widget);
236
237
yw->actions = act;
238
yw->init_func = ifunc;
239
yw->init_data = idata;
240
yw->run_func = rfunc;
241
yw->reset_func = resetfunc;
242
243
return widget;
244
}
245
246
void yui_window_toggle_fullscreen(GtkWidget * w, YuiWindow * yui) {
247
GtkAction * action = gtk_action_group_get_action(yui->action_group, "fullscreen");
248
static unsigned int beforefswidth = 1;
249
static unsigned int beforefsheight = 1;
250
251
if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))) {
252
beforefswidth = GTK_WIDGET(yui)->allocation.width;
253
beforefsheight = GTK_WIDGET(yui)->allocation.height;
254
gtk_widget_hide(yui->menu);
255
gtk_window_fullscreen(GTK_WINDOW(yui));
256
} else {
257
gtk_window_unfullscreen(GTK_WINDOW(yui));
258
gtk_widget_show(yui->menu);
259
gtk_window_resize(GTK_WINDOW(yui), beforefswidth, beforefsheight);
260
}
261
}
262
263
void yui_window_toggle_frameskip(GtkWidget * w, YuiWindow * yui) {
264
GtkAction * action = gtk_action_group_get_action(yui->action_group, "frameskip");
265
gboolean active = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
266
267
if (active)
268
EnableAutoFrameSkip ();
269
else
270
DisableAutoFrameSkip ();
271
}
272
273
static gboolean yui_window_keypress(GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
274
PerKeyDown(event->keyval);
275
276
return FALSE;
277
}
278
279
static gboolean yui_window_keyrelease(GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
280
PerKeyUp(event->keyval);
281
282
return FALSE;
283
}
284
285
void yui_window_update(YuiWindow * yui) {
286
287
if (!(yui->state & YUI_IS_RUNNING)) yui_gl_draw_pause(YUI_GL(yui->area));
288
else yui_gl_draw(YUI_GL(yui->area));
289
}
290
291
void yui_window_log(YuiWindow * yui, const char * message) {
292
GtkTextBuffer * buffer;
293
GtkTextIter iter;
294
295
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(yui->log));
296
gtk_text_buffer_get_start_iter(buffer, &iter);
297
gtk_text_buffer_insert(buffer, &iter, message, -1);
298
}
299
300
void yui_window_show_log(YuiWindow * yui) {
301
static int i = 0;
302
if (i)
303
gtk_widget_hide(yui->logpopup);
304
else
305
gtk_widget_show_all(yui->logpopup);
306
i = !i;
307
}
308
309
static void yui_window_keep_clean(GtkWidget * widget, GdkEventExpose * event, YuiWindow * yui) {
310
#ifdef HAVE_LIBGTKGLEXT
311
glClear(GL_COLOR_BUFFER_BIT);
312
#endif
313
yui_window_update(yui);
314
}
315
316
void yui_window_start(YuiWindow * yui) {
317
if ((yui->state & YUI_IS_INIT) == 0) {
318
if (((int (*)(gpointer)) yui->init_func)(yui->init_data) == 0) {
319
yui->state |= YUI_IS_INIT;
320
gtk_action_set_sensitive(gtk_action_group_get_action(yui->action_group, "reset"), TRUE);
321
VIDCore->Resize(GTK_WIDGET(yui->area)->allocation.width, GTK_WIDGET(yui->area)->allocation.height, FALSE);
322
}
323
}
324
}
325
326
void yui_window_run(YuiWindow * yui) {
327
yui_window_start(yui);
328
329
if ((yui->state & YUI_IS_INIT) && ((yui->state & YUI_IS_RUNNING) == 0)) {
330
ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
331
g_idle_add(yui->run_func, GINT_TO_POINTER(1));
332
g_signal_emit(G_OBJECT(yui), yui_window_signals[YUI_WINDOW_RUNNING_SIGNAL], 0);
333
yui->state |= YUI_IS_RUNNING;
334
gtk_action_set_sensitive(gtk_action_group_get_action(yui->action_group, "run"), FALSE);
335
gtk_action_set_sensitive(gtk_action_group_get_action(yui->action_group, "pause"), TRUE);
336
}
337
}
338
339
void yui_window_pause(YuiWindow * yui) {
340
if (yui->state & YUI_IS_RUNNING) {
341
yui_gl_dump_screen(YUI_GL(yui->area));
342
ScspMuteAudio(SCSP_MUTE_SYSTEM);
343
g_idle_remove_by_data(GINT_TO_POINTER(1));
344
g_signal_emit(G_OBJECT(yui), yui_window_signals[YUI_WINDOW_PAUSED_SIGNAL], 0);
345
yui->state &= ~YUI_IS_RUNNING;
346
gtk_action_set_sensitive(gtk_action_group_get_action(yui->action_group, "run"), TRUE);
347
gtk_action_set_sensitive(gtk_action_group_get_action(yui->action_group, "pause"), FALSE);
348
}
349
}
350
351
void yui_window_reset(YuiWindow * yui) {
352
if (yui->state & YUI_IS_INIT) {
353
yui->reset_func();
354
}
355
}
356
357
void yui_window_invalidate(YuiWindow * yui) {
358
359
/* Emit a pause signal while already in pause means refresh all debug views */
360
361
if ( !(yui->state & YUI_IS_RUNNING ))
362
g_signal_emit(G_OBJECT(yui), yui_window_signals[YUI_WINDOW_PAUSED_SIGNAL], 0);
363
}
364
365
void yui_window_set_fullscreen(YuiWindow * yui, gboolean f) {
366
GtkAction * action = gtk_action_group_get_action(yui->action_group, "fullscreen");
367
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), f);
368
}
369
370
void yui_window_set_frameskip(YuiWindow * yui, gboolean f) {
371
GtkAction * action = gtk_action_group_get_action(yui->action_group, "frameskip");
372
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), f);
373
}
374
375