/* ------------------------------------ * gap_image_is_alive * ------------------------------------ * TODO: gimp 1.3.x sometimes keeps a copy of closed images * therefore this proceedure may tell only half the truth * * return TRUE if OK (image is still valid) * return FALSE if image is NOT valid */ gboolean gap_image_is_alive(gint32 image_id) { gint32 *images; gint nimages; gint l_idi; gint l_found; if(image_id < 0) { return FALSE; } images = gimp_image_list(&nimages); l_idi = nimages -1; l_found = FALSE; while((l_idi >= 0) && images) { if(image_id == images[l_idi]) { l_found = TRUE; break; } l_idi--; } if(images) g_free(images); if(l_found) { return TRUE; /* OK */ } if(gap_debug) printf("gap_image_is_alive: image_id %d is not VALID\n", (int)image_id); return FALSE ; /* INVALID image id */ } /* end gap_image_is_alive */
/* ---------------------------------------------------- * p_drop_image_cache * ---------------------------------------------------- * drop the image cache. */ static void p_drop_image_cache(void) { gint32 *images; gint nimages; gint l_idi; if(gap_debug) { printf("p_drop_image_cache START pid:%d\n", (int) gap_base_getpid()); } images = gimp_image_list(&nimages); for(l_idi=0; l_idi < nimages; l_idi++) { GimpParasite *l_parasite; l_parasite = gimp_image_parasite_find(images[l_idi], GAP_IMAGE_CACHE_PARASITE); if(gap_debug) { printf("FrameFetcher: CHECK (image_id:%d) name:%s pid:%d\n" , (int)images[l_idi] , gimp_image_get_filename(images[l_idi]) , (int)gap_base_getpid() ); } if(l_parasite) { if(gap_debug) { printf("FrameFetcher: DELETE (image_id:%d) name:%s pid:%d\n" , (int)images[l_idi] , gimp_image_get_filename(images[l_idi]) , (int)gap_base_getpid() ); } /* delete image from the duplicates cache */ gap_image_delete_immediate(images[l_idi]); gimp_parasite_free(l_parasite); } } if(images) { g_free(images); } if(gap_debug) { printf("p_drop_image_cache END pid:%d\n", (int)gap_base_getpid()); } } /* end p_drop_image_cache */
/* ------------------------------------------------- * gap_frame_fetch_delete_list_of_duplicated_images * ------------------------------------------------- * deletes all duplicate imageas that wre created by the specified ffetch_user_id * (if ffetch_user_id -1 is specified delte all duplicated images) */ void gap_frame_fetch_delete_list_of_duplicated_images(gint32 ffetch_user_id) { gint32 *images; gint nimages; gint l_idi; images = gimp_image_list(&nimages); for(l_idi=0; l_idi < nimages; l_idi++) { GimpParasite *l_parasite; l_parasite = gimp_image_parasite_find(images[l_idi], GAP_IMAGE_DUP_CACHE_PARASITE); if(gap_debug) { printf("FrameFetcher: check (image_id:%d) name:%s pid:%d\n" , (int)images[l_idi] , gimp_image_get_filename(images[l_idi]) , (int)gap_base_getpid() ); } if(l_parasite) { gint32 *ffetch_user_id_ptr; ffetch_user_id_ptr = (gint32 *) l_parasite->data; if((*ffetch_user_id_ptr == ffetch_user_id) || (ffetch_user_id < 0)) { if(gap_debug) { printf("FrameFetcher: DELETE duplicate %s (image_id:%d) user_id:%d (%d) name:%s pid:%d\n" , gimp_image_get_filename(images[l_idi]) , (int)images[l_idi] , (int)ffetch_user_id , (int)*ffetch_user_id_ptr , gimp_image_get_filename(images[l_idi]) , (int)gap_base_getpid() ); } /* delete image from the duplicates cache */ gap_image_delete_immediate(images[l_idi]); } gimp_parasite_free(l_parasite); } } if(images) { g_free(images); } } /* end gap_frame_fetch_delete_list_of_duplicated_images */
static void create_selection_tab (GtkWidget *notebook, gint32 image_ID) { GtkSizeGroup *group; GtkWidget *vbox; GtkWidget *vbox2; GtkWidget *hbox; GtkWidget *table; GtkWidget *label; GtkWidget *frame; GtkWidget *toggle; GtkWidget *spinbutton; GtkAdjustment *adj; GtkWidget *button; GtkWidget *font_button; gint32 *image_id_list; gint nimages, j; hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_container_set_border_width (GTK_CONTAINER (hbox), 12); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), hbox, gtk_label_new_with_mnemonic (_("Selection"))); gtk_widget_show (hbox); vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0); gtk_widget_show (vbox2); group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); /* Film height/color */ frame = gimp_frame_new (_("Filmstrip")); gtk_box_pack_start (GTK_BOX (vbox2), frame, FALSE, FALSE, 0); gtk_widget_show (frame); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (frame), vbox); gtk_widget_show (vbox); /* Keep maximum image height */ toggle = gtk_check_button_new_with_mnemonic (_("_Fit height to images")); gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); gtk_widget_show (toggle); g_signal_connect (toggle, "toggled", G_CALLBACK (gimp_toggle_button_update), &filmvals.keep_height); table = gtk_table_new (2, 2, FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 6); gtk_table_set_col_spacings (GTK_TABLE (table), 6); gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); gtk_widget_show (table); /* Film height */ adj = GTK_ADJUSTMENT (gtk_adjustment_new (filmvals.film_height, 10, GIMP_MAX_IMAGE_SIZE, 1, 10, 0)); spinbutton = gtk_spin_button_new (adj, 1, 0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, _("_Height:"), 0.0, 0.5, spinbutton, 1, TRUE); gtk_size_group_add_widget (group, label); g_object_unref (group); g_signal_connect (adj, "value-changed", G_CALLBACK (gimp_int_adjustment_update), &filmvals.film_height); g_object_bind_property (toggle, "active", spinbutton, "sensitive", G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); g_object_bind_property (toggle, "active", /* FIXME: eeeeeek */ g_list_nth_data (gtk_container_get_children (GTK_CONTAINER (table)), 1), "sensitive", G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), filmvals.keep_height); /* Film color */ button = gimp_color_button_new (_("Select Film Color"), COLOR_BUTTON_WIDTH, COLOR_BUTTON_HEIGHT, &filmvals.film_color, GIMP_COLOR_AREA_FLAT); label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, _("Co_lor:"), 0.0, 0.5, button, 1, FALSE); gtk_size_group_add_widget (group, label); g_signal_connect (button, "color-changed", G_CALLBACK (gimp_color_button_get_color), &filmvals.film_color); /* Film numbering: Startindex/Font/color */ frame = gimp_frame_new (_("Numbering")); gtk_box_pack_start (GTK_BOX (vbox2), frame, TRUE, TRUE, 0); gtk_widget_show (frame); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (frame), vbox); gtk_widget_show (vbox); table = gtk_table_new (3, 2, FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 6); gtk_table_set_col_spacings (GTK_TABLE (table), 6); gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); gtk_widget_show (table); /* Startindex */ adj = GTK_ADJUSTMENT (gtk_adjustment_new (filmvals.number_start, 0, GIMP_MAX_IMAGE_SIZE, 1, 10, 0)); spinbutton = gtk_spin_button_new (adj, 1, 0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, _("Start _index:"), 0.0, 0.5, spinbutton, 1, TRUE); gtk_size_group_add_widget (group, label); g_signal_connect (adj, "value-changed", G_CALLBACK (gimp_int_adjustment_update), &filmvals.number_start); /* Fontfamily for numbering */ font_button = gimp_font_select_button_new (NULL, filmvals.number_font); g_signal_connect (font_button, "font-set", G_CALLBACK (film_font_select_callback), &filmvals); label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, _("_Font:"), 0.0, 0.5, font_button, 1, FALSE); gtk_size_group_add_widget (group, label); /* Numbering color */ button = gimp_color_button_new (_("Select Number Color"), COLOR_BUTTON_WIDTH, COLOR_BUTTON_HEIGHT, &filmvals.number_color, GIMP_COLOR_AREA_FLAT); label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, _("Co_lor:"), 0.0, 0.5, button, 1, FALSE); gtk_size_group_add_widget (group, label); g_signal_connect (button, "color-changed", G_CALLBACK (gimp_color_button_get_color), &filmvals.number_color); for (j = 0; j < 2; j++) { toggle = gtk_check_button_new_with_mnemonic (j ? _("At _bottom") : _("At _top")); gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), filmvals.number_pos[j]); gtk_widget_show (toggle); g_signal_connect (toggle, "toggled", G_CALLBACK (gimp_toggle_button_update), &filmvals.number_pos[j]); } /*** The right frame keeps the image selection ***/ frame = gimp_frame_new (_("Image Selection")); gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE); gtk_container_add (GTK_CONTAINER (frame), hbox); /* Get a list of all image names */ image_id_list = gimp_image_list (&nimages); filmint.image_list_all = add_image_list (TRUE, nimages, image_id_list, hbox); /* Get a list of the images used for the film */ filmint.image_list_film = add_image_list (FALSE, 1, &image_ID, hbox); gtk_widget_show (hbox); }
/* ---------------------------------------------------- * p_load_cache_image * ---------------------------------------------------- * load an image from cache or from file (in case image is not already cached) * in case the flag addToCache is TRUE the image will be automatically added * to the cache after read from file operation. */ static gint32 p_load_cache_image(const char* filename, gint32 ffetch_user_id, gboolean addToCache) { gint32 l_image_id; char *l_filename; gint32 *images; gint nimages; gint l_idi; gint l_number_of_cached_images; gint32 l_first_cached_image_id; GimpParasite *l_parasite; if(filename == NULL) { printf("p_load_cache_image: ** ERROR cant load filename == NULL! pid:%d\n", (int)gap_base_getpid()); return -1; } l_image_id = -1; l_first_cached_image_id = -1; l_number_of_cached_images = 0; images = gimp_image_list(&nimages); for(l_idi=0; l_idi < nimages; l_idi++) { l_parasite = gimp_image_parasite_find(images[l_idi], GAP_IMAGE_CACHE_PARASITE); if(l_parasite) { gint32 *mtime_ptr; gint32 *ffetch_id_ptr; gchar *filename_ptr; mtime_ptr = (gint32 *) l_parasite->data; ffetch_id_ptr = (gint32 *)&l_parasite->data[sizeof(gint32)]; filename_ptr = (gchar *)&l_parasite->data[sizeof(gint32) + sizeof(gint32)]; l_number_of_cached_images++; if (l_first_cached_image_id < 0) { l_first_cached_image_id = images[l_idi]; } if(strcmp(filename, filename_ptr) == 0) { gint32 mtimefile; mtimefile = gap_file_get_mtime(filename); if(mtimefile == *mtime_ptr) { /* image found in cache */ l_image_id = images[l_idi]; } else { /* image found in cache, but has changed modification timestamp * (delete from cache and reload) */ if(gap_debug) { printf("FrameFetcher: DELETE because mtime changed : (image_id:%d) ffetchId:%d name:%s mtimefile:%d mtimecache:%d pid:%d\n" , (int)images[l_idi] , (int)*ffetch_id_ptr , gimp_image_get_filename(images[l_idi]) , (int)mtimefile , (int)*mtime_ptr , (int)gap_base_getpid() ); } gap_image_delete_immediate(images[l_idi]); } l_idi = nimages -1; /* force break at next loop iteration */ } gimp_parasite_free(l_parasite); } } if(images) { g_free(images); } if (l_image_id >= 0) { if(gap_debug) { printf("FrameFetcher: p_load_cache_image CACHE-HIT :%s (image_id:%d) pid:%d\n" , filename, (int)l_image_id, (int)gap_base_getpid()); } return(l_image_id); } l_filename = g_strdup(filename); l_image_id = gap_lib_load_image(l_filename); if(gap_debug) { printf("FrameFetcher: loaded image from disk:%s (image_id:%d) pid:%d\n" , l_filename, (int)l_image_id, (int)gap_base_getpid()); } if((l_image_id >= 0) && (addToCache == TRUE)) { guchar *parasite_data; gint32 parasite_size; gint32 *parasite_mtime_ptr; gint32 *parasite_ffetch_id_ptr; gchar *parasite_filename_ptr; gint32 len_filename0; /* filename length including the terminating 0 */ if (l_number_of_cached_images > p_get_ffetch_max_img_cache_elements()) { /* the image cache already has more elements than desired, * drop the 1st cached image */ if(gap_debug) { printf("FrameFetcher: DELETE because cache is full: (image_id:%d) name:%s number_of_cached_images:%d pid:%d\n" , (int)l_first_cached_image_id , gimp_image_get_filename(l_first_cached_image_id) , (int)l_number_of_cached_images , (int)gap_base_getpid() ); } gap_image_delete_immediate(l_first_cached_image_id); } /* build parasite data including mtime and full filename with terminating 0 byte */ len_filename0 = strlen(filename) + 1; parasite_size = sizeof(gint32) + sizeof(gint32) + len_filename0; parasite_data = g_malloc0(parasite_size); parasite_mtime_ptr = (gint32 *)parasite_data; parasite_ffetch_id_ptr = (gint32 *)¶site_data[sizeof(gint32)]; parasite_filename_ptr = (gchar *)¶site_data[sizeof(gint32) + sizeof(gint32)]; *parasite_mtime_ptr = gap_file_get_mtime(filename); *parasite_ffetch_id_ptr = ffetch_user_id; memcpy(parasite_filename_ptr, filename, len_filename0); /* attach a parasite to mark the image as part of the gap image cache */ l_parasite = gimp_parasite_new(GAP_IMAGE_CACHE_PARASITE ,0 /* GIMP_PARASITE_PERSISTENT 0 for non persistent */ ,parasite_size ,parasite_data ); if(l_parasite) { gimp_image_parasite_attach(l_image_id, l_parasite); gimp_parasite_free(l_parasite); } g_free(parasite_data); } g_free(l_filename); return(l_image_id); } /* end p_load_cache_image */
/* ---------------------------------------------------- * gap_frame_fetch_dump_resources * ---------------------------------------------------- * print current resource usage to stdout * this includes information about * - ALL images currently loaded * - all video filehandles with memory cache sizes * */ void gap_frame_fetch_dump_resources() { gint32 *images; gint nimages; gint l_idi; gint l_number_of_cached_images; printf("gap_frame_fetch_dump_resources: START pid:%d\n", (int)gap_base_getpid()); l_number_of_cached_images = 0; images = gimp_image_list(&nimages); for(l_idi=0; l_idi < nimages; l_idi++) { GimpParasite *l_parasite; char *l_filename; char *l_cacheInfoString; gint32 image_id; image_id = images[l_idi]; l_filename = gimp_image_get_filename(image_id); l_parasite = gimp_image_parasite_find(image_id, GAP_IMAGE_CACHE_PARASITE); if(l_parasite) { gint32 *mtime_ptr; gint32 *ffetch_id_ptr; gchar *filename_ptr; mtime_ptr = (gint32 *) l_parasite->data; ffetch_id_ptr = (gint32 *)&l_parasite->data[sizeof(gint32)]; filename_ptr = (gchar *)&l_parasite->data[sizeof(gint32) + sizeof(gint32)]; l_number_of_cached_images++; l_cacheInfoString = g_strdup_printf("Cache member: mtime:%d ffetchId:%d %s" ,*mtime_ptr ,*ffetch_id_ptr ,filename_ptr ); gimp_parasite_free(l_parasite); } else { l_parasite = gimp_image_parasite_find(images[l_idi], GAP_IMAGE_DUP_CACHE_PARASITE); if(l_parasite) { gint32 *ffetch_user_id_ptr; ffetch_user_id_ptr = (gint32 *) l_parasite->data; l_number_of_cached_images++; l_cacheInfoString = g_strdup_printf("Cache member (merged duplicate): ffetchId:%d" ,*ffetch_user_id_ptr ); gimp_parasite_free(l_parasite); } else { l_cacheInfoString = g_strdup_printf("Not cached"); } } printf(" FrameFetcher ImgId:%d (%d x %d) %s %s\n" ,(int)image_id ,(int)gimp_image_width(image_id) ,(int)gimp_image_height(image_id) ,l_filename ,l_cacheInfoString ); g_free(l_cacheInfoString); if(l_filename != NULL) { g_free(l_filename); } l_parasite = NULL; } if(images) { g_free(images); } printf(" Number of images currently loaded in gimp total: %d gap_ffetch_max_img_cache_elements:%d marked as cache member:%d\n" ,(int)nimages ,(int)p_get_ffetch_max_img_cache_elements() ,(int)l_number_of_cached_images ); p_dump_resources_gvahand(); p_dump_process_resource_usage(); } /* end gap_frame_fetch_dump_resources */