00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00025 #include <errno.h>
00026 #include <glib/gstdio.h>
00027 #include <gtk/gtk.h>
00028 #include <stdlib.h>
00029 #include <unistd.h>
00030
00031 #include "application-data.h"
00032 #include "frame-common.h"
00033 #include "frame-private.h"
00034 #include "frame-signals.h"
00035 #include "frame-table.h"
00036 #include "frame-utilities.h"
00037 #include "gedit-spinner.h"
00038 #include "machine.h"
00039 #include "plugins.h"
00040 #include "time-period.h"
00041
00042
00043
00044 void frame_set_id (frame_t *f, GList *list)
00045 {
00046 synema_instance_t *inst = synema_instance ();
00047 f->id = unique_frame_id_generator (list);
00048 gchar *path = g_strdup_printf ("%s/frame_%u", inst->tmp_dir, f->id);
00049
00050 if (g_mkdir_with_parents (path, 0777) != 0) {
00051 g_warning ("frame_set_id: Could not create a tmp directory, the plugin may encounter problems (%s)",
00052 g_strerror (errno));
00053 }
00054 g_free (path);
00055 }
00056
00057
00058
00059 void frame_on_exit (GtkWidget *button, gpointer user_data)
00060 {
00061 frame_t *f = (frame_t *) user_data;
00062
00063 frame_table_remove (f->parent, f);
00064 }
00065
00066
00067
00068 frame_t *frame_new (char *type)
00069 {
00070 gboolean deprecated = FALSE;
00071 frame_t *frame = g_malloc (sizeof (frame_t));
00072 plugin_t *pt = plugin_list_find (type);
00073
00074 *(void **) (&(frame->build_func_list)) = plugin_get_symbol (pt, "build_func_list", TRUE);
00075 if (!frame->build_func_list) {
00076 g_warning ("frame_new: Failed to get mandatory symbol build_func_list");
00077 g_free (frame);
00078 return NULL;
00079 }
00080
00081 *(void **) (&(frame->build_time_periods)) = plugin_get_symbol (pt, "build_time_periods", TRUE);
00082 if (!frame->build_time_periods) {
00083 g_warning ("frame_new: Failed to get mandatory symbol build_time_periods");
00084 g_free (frame);
00085 return NULL;
00086 }
00087
00088 *(void **) (&(frame->is_refreshing_needed)) = plugin_get_symbol (pt, "is_refreshing_needed", TRUE);
00089 if (!frame->is_refreshing_needed) {
00090 g_warning ("frame_new: Failed to get mandatory symbol is_refreshing_needed");
00091 g_free (frame);
00092 return NULL;
00093 }
00094
00095 *(void **) (&(frame->refresh_content)) = plugin_get_symbol (pt, "refresh_content", TRUE);
00096 if (!frame->refresh_content) {
00097 g_warning ("frame_new: Failed to get mandatory symbol refresh_content");
00098 g_free (frame);
00099 return NULL;
00100 }
00101
00102 *(void **) (&(frame->init_private)) = plugin_get_symbol (pt, "init_private", TRUE);
00103 if (!frame->init_private) {
00104 g_warning ("frame_new: Failed to get mandatory symbol init_private");
00105 g_free (frame);
00106 return NULL;
00107 }
00108
00109 *(void **) (&(frame->free_private)) = plugin_get_symbol (pt, "free_private", TRUE);
00110 if (!frame->free_private) {
00111 g_warning ("frame_new: Failed to get mandatory symbol free_private");
00112 g_free (frame);
00113 return NULL;
00114 }
00115
00116 *(void **) (&(frame->display_machine_changed)) = plugin_get_symbol (pt, "display_machine_changed", TRUE);
00117 if (!frame->display_machine_changed) {
00118 g_warning ("frame_new: Failed to get mandatory symbol display_machine_changed");
00119 g_free (frame);
00120 return NULL;
00121 }
00122
00123 *(void **) (&(frame->time_period_changed)) = plugin_get_symbol (pt, "time_period_changed", TRUE);
00124 if (!frame->time_period_changed) {
00125 g_warning ("frame_new: Failed to get mandatory symbol time_period_changed");
00126 g_free (frame);
00127 return NULL;
00128 }
00129
00130 *(void **) (&(frame->frame_size_changed)) = plugin_get_symbol (pt, "frame_size_changed", TRUE);
00131 if (!frame->frame_size_changed) {
00132 g_warning ("frame_new: Failed to get mandatory symbol frame_size_changed");
00133 g_free (frame);
00134 return NULL;
00135 }
00136
00137 *(void **) (&(frame->draw_area)) = plugin_get_symbol (pt, "draw_area", TRUE);
00138 if (!frame->draw_area) {
00139 g_warning ("frame_new: Failed to get mandatory symbol draw_area");
00140 g_free (frame);
00141 return NULL;
00142 }
00143
00144 *(void **) (&(frame->get_display_name)) = plugin_get_symbol (pt, "get_display_name", TRUE);
00145 if (!frame->get_display_name) {
00146 g_warning ("frame_new: Failed to get mandatory symbol get_display_name");
00147 g_free (frame);
00148 return NULL;
00149 }
00150
00151
00152 *(void **) (&(frame->button_press_handler)) = plugin_get_symbol (pt, "button_press_handler", FALSE);
00153 if (!frame->button_press_handler) {
00154 g_warning ("frame_new: Failed to get optional symbol button_press_handler");
00155 deprecated = TRUE;
00156 }
00157
00158 *(void **) (&(frame->button_release_handler)) = plugin_get_symbol (pt, "button_release_handler", FALSE);
00159 if (!frame->button_release_handler) {
00160 g_warning ("frame_new: Failed to get optional symbol button_release_handler");
00161 deprecated = TRUE;
00162 }
00163
00164 *(void **) (&(frame->restore_private)) = plugin_get_symbol (pt, "restore_private", FALSE);
00165 if (!frame->restore_private) {
00166 g_warning ("frame_new: Failed to get optional symbol restore_private");
00167 deprecated = TRUE;
00168 }
00169
00170 *(void **) (&(frame->save_private)) = plugin_get_symbol (pt, "save_private", FALSE);
00171 if (!frame->save_private) {
00172 g_warning ("frame_new: Failed to get optional symbol save_private");
00173 deprecated = TRUE;
00174 }
00175
00176
00177 if (deprecated)
00178 g_warning ("frame_new: plugin %s uses a deprecated API version", type);
00179
00180 frame->type = g_strdup (type);
00181 return frame;
00182 }
00183
00184
00185
00186 void frame_free (frame_t *f)
00187 {
00188 if (f) {
00189 f->compute = FALSE;
00190 g_cond_signal (f->cond);
00191 g_thread_join (f->computing_thread);
00192 g_mutex_free (f->mutex);
00193 g_cond_free (f->cond);
00194 f->free_private (f);
00195 if (f->spinner_stop_src)
00196 g_source_remove (f->spinner_stop_src);
00197 if (f->spinner_start_src)
00198 g_source_remove (f->spinner_start_src);
00199 g_object_unref (f->signal_box);
00200 g_object_unref (f->builder);
00201 g_free (f->type);
00202 g_free (f);
00203 }
00204 }
00205
00206
00207
00208 void frame_free_uninitialised (frame_t *f)
00209 {
00210 if (f) {
00211 g_free (f->type);
00212 g_free (f);
00213 }
00214 }
00215
00216
00217
00218 double frame_timed_refresh_content (frame_t *f, int *call_result)
00219 {
00220 GTimer *chrono = g_timer_new ();
00221
00222 if (call_result != NULL)
00223 *call_result = f->refresh_content (f);
00224 else
00225 f->refresh_content (f);
00226
00227 g_timer_stop (chrono);
00228
00229 double result = g_timer_elapsed (chrono, NULL);
00230
00231 g_timer_destroy (chrono);
00232
00233 return result;
00234 }
00235
00236
00237
00238 void frame_update_size_button (frame_t *f)
00239 {
00240 GtkWidget *button = NULL;
00241 GtkWidget *size_image = NULL;
00242
00243 button = (GtkWidget *) gtk_builder_get_object (f->builder, "size_toggle");
00244
00245 if (f->size == NORMAL)
00246 size_image = gtk_image_new_from_stock ("gtk-zoom-in", GTK_ICON_SIZE_BUTTON);
00247 else if (f->size == LARGE)
00248 size_image = gtk_image_new_from_stock ("gtk-zoom-out", GTK_ICON_SIZE_BUTTON);
00249 else
00250 size_image = gtk_image_new_from_stock ("gtk-leave-fullscreen", GTK_ICON_SIZE_BUTTON);
00251
00252 gtk_button_set_image (GTK_BUTTON (button), size_image);
00253 }
00254
00255
00256
00257 void frame_machine_changed (GtkComboBox *box, gpointer user_data)
00258 {
00259 frame_t *f = NULL;
00260 GtkTreeIter iter;
00261 GtkTreeModel *model;
00262
00263 f = (frame_t *) user_data;
00264
00265 if (gtk_combo_box_get_active_iter (box, &iter)) {
00266 model = gtk_combo_box_get_model (box);
00267 gtk_tree_model_get (model, &iter, 1, &f->display_machine, -1);
00268 }
00269
00270 if (f->last_err == ERROR_MACHINE)
00271 frame_unset_error (f);
00272
00273 f->display_machine_changed (f);
00274 }
00275
00276
00277
00278 void frame_time_period_changed (GtkComboBox *box, gpointer user_data)
00279 {
00280 frame_t *f = NULL;
00281 GtkTreeIter iter;
00282 GtkTreeModel *model;
00283
00284 f = (frame_t *) user_data;
00285
00286 if (gtk_combo_box_get_active_iter (box, &iter)) {
00287 model = gtk_combo_box_get_model (box);
00288 gtk_tree_model_get (model, &iter, 1, &f->display_period.type, 2, &f->display_period.value, -1);
00289 }
00290
00291 if (f->last_err == ERROR_PERIOD)
00292 frame_unset_error (f);
00293
00294 f->time_period_changed (f);
00295 }
00296
00297
00298
00299 gboolean frame_button_event (GtkWidget *area,
00300 GdkEventButton *event,
00301 gpointer user_data)
00302 {
00303 frame_t *frame = user_data;
00304
00305 if (event->type == GDK_BUTTON_PRESS) {
00306 if (frame->button_press_handler)
00307 frame->button_press_handler (frame, event);
00308 else
00309 g_warning ("frame_button_event: No button_press_handler function in frame %u, deprecated plugin (%s) format (0.3.1)", frame->id, frame->type);
00310 } else if (event->type == GDK_BUTTON_RELEASE) {
00311 if (frame->button_release_handler)
00312 frame->button_release_handler (frame, event);
00313 else
00314 g_warning ("frame_button_event: No button_release_handler function in frame %u, deprecated plugin (%s) format (0.3.1)", frame->id, frame->type);
00315 }
00316
00317 return FALSE;
00318 }
00319
00320
00321
00322 gboolean frame_expose_handler (GtkWidget *area,
00323 GdkEventExpose *event,
00324 gpointer user_data)
00325 {
00326 frame_t *f = NULL;
00327 cairo_t *cr = NULL;
00328
00329 f = (frame_t *) user_data;
00330
00331 cr = gdk_cairo_create (area->window);
00332 cairo_rectangle (cr, event->area.x, event->area.y,
00333 event->area.width, event->area.height);
00334 cairo_clip (cr);
00335
00336 f->draw_area (f, cr);
00337
00338 cairo_destroy (cr);
00339
00340 return FALSE;
00341 }
00342
00343
00344
00345 void frame_size_changed_event (GtkWidget *button,
00346 gpointer user_data)
00347 {
00348 frame_t *f = NULL;
00349 GtkWidget *area = NULL;
00350
00351 f = (frame_t *) user_data;
00352
00353 if (f->size == NORMAL)
00354 f->size = LARGE;
00355 else
00356 f->size = NORMAL;
00357
00358 frame_update_size_button (f);
00359
00360 area = (GtkWidget *) gtk_builder_get_object (f->builder, "drawing_area");
00361 gtk_widget_set_size_request (area, frame_get_width (f),
00362 frame_get_height (f));
00363 gtk_widget_queue_resize (frame_get_root_widget (f));
00364
00365 f->frame_size_changed (f);
00366 }
00367
00368
00369
00370 static gboolean frame_spinner_stop (gpointer data)
00371 {
00372 frame_t *f = (frame_t *) data;
00373 g_signal_emit_by_name (f->signal_box, "spinner_stop", data);
00374 return FALSE;
00375 }
00376
00377
00378
00379 static gboolean frame_spinner_start (gpointer data)
00380 {
00381 frame_t *f = (frame_t *) data;
00382 g_signal_emit_by_name (f->signal_box, "spinner_start", data);
00383 return FALSE;
00384 }
00385
00386
00387
00388 gpointer frame_computing_thread (gpointer data)
00389 {
00390 synema_instance_t *inst = synema_instance ();
00391 frame_t *f = (frame_t *) data;
00392 gboolean do_refresh = FALSE;
00393 GTimeVal timeval;
00394
00395 while (f->compute) {
00396 g_mutex_lock (f->mutex);
00397
00398 g_get_current_time (&timeval);
00399 if (inst->settings->refresh_freq == REFRESH_FREQ_AUTO) {
00400
00401
00402
00403
00404
00405
00406
00407 if (f->avg_refresh_timeout <= 0) {
00408
00409 GTimer *elapsed = g_timer_new ();
00410 g_timer_start (elapsed);
00411 if (f->avg_refresh_timeout == 0)
00412 f->avg_refresh_time = 0;
00413
00414
00415 while (!f->is_refreshing_needed (f)) {
00416 g_get_current_time (&timeval);
00417 g_time_val_add (&timeval, 250000);
00418 g_cond_timed_wait (f->cond, f->mutex, &timeval);
00419 }
00420
00421 g_timer_stop (elapsed);
00422 f->avg_refresh_time += g_timer_elapsed (elapsed, NULL);
00423 g_timer_destroy (elapsed);
00424 do_refresh = TRUE;
00425
00426
00427
00428
00429
00430 if (f->avg_refresh_timeout == -(AVG_REFRESH_TIME_NB_PASS - 1)) {
00431 f->avg_refresh_timeout = AUTO_REFRESH_FREQ_TIMEOUT_LEN;
00432 f->avg_refresh_time /= AVG_REFRESH_TIME_NB_PASS;
00433 } else {
00434 f->avg_refresh_timeout--;
00435 }
00436 }
00437
00438 else {
00439 f->avg_refresh_timeout -= f->avg_refresh_time;
00440 if (f->avg_refresh_timeout < 0)
00441 f->avg_refresh_timeout = 0;
00442 g_time_val_add (&timeval, f->avg_refresh_time * G_USEC_PER_SEC);
00443 g_cond_timed_wait (f->cond, f->mutex, &timeval);
00444 do_refresh = f->is_refreshing_needed (f);
00445 }
00446 }
00447
00448 else {
00449 g_time_val_add (&timeval, inst->settings->refresh_freq * 1000);
00450 g_cond_timed_wait (f->cond, f->mutex, &timeval);
00451 do_refresh = f->is_refreshing_needed (f);
00452 }
00453
00454
00455
00456 if ((f->compute) && (do_refresh) && (!f->hidden)) {
00457 f->show_spinner = TRUE;
00458 f->spinner_start_src = gdk_threads_add_idle (frame_spinner_start, data);
00459 do {
00460 f->computing_requested = FALSE;
00461 f->refresh_content (f);
00462 } while (f->computing_requested);
00463 f->show_spinner = FALSE;
00464 f->spinner_stop_src = gdk_threads_add_idle (frame_spinner_stop, data);
00465 }
00466
00467 g_mutex_unlock (f->mutex);
00468 }
00469
00470 return NULL;
00471 }