Made ChimaraApp class
[projects/chimara/chimara.git] / player / player.c
1 #include <glib-object.h>
2 #include <libchimara/chimara-glk.h>
3 #include <libchimara/chimara-if.h>
4 #include "player.h"
5 #include "error.h"
6 #include "app.h"
7
8 typedef struct _ChimaraPlayerPrivate {
9         int dummy;
10 } ChimaraPlayerPrivate;
11
12 #define CHIMARA_PLAYER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), CHIMARA_TYPE_PLAYER, ChimaraPlayerPrivate))
13 #define CHIMARA_PLAYER_USE_PRIVATE ChimaraPlayerPrivate *priv = CHIMARA_PLAYER_PRIVATE(self)
14
15 G_DEFINE_TYPE(ChimaraPlayer, chimara_player, GTK_TYPE_WINDOW);
16
17 static GObject *
18 load_object(GtkBuilder *builder, const gchar *name)
19 {
20         GObject *retval;
21         if( (retval = gtk_builder_get_object(builder, name)) == NULL) {
22                 error_dialog(NULL, NULL, "Error while getting object '%s'", name);
23                 g_error("Error while getting object '%s'", name);
24         }
25         return retval;
26 }
27
28 static void
29 change_window_title(ChimaraGlk *glk, GParamSpec *pspec, GtkWindow *window)
30 {
31         gchar *program_name, *story_name, *title;
32         g_object_get(glk, "program-name", &program_name, "story-name", &story_name, NULL);
33         if(!program_name) {
34                 gtk_window_set_title(window, "Chimara");
35                 return;
36         }
37         else if(!story_name)
38                 title = g_strdup_printf("%s - Chimara", program_name);
39         else
40                 title = g_strdup_printf("%s - %s - Chimara", program_name, story_name);
41         
42         g_free(program_name);
43         g_free(story_name);
44         gtk_window_set_title(window, title);
45         g_free(title);
46 }
47
48 static void
49 chimara_player_dispose(GObject *object)
50 {
51         ChimaraPlayer *self = CHIMARA_PLAYER(object);
52         if(chimara_glk_get_running(CHIMARA_GLK(self->glk))) {
53                 chimara_glk_stop(CHIMARA_GLK(self->glk));
54                 g_printerr("Stopping...\n");
55                 chimara_glk_wait(CHIMARA_GLK(self->glk));
56                 g_printerr("Done Waiting\n");
57         }
58         
59         /* Chain up */
60         G_OBJECT_CLASS(chimara_player_parent_class)->dispose(object);
61 }
62
63 static void
64 chimara_player_finalize(GObject *object)
65 {
66         g_printerr("Unreffing\n");
67         g_object_unref(CHIMARA_PLAYER(object)->glk);
68         
69         /* Chain up */
70         G_OBJECT_CLASS(chimara_player_parent_class)->finalize(object);
71 }
72
73 static void
74 chimara_player_class_init(ChimaraPlayerClass *klass)
75 {
76         /* Override methods of parent classes */
77         GObjectClass *object_class = G_OBJECT_CLASS(klass);
78         //object_class->set_property = chimara_if_set_property;
79         //object_class->get_property = chimara_if_get_property;
80         object_class->dispose = chimara_player_dispose;
81         object_class->finalize = chimara_player_finalize;
82         
83         /* Signals */
84
85         /* Properties */
86
87         /* Private data */
88         g_type_class_add_private(klass, sizeof(ChimaraPlayerPrivate));
89 }
90
91 static void
92 chimara_player_init(ChimaraPlayer *self)
93 {       
94         GError *error = NULL;
95         
96         GtkBuilder *builder = gtk_builder_new();
97         char *object_ids[] = {
98                 "actiongroup",
99                 "vbox",
100                 NULL
101         };
102         
103         if( !gtk_builder_add_objects_from_file(builder, PACKAGE_DATA_DIR "/chimara.ui", object_ids, &error) ) {
104 #ifdef DEBUG
105                 g_error_free(error);
106                 error = NULL;
107                 if( !gtk_builder_add_objects_from_file(builder, PACKAGE_SRC_DIR "/chimara.ui", object_ids, &error) ) {
108 #endif /* DEBUG */
109                         error_dialog(NULL, error, "Error while building interface: ");  
110                         return;
111 #ifdef DEBUG
112                 }
113 #endif /* DEBUG */
114         }
115         
116         GtkActionGroup *actiongroup = GTK_ACTION_GROUP(load_object(builder, "actiongroup"));
117         
118         /* Set the default value of the "View/Toolbar" menu item upon creation of a
119          new window to the "show-toolbar-default" setting, but bind the setting
120          one-way only - we don't want toolbars to disappear suddenly */
121         GtkToggleAction *toolbar_action = GTK_TOGGLE_ACTION(load_object(builder, "toolbar"));
122         //gtk_toggle_action_set_active(toolbar_action, g_settings_get_boolean(state_settings, "show-toolbar-default"));
123         //g_settings_bind(state_settings, "show-toolbar-default", toolbar_action, "active", G_SETTINGS_BIND_SET);
124                 
125         GtkUIManager *uimanager = gtk_ui_manager_new();
126         if( !gtk_ui_manager_add_ui_from_file(uimanager, PACKAGE_DATA_DIR "/chimara.menus", &error) ) {
127 #ifdef DEBUG
128                 g_error_free(error);
129                 error = NULL;
130                 if( !gtk_ui_manager_add_ui_from_file(uimanager, PACKAGE_SRC_DIR "/chimara.menus", &error) ) {
131 #endif /* DEBUG */
132                         error_dialog(NULL, error, "Error while building interface: ");
133                         return;
134 #ifdef DEBUG
135                 }
136 #endif /* DEBUG */
137         }
138         
139         self->glk = chimara_if_new();
140         g_object_set(self->glk,
141                                  "ignore-errors", TRUE,
142                                  /*"interpreter-number", CHIMARA_IF_ZMACHINE_TANDY_COLOR,*/
143                                  NULL);
144         if( !chimara_glk_set_css_from_file(CHIMARA_GLK(self->glk), PACKAGE_DATA_DIR "/style.css", &error) ) {
145 #ifdef DEBUG
146                 g_error_free(error);
147                 error = NULL;
148                 if( !chimara_glk_set_css_from_file(CHIMARA_GLK(self->glk), PACKAGE_SRC_DIR "/style.css", &error) ) {
149 #endif /* DEBUG */
150                         error_dialog(NULL, error, "Couldn't open CSS file: ");
151                         return;
152 #ifdef DEBUG
153                 }
154 #endif /* DEBUG */
155         }
156         
157         /* DON'T UNCOMMENT THIS your eyes will burn
158          but it is a good test of programmatically altering just one style
159          chimara_glk_set_css_from_string(CHIMARA_GLK(glk),
160          "buffer.normal { font-family: 'Comic Sans MS'; }");*/
161         
162         GtkBox *vbox = GTK_BOX(load_object(builder, "vbox"));                   
163
164         ChimaraApp *theapp = chimara_app_get();
165
166         gtk_ui_manager_insert_action_group(uimanager, actiongroup, 0);
167         gtk_ui_manager_insert_action_group(uimanager, chimara_app_get_action_group(theapp), 1);
168         GtkWidget *menubar = gtk_ui_manager_get_widget(uimanager, "/player_menu");
169         self->toolbar = gtk_ui_manager_get_widget(uimanager, "/player_toolbar");
170         gtk_widget_set_no_show_all(self->toolbar, TRUE);
171         if(gtk_toggle_action_get_active(toolbar_action))
172                 gtk_widget_show(self->toolbar);
173         else
174                 gtk_widget_hide(self->toolbar);
175         
176         /* Connect the accelerators */
177         GtkAccelGroup *accels = gtk_ui_manager_get_accel_group(uimanager);
178         gtk_window_add_accel_group(GTK_WINDOW(self), accels);
179         
180         gtk_box_pack_end(vbox, self->glk, TRUE, TRUE, 0);
181         g_object_ref(self->glk); /* add an extra reference to keep it alive while
182                                                           the Glk program shuts down */
183         gtk_box_pack_start(vbox, menubar, FALSE, FALSE, 0);
184         gtk_box_pack_start(vbox, self->toolbar, FALSE, FALSE, 0);
185         gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(vbox));
186         
187         gtk_builder_connect_signals(builder, self);
188         g_signal_connect(self->glk, "notify::program-name", G_CALLBACK(change_window_title), self);
189         g_signal_connect(self->glk, "notify::story-name", G_CALLBACK(change_window_title), self);
190
191         g_object_unref( G_OBJECT(builder) );
192         g_object_unref( G_OBJECT(uimanager) );
193 }
194
195 /* PUBLIC FUNCTIONS */
196
197 GtkWidget *
198 chimara_player_new(void)
199 {
200     return GTK_WIDGET(g_object_new(CHIMARA_TYPE_PLAYER,
201                 "type", GTK_WINDOW_TOPLEVEL,
202                 NULL));
203 }