int find_path(int y1, int x1, int y2, int x2) { GList *queue = NULL, *node; unsigned int path[SIZE][SIZE]; unsigned int distance[SIZE][SIZE]; int i, j, x, y; for (i = 0; i < SIZE; i++) for (j = 0; j < SIZE; j++) { path[i][j] = i << 16 | j; distance[i][j] = MAXINT; } distance[y1][x1] = 0; queue = g_list_append(NULL, (gpointer)(y1 << 16 | x1)); while (queue) { x = (unsigned)(queue->data) & 0xFFFF; y = (unsigned)(queue->data) >> 16; node = queue; queue = g_list_remove_link(queue, node); g_list_free(node); /* up */ if ( y && distance[y-1][x] > distance[y][x] + 1 && !field[y-1][x]) { distance[y-1][x] = distance[y][x] + 1; path[y-1][x] = y << 16 | x; queue = g_list_append(queue, (gpointer)((y-1) << 16 | x)); } /* down */ if ( y < SIZE - 1 && distance[y+1][x] > distance[y][x] + 1 && !field[y+1][x]) { distance[y+1][x] = distance[y][x] + 1; path[y+1][x] = y << 16 | x; queue = g_list_append(queue, (gpointer)((y+1) << 16 | x)); } /* left */ if ( x && distance[y][x-1] > distance[y][x] + 1 && !field[y][x-1]) { distance[y][x-1] = distance[y][x] + 1; path[y][x-1] = y << 16 | x; queue = g_list_append(queue, (gpointer)(y << 16 | (x-1))); } /* right */ if ( x < SIZE - 1 && distance[y][x+1] > distance[y][x] + 1 && !field[y][x+1]) { distance[y][x+1] = distance[y][x] + 1; path[y][x+1] = y << 16 | x; queue = g_list_append(queue, (gpointer)(y << 16 | (x+1))); } } /* while */ /* if we didn't reach the dest. */ if (distance[y2][x2] == MAXINT) return FALSE; /* Okay, if we found it... */ /* we have a reverse path */ /* put it to a list */ queue = g_list_prepend(queue, (gpointer)(y2 << 16 | x2) ); while( x2 != x1 || y2 != y1 ) { x = path[y2][x2] & 0xFFFF; y = path[y2][x2] >> 16; queue = g_list_prepend(queue, (gpointer)(path[y2][x2])); x2 = x; y2 = y; } /* and now move a ball */ anim_move_ball(queue); return TRUE; }
static void grid_placement ( DeepinWorkspaceOverview* self, MonitorData* md, MetaRectangle area, gboolean closest) { DeepinWorkspaceOverviewPrivate* priv = self->priv; GPtrArray* clones = md->clones; if (!clones || clones->len == 0) return; int window_count = clones->len; int columns = (int)ceil (sqrt (window_count)); int rows = (int)ceil (window_count / (double)columns); // Assign slots int slot_width = area.width / columns; int slot_height = area.height / rows; GList* windows = NULL; for (int i = 0; i < clones->len; i++) { MetaDeepinClonedWidget* clone = g_ptr_array_index(clones, i); TilableWindow* tw = g_new0(TilableWindow, 1); tw->id = clone; MetaWindow* win = meta_deepin_cloned_widget_get_window(clone); meta_window_get_input_rect(win, &tw->rect); windows = g_list_append(windows, tw); } TilableWindow* taken_slots[rows * columns]; memset(taken_slots, 0, sizeof taken_slots); if (closest) { // Assign each window to the closest available slot. // precalculate all slot centers GdkPoint slot_centers[rows * columns]; memset(slot_centers, 0, sizeof slot_centers); for (int x = 0; x < columns; x++) { for (int y = 0; y < rows; y++) { slot_centers[x + y * columns] = (GdkPoint) { area.x + slot_width * x + slot_width / 2, area.y + slot_height * y + slot_height / 2 }; } } GList* tmplist = g_list_copy(windows); while (g_list_length(tmplist) > 0) { GList* link = g_list_nth(tmplist, 0); TilableWindow* window = (TilableWindow*)link->data; MetaRectangle rect = window->rect; int slot_candidate = -1; int slot_candidate_distance = INT_MAX; GdkPoint pos = rect_center (rect); // all slots for (int i = 0; i < columns * rows; i++) { if (i > window_count - 1) break; int dist = squared_distance (pos, slot_centers[i]); if (dist < slot_candidate_distance) { // window is interested in this slot TilableWindow* occupier = taken_slots[i]; if (occupier == window) continue; if (occupier == NULL || dist < squared_distance (rect_center (occupier->rect), slot_centers[i])) { // either nobody lives here, or we're better - takeover the slot if it's our best slot_candidate = i; slot_candidate_distance = dist; } } } if (slot_candidate == -1) continue; if (taken_slots[slot_candidate] != NULL) tmplist = g_list_prepend(tmplist, taken_slots[slot_candidate]); tmplist = g_list_remove_link(tmplist, link); taken_slots[slot_candidate] = window; g_list_free(link); } g_list_free(tmplist); } else { // Assign each window as the origin order. for (int i = 0; i < clones->len; i++) { GList* link = g_list_nth (windows, i); taken_slots[i] = (TilableWindow*)link->data; } } // see how many windows we have on the last row int left_over = (int)window_count - columns * (rows - 1); for (int slot = 0; slot < columns * rows; slot++) { TilableWindow* window = taken_slots[slot]; // some slots might be empty if (window == NULL) continue; MetaRectangle rect = window->rect; // Work out where the slot is MetaRectangle target = { area.x + (slot % columns) * slot_width, area.y + (slot / columns) * slot_height, slot_width, slot_height }; target = rect_adjusted (target, 10, 10, -10, -10); float scale; if (target.width / (double)rect.width < target.height / (double)rect.height) { // Center vertically scale = target.width / (float)rect.width; target.y += (target.height - (int)(rect.height * scale)) / 2; target.height = (int)floorf (rect.height * scale); } else { // Center horizontally scale = target.height / (float)rect.height; target.x += (target.width - (int)(rect.width * scale)) / 2; target.width = (int)floorf (rect.width * scale); } // Don't scale the windows too much if (scale > 1.0) { scale = 1.0f; target = (MetaRectangle) { rect_center (target).x - (int)floorf (rect.width * scale) / 2, rect_center (target).y - (int)floorf (rect.height * scale) / 2, (int)floorf (scale * rect.width), (int)floorf (scale * rect.height) }; } // put the last row in the center, if necessary if (left_over != columns && slot >= columns * (rows - 1)) target.x += (columns - left_over) * slot_width / 2; place_window(self, window->id, target); } g_list_free_full(windows, g_free); }
/* * Update the priority queue of the "interesting sessions" * (sess_list_by_lastact). */ void lastact_update(session *sess) { int newidx; /* * Find the priority (for the order see before). * NOTE: we ignore new_data, because (especially with a lot of windows), * that makes lastact essentially useless and annoying. */ if (sess->type == SESS_DIALOG) { if (sess->nick_said) newidx = LACT_QUERY_HI; else if (sess->msg_said) newidx = LACT_QUERY; /* else if (sess->new_data) newidx = LACT_QUERY; */ else newidx = LACT_NONE; } else { if (sess->nick_said) newidx = LACT_CHAN_HI; else if (sess->msg_said) newidx = LACT_CHAN; /* else if (sess->new_data) newidx = LACT_CHAN_DATA; */ else newidx = LACT_NONE; } /* Check if this update is a no-op */ if (sess->lastact_idx == newidx && ((newidx != LACT_NONE && sess->lastact_elem == sess_list_by_lastact[newidx]) || (newidx == LACT_NONE))) return; /* Remove from the old position (and, if no new position, return */ else if (sess->lastact_idx != LACT_NONE && sess->lastact_elem) { sess_list_by_lastact[sess->lastact_idx] = g_list_remove_link( sess_list_by_lastact[sess->lastact_idx], sess->lastact_elem); if (newidx == LACT_NONE) { sess->lastact_idx = newidx; return; } } /* No previous position, allocate new */ else if (!sess->lastact_elem) sess->lastact_elem = g_list_prepend(sess->lastact_elem, sess); sess->lastact_idx = newidx; sess_list_by_lastact[newidx] = g_list_concat( sess->lastact_elem, sess_list_by_lastact[newidx]); }
static void mex_search_plugin_search (MexSearchPlugin *self, const gchar *search) { GList *l, *list; MexSearchPluginPrivate *priv = self->priv; MexModelManager *manager = mex_model_manager_get_default (); gboolean have_tracker = FALSE; if (!priv->search_model) { /* Create search model */ priv->search_model = mex_aggregate_model_new (); g_object_set (G_OBJECT (priv->search_model), "title", _("Search results"), NULL); } /* Kill the last search */ list = (GList *) mex_aggregate_model_get_models ( MEX_AGGREGATE_MODEL (priv->search_model)); for (l = list; l; l = l->next) mex_model_manager_remove_model (manager, l->data); mex_aggregate_model_clear (MEX_AGGREGATE_MODEL (priv->search_model)); /* Iterate over searchable Grilo sources */ list = grl_plugin_registry_get_sources (grl_plugin_registry_get_default (), FALSE); /* find the local files source and place it first */ for (l = list; l; l = l->next) { GrlMetadataSource *meta_src = l->data; const gchar *name = grl_metadata_source_get_name (meta_src); const gchar *source_id; if (!GRL_IS_METADATA_SOURCE (meta_src)) continue; source_id = grl_media_plugin_get_id (GRL_MEDIA_PLUGIN (meta_src)); if (source_id && g_str_equal (source_id, "grl-tracker")) have_tracker = TRUE; if (name && !strcmp (name, "Local files")) { list = g_list_remove_link (list, l); list = g_list_concat (list, l); break; } } /* prefer tracker over the filesystem plugin by removing it from the list if * tracker is available */ if (have_tracker) { for (l = list; l; l = l->next) { GrlMetadataSource *meta_src = l->data; const gchar *source_id; if (!GRL_IS_METADATA_SOURCE (meta_src)) continue; source_id = grl_media_plugin_get_id (GRL_MEDIA_PLUGIN (meta_src)); if (source_id && g_str_equal (source_id, "grl-filesystem")) { list = g_list_delete_link (list, l); break; } } } for (l = list; l; l = l->next) { const gchar *source_id; GrlSupportedOps supported; GrlMetadataSource *meta_src = l->data; if (!GRL_IS_METADATA_SOURCE (meta_src)) continue; /* only search upnp and tracker sources */ source_id = grl_media_plugin_get_id (GRL_MEDIA_PLUGIN (meta_src)); supported = grl_metadata_source_supported_operations (meta_src); if ((supported & GRL_OP_SEARCH) || (supported & GRL_OP_QUERY)) { MexFeed *feed; GController *controller; if (g_str_equal (source_id, "grl-tracker")) feed = mex_grilo_tracker_feed_new (GRL_MEDIA_SOURCE (meta_src), NULL, NULL, NULL, NULL); else feed = mex_grilo_feed_new (GRL_MEDIA_SOURCE (meta_src), NULL, NULL, NULL); mex_model_set_sort_func (MEX_MODEL (feed), mex_model_sort_time_cb, GINT_TO_POINTER (TRUE)); g_object_set (G_OBJECT (feed), "category", "search-results", "placeholder-text", _("No videos found"), NULL); mex_model_manager_add_model (manager, MEX_MODEL (feed)); controller = mex_model_get_controller (MEX_MODEL (feed)); /* Attach to the changed signal so that we can alter the * mime-type of content if necessary. */ g_signal_connect (controller, "changed", G_CALLBACK (mex_search_plugin_model_changed_cb), feed); mex_aggregate_model_add_model ( MEX_AGGREGATE_MODEL (priv->search_model), MEX_MODEL (feed)); /* FIXME: Arbitrary 50 item limit... */ mex_grilo_feed_search (MEX_GRILO_FEED (feed), search, 0, 50); g_object_unref (G_OBJECT (feed)); } } g_list_free (list); }
/** log_score * * Inputs: * 'progname' - the program to log a score for * 'level' - the freeform level identifier * 'username' - the username that this score is logged under * 'score' - the game score * 'ordering' - whether lower scores are better. * * Outputs: * 'retval' - Whether the score got onto the highscore list * * Description: * Loads all the existing scores into the 'scores' * list. Goes through and finds out whether there's a * place for the new score on the high-score list, and * if so, inserts it. Writes out the new high-score list. */ static gint log_score(const gchar* progname, const gchar* level, gchar* username, gfloat score, gboolean ordering) { FILE* infile; FILE* outfile; gchar buf[512], *buf2; GList* scores = NULL, *anode; gchar* game_score_file; gfloat ascore; struct ascore_t* anitem, *curscore; int i; gint retval = 1; gint pos; game_score_file = mate_get_score_file_name(progname, level); infile = g_fopen(game_score_file, "r"); if (infile) { /* make sure we read values from files in a consistent manner */ mate_i18n_push_c_numeric_locale(); while (fgets(buf, sizeof(buf), infile)) { long ltime; i = strlen (buf) - 1; /* Chomp */ while (g_ascii_isspace (buf[i])) buf[i--] = '\0'; { char *tokp; if((buf2 = strtok_r (buf, " ", &tokp)) == NULL) break; ascore = atof (buf2); if((buf2 = strtok_r (NULL, " ", &tokp)) == NULL) break; ltime = atoi (buf2); if((buf2 = strtok_r (NULL, "\n", &tokp)) == NULL) break; } anitem = g_new(struct ascore_t, 1); anitem->score = ascore; anitem->username = g_strdup(buf2); anitem->scoretime = (time_t) ltime; scores = g_list_append(scores, (gpointer) anitem); } mate_i18n_pop_c_numeric_locale(); fclose(infile); } anitem = g_new(struct ascore_t, 1); anitem->score = score; anitem->username = g_strdup(username); anitem->scoretime = time(NULL); for (pos = 0, anode = scores; pos < NSCORES && anode; pos++, anode = anode->next) { curscore = anode->data; if (ordering) { if (curscore->score < anitem->score) { break; } } else { if (curscore->score > anitem->score) { break; } } } if (pos < NSCORES) { scores = g_list_insert(scores, anitem, pos); if ((anode = g_list_nth(scores, NSCORES))) { free_ascore(anode->data); scores = g_list_remove_link(scores, g_list_nth(scores, NSCORES)); } retval = pos + 1; } else { retval = 0; } /* we dont create the file; it must already exist */ outfile = g_fopen(game_score_file, "r+"); #ifndef G_OS_WIN32 ftruncate(fileno(outfile), 0); #else _chsize(fileno(outfile), 0); #endif if (outfile) { mate_i18n_push_c_numeric_locale(); g_list_foreach(scores, (GFunc) print_ascore, outfile); mate_i18n_pop_c_numeric_locale(); fclose(outfile); } else { perror(game_score_file); } g_free(game_score_file); g_list_foreach(scores, (GFunc) free_ascore, NULL); g_list_free(scores); return retval; }
/* load a map file or get it from the cache */ static struct pixmap_info *load_image_mtime(char *name,time_t *mtime /*GdkWindow *win*/) { GList *cached; struct cache_entry ce_search; struct cache_entry *ce; struct stat st; char filename[512]; #ifdef USE_IMLIB GdkPixmap *p; GdkImlibImage *im; #else struct pixmap_info *p; #endif cache_count++; ce_search.name=name; p=NULL; cached=g_list_find_custom(cache_list, &ce_search,find_cache); if (cached) { ce=(struct cache_entry *)cached->data; if (ce) { ce->count=cache_count; if (mtime) *mtime=ce->mtime; return ce->p; } } if (g_list_length(cache_list)>=MAX_CACHE) { GList *rem; cache_list=g_list_sort(cache_list,compare_cache); ce=(struct cache_entry *)g_list_nth_data(cache_list,0); if (ce->p) #ifdef USE_IMLIB gdk_imlib_free_pixmap(ce->p); #else free_pinfo(ce->p); #endif /* printf("entferne %s\n",ce->name); */ g_free(ce->name); g_free(ce); rem=g_list_first(cache_list); cache_list=g_list_remove_link(cache_list,rem); g_list_free(rem); } snprintf(filename,sizeof(filename),"%s.str", name); read_str_file(filename,name); snprintf(filename,sizeof(filename),"%s.png", name); #ifndef USE_IMLIB p=load_gfxfile(filename); if (!p) { if (!stat(filename,&st)) { if (mtime) *mtime=st.st_mtime; return NULL; } snprintf(filename,sizeof(filename),"%s.jpg", name); p=load_gfxfile(filename); } #endif #ifdef USE_IMLIB im=gdk_imlib_load_image(filename); if (im) break; snprintf(filename,sizeof(filename),"%s/%s.bmp",kartenpfad[i], name); im=gdk_imlib_load_image(filename); if (im) break; #endif #ifdef USE_IMLIB if (!im) return NULL; w=im->rgb_width; h=im->rgb_height; if (!gdk_imlib_render(im,w,h)) { gdk_imlib_destroy_image(im); return NULL; } p=gdk_imlib_move_image(im); gdk_imlib_destroy_image(im); #endif if (p) { struct stat st; ce=g_malloc(sizeof(struct cache_entry)); ce->p=p; ce->name=g_strdup(name); ce->count=cache_count; cache_list=g_list_append(cache_list,ce); stat(filename,&st); ce->mtime=st.st_mtime; if (mtime) *mtime=ce->mtime; } else { if (!stat(filename,&st)) { if (mtime) *mtime=st.st_mtime; return NULL; } } return p; }
/** * Decides if the queue can send a message. Currently use simple fixed * time base heuristics. May add bursty control later... */ void sq_process(squeue_t *sq, time_t now) { time_delta_t spacing = GNET_PROPERTY(search_queue_spacing); GList *item; smsg_t *sb; struct gnutella_node *n; bool sent; g_assert(sq->node == NULL || sq->node->outq != NULL); retry: /* * We don't need to do anything if either: * * 1. The queue is empty. * 2. We sent our last search less than "search_queue_spacing" seconds ago. * 3. We never got a packet from that node. * 4. The node activated hops-flow to shut all queries * 5. We activated flow-control on the node locally. * * --RAM, 01/05/2002 */ if (sq->count == 0) return; if (delta_time(now, sq->last_sent) < spacing) return; n = sq->node; /* Will be NULL for the global SQ */ if (n != NULL) { if (n->received == 0) /* RX = 0, wait for handshaking ping */ return; if (!node_query_hops_ok(n, 0)) /* Cannot send hops=0 query */ return; if (!NODE_IS_WRITABLE(n)) return; if (NODE_IN_TX_FLOW_CONTROL(n)) /* Don't add to the mqueue yet */ return; } else { /* * Processing the global SQ. */ if (settings_is_leaf()) return; if (3*UNSIGNED(node_keep_missing()) > 2*GNET_PROPERTY(up_connections)) return; /* Not enough nodes for querying */ } /* * Queue is managed as a LIFO: we extract the first message, i.e. the last * one enqueued, and pass it along to the node's message queue. */ g_assert(sq->searches); item = g_list_first(sq->searches); sb = item->data; g_assert(sq->count > 0); sq->count--; sent = TRUE; /* Assume we're going to send/initiate it */ if (n == NULL) { g_assert(sb->qhv != NULL); /* Enqueued via sq_global_putq() */ if (GNET_PROPERTY(sq_debug) > 2) g_debug("sq GLOBAL, queuing \"%s\" (%u left, %d sent)", gnutella_msg_search_get_text(pmsg_start(sb->mb)), sq->count, sq->n_sent); dq_launch_local(sb->shandle, sb->mb, sb->qhv); } else if (search_query_allowed(sb->shandle)) { /* * Must log before sending, in case the queue discards the message * buffer immediately. */ g_assert(sb->qhv == NULL); /* Enqueued via sq_putq() */ if (GNET_PROPERTY(sq_debug) > 2) g_debug("sq for node %s, queuing \"%s\" (%u left, %d sent)", node_addr(n), gnutella_msg_search_get_text(pmsg_start(sb->mb)), sq->count, sq->n_sent); /* * If we're a leaf node, we're doing a leaf-guided dynamic query. * In order to be able to report hits we get to the UPs to whom * we sent our searches, we need to be notified of all the physical * queries that go out. */ if (settings_is_leaf()) smsg_mutate(sb, n); mq_tcp_putq(n->outq, sb->mb, NULL); } else { if (GNET_PROPERTY(sq_debug) > 4) g_debug("sq for node %s, ignored \"%s\" (%u left, %d sent)", node_addr(n), gnutella_msg_search_get_text(pmsg_start(sb->mb)), sq->count, sq->n_sent); pmsg_free(sb->mb); if (sb->qhv) qhvec_free(sb->qhv); sent = FALSE; } if (sent) { sq->n_sent++; sq->last_sent = now; } sqh_remove(sq, sb->shandle); smsg_free(sb); sq->searches = g_list_remove_link(sq->searches, item); g_list_free_1(item); /* * If we ignored the query, retry with the next in the queue. * We don't use a do/while() loop to avoid identing the whole body. */ if (!sent) goto retry; }
static gboolean start_next (RBTrackTransferBatch *batch) { char *media_type = NULL; char *extension = NULL; if (batch->priv->cancelled == TRUE) { return FALSE; } if (batch->priv->entries == NULL) { /* guess we must be done.. */ g_signal_emit (batch, signals[COMPLETE], 0); return FALSE; } batch->priv->current_fraction = 0.0; batch->priv->current_encoder = rb_encoder_new (); g_signal_connect_object (batch->priv->current_encoder, "progress", G_CALLBACK (encoder_progress_cb), batch, 0); g_signal_connect_object (batch->priv->current_encoder, "overwrite", G_CALLBACK (encoder_overwrite_cb), batch, 0); g_signal_connect_object (batch->priv->current_encoder, "completed", G_CALLBACK (encoder_completed_cb), batch, 0); rb_debug ("%d entries remain in the batch", g_list_length (batch->priv->entries)); while ((batch->priv->entries != NULL) && (batch->priv->cancelled == FALSE)) { RhythmDBEntry *entry; guint64 filesize; gulong duration; double fraction; GList *n; n = batch->priv->entries; batch->priv->entries = g_list_remove_link (batch->priv->entries, n); entry = (RhythmDBEntry *)n->data; g_list_free_1 (n); rb_debug ("attempting to transfer %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); /* calculate the fraction of the transfer that this entry represents */ filesize = rhythmdb_entry_get_uint64 (entry, RHYTHMDB_PROP_FILE_SIZE); duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION); if (batch->priv->total_duration > 0) { g_assert (duration > 0); /* otherwise total_duration would be 0 */ fraction = ((double)duration) / (double) batch->priv->total_duration; } else if (batch->priv->total_size > 0) { g_assert (filesize > 0); /* otherwise total_size would be 0 */ fraction = ((double)filesize) / (double) batch->priv->total_size; } else { int count = g_list_length (batch->priv->entries) + g_list_length (batch->priv->done_entries) + 1; fraction = 1.0 / ((double)count); } g_free (media_type); g_free (extension); media_type = NULL; extension = NULL; if (rb_encoder_get_media_type (batch->priv->current_encoder, entry, batch->priv->media_types, &media_type, &extension) == FALSE) { rb_debug ("skipping entry %s, can't find a destination format", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); rhythmdb_entry_unref (entry); batch->priv->total_fraction += fraction; continue; } g_free (batch->priv->current_dest_uri); batch->priv->current_dest_uri = NULL; g_signal_emit (batch, signals[GET_DEST_URI], 0, entry, media_type, extension, &batch->priv->current_dest_uri); if (batch->priv->current_dest_uri == NULL) { rb_debug ("unable to build destination URI for %s, skipping", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); rhythmdb_entry_unref (entry); batch->priv->total_fraction += fraction; continue; } batch->priv->current = entry; batch->priv->current_entry_fraction = fraction; break; } if (batch->priv->current == NULL) { g_object_unref (batch->priv->current_encoder); batch->priv->current_encoder = NULL; } else { g_signal_emit (batch, signals[TRACK_STARTED], 0, batch->priv->current, batch->priv->current_dest_uri); rb_encoder_encode (batch->priv->current_encoder, batch->priv->current, batch->priv->current_dest_uri, media_type); } g_free (media_type); g_free (extension); return TRUE; }
void load_thumbnails(ThumbnailTask* task) { GList* l; GdkPixbuf* normal_pix = NULL; GdkPixbuf* large_pix = NULL; const char* normal_path = task->normal_path; const char* large_path = task->large_path; if( IS_CANCELLED(task) ) goto _out; DEBUG("loading: %s, %s", task->fi->path->name, normal_path); if(task->flags & LOAD_NORMAL) { normal_pix = gdk_pixbuf_new_from_file(normal_path, NULL); if(!normal_pix || is_thumbnail_outdated(normal_pix, normal_path, task->fi->mtime)) { /* normal_pix is freed in is_thumbnail_outdated() if it's out of date. */ /* generate normal size thumbnail */ task->flags |= GENERATE_NORMAL; normal_pix = NULL; /* DEBUG("need to generate normal thumbnail"); */ } else DEBUG("normal thumbnail loaded: %p", normal_pix); } if( IS_CANCELLED(task) ) goto _out; if(task->flags & LOAD_LARGE) { large_pix = gdk_pixbuf_new_from_file(large_path, NULL); if(!large_pix || is_thumbnail_outdated(large_pix, large_path, task->fi->mtime)) { /* large_pix is freed in is_thumbnail_outdated() if it's out of date. */ /* generate large size thumbnail */ task->flags |= GENERATE_LARGE; large_pix = NULL; } } if( IS_CANCELLED(task) ) goto _out; if(task->flags & (GENERATE_NORMAL|GENERATE_LARGE)) /* need to re-generate some thumbnails */ { GList* generate_reqs = NULL, *l; ThumbnailTask* generate_task; #if 0 /* all requested thumbnails need to be re-generated. */ if( ((task->flags & LOAD_NORMAL|LOAD_LARGE) << 2) == (task->flags & (GENERATE_NORMAL|GENERATE_LARGE)) ) { task->uri = g_strdup(task->uri); task->normal_path = g_strdup(normal_path); task->large_path = g_strdup(large_path); task->flags |= ALLOC_STRINGS; /* push the whole task into generator queue */ queue_generate(task); return; } #endif /* remove all requests which requires re-generating thumbnails from task and gather them in a list */ for(l=task->requests; l; ) { FmThumbnailRequest* req = (FmThumbnailRequest*)l->data; GList* next = l->next; if(req->size <= 128) /* need normal thumbnail */ { if(task->flags & GENERATE_NORMAL) { task->requests = g_list_remove_link(task->requests, l); generate_reqs = g_list_concat(generate_reqs, l); } } else /* need large thumbnail */ { if(task->flags & GENERATE_LARGE) { task->requests = g_list_remove_link(task->requests, l); generate_reqs = g_list_concat(generate_reqs, l); } } l = next; } /* this list contains requests requiring regeration of thumbnails */ if(generate_reqs) { generate_task = g_slice_new0(ThumbnailTask); generate_task->flags = task->flags | ALLOC_STRINGS; generate_task->fi = fm_file_info_ref(task->fi); generate_task->requests = generate_reqs; generate_task->uri = g_strdup(task->uri); generate_task->normal_path = g_strdup(task->normal_path); generate_task->large_path = g_strdup(task->large_path); DEBUG("queue regenerate for :%s", task->fi->path->name); /* queue the re-generation task */ queue_generate(generate_task); } } _out: G_LOCK(queue); /* thumbnails which don't require re-generation should all be loaded at this point. */ if( IS_CANCELLED(task) || !task->requests ) thumbnail_task_free(task); else thumbnail_task_finish(task, normal_pix, large_pix); cur_loading = NULL; /* task is freed in thumbnail_task_finish() */ G_UNLOCK(queue); if(normal_pix) g_object_unref(normal_pix); if(large_pix) g_object_unref(large_pix); return; }
static void dt_dev_change_image(dt_develop_t *dev, const uint32_t imgid) { // stop crazy users from sleeping on key-repeat spacebar: if(dev->image_loading) return; // get last active plugin, make sure focus out is called: gchar *active_plugin = dt_conf_get_string("plugins/darkroom/active"); dt_iop_request_focus(NULL); // store last active group dt_conf_set_int("plugins/darkroom/groups", dt_dev_modulegroups_get(dev)); // store last active plugin: if(darktable.develop->gui_module) dt_conf_set_string("plugins/darkroom/active", darktable.develop->gui_module->op); else dt_conf_set_string("plugins/darkroom/active", ""); g_assert(dev->gui_attached); // commit image ops to db dt_dev_write_history(dev); // be sure light table will update the thumbnail // TODO: only if image changed! // if() { dt_mipmap_cache_remove(darktable.mipmap_cache, dev->image_storage.id); dt_image_synch_xmp(dev->image_storage.id); } select_this_image(imgid); while(dev->history) { // clear history of old image free(((dt_dev_history_item_t *)dev->history->data)->params); free( (dt_dev_history_item_t *)dev->history->data); dev->history = g_list_delete_link(dev->history, dev->history); } // get new image: dt_dev_reload_image(dev, imgid); // make sure no signals propagate here: darktable.gui->reset = 1; GList *modules = g_list_last(dev->iop); int nb_iop = g_list_length(dev->iop); dt_dev_pixelpipe_cleanup_nodes(dev->pipe); dt_dev_pixelpipe_cleanup_nodes(dev->preview_pipe); for (int i=nb_iop-1; i>0; i--) { dt_iop_module_t *module = (dt_iop_module_t *)(g_list_nth_data(dev->iop,i)); if (module->multi_priority == 0) //if the module is the "base" instance, we keep it { dt_iop_reload_defaults(module); dt_iop_gui_update(module); } else //else we delete it and remove it from the panel { if (!dt_iop_is_hidden(module)) { gtk_container_remove (GTK_CONTAINER(dt_ui_get_container(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER)),module->expander); dt_iop_gui_cleanup_module(module); } //we remove the module from the list dev->iop = g_list_remove_link(dev->iop,g_list_nth(dev->iop,i)); //we cleanup the module dt_accel_disconnect_list(module->accel_closures); dt_accel_cleanup_locals_iop(module); module->accel_closures = NULL; dt_iop_cleanup_module(module); free(module); } } dt_dev_pixelpipe_create_nodes(dev->pipe, dev); dt_dev_pixelpipe_create_nodes(dev->preview_pipe, dev); dt_dev_read_history(dev); //we have to init all module instances other than "base" instance modules = dev->iop; while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); if(module->multi_priority > 0) { if (!dt_iop_is_hidden(module)) { module->gui_init(module); dt_iop_reload_defaults(module); //we search the base iop corresponding GList *mods = g_list_first(dev->iop); dt_iop_module_t *base = NULL; int pos_module = 0; int pos_base = 0; int pos = 0; while (mods) { dt_iop_module_t *mod = (dt_iop_module_t *)(mods->data); if (mod->multi_priority == 0 && mod->instance == module->instance) { base = mod; pos_base = pos; } else if (mod == module) pos_module = pos; mods = g_list_next(mods); pos++; } if (!base) continue; /* add module to right panel */ GtkWidget *expander = dt_iop_gui_get_expander(module); dt_ui_container_add_widget(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER, expander); GValue gv = { 0, { { 0 } } }; g_value_init(&gv,G_TYPE_INT); gtk_container_child_get_property(GTK_CONTAINER(dt_ui_get_container(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER)),base->expander,"position",&gv); gtk_box_reorder_child (dt_ui_get_container(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER),expander,g_value_get_int(&gv)+pos_base-pos_module); dt_iop_gui_set_expanded(module, TRUE); dt_iop_gui_update_blending(module); } /* setup key accelerators */ module->accel_closures = NULL; if(module->connect_key_accels) module->connect_key_accels(module); dt_iop_connect_common_accels(module); //we update show params for multi-instances for each other instances dt_dev_modules_update_multishow(module->dev); } modules = g_list_next(modules); } dt_dev_pop_history_items(dev, dev->history_end); if(active_plugin) { modules = dev->iop; while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); if(!strcmp(module->op, active_plugin)) dt_iop_request_focus(module); modules = g_list_next(modules); } g_free(active_plugin); } /* last set the group to update visibility of iop modules for new pipe */ dt_dev_modulegroups_set(dev,dt_conf_get_int("plugins/darkroom/groups")); // make signals work again, but only after focus event, // to avoid crop/rotate for example to add another history item. darktable.gui->reset = 0; // Signal develop initialize dt_control_signal_raise(darktable.signals, DT_SIGNAL_DEVELOP_IMAGE_CHANGED); // prefetch next few from first selected image on. dt_view_filmstrip_prefetch(); }
/** * g_srv_target_list_sort: * @targets: a #GList of #GSrvTarget * * Sorts @targets in place according to the algorithm in RFC 2782. * * Return value: the head of the sorted list. * * Since: 2.22 */ GList * g_srv_target_list_sort (GList *targets) { gint sum, num, val, priority, weight; GList *t, *out, *tail; GSrvTarget *target; if (!targets) return NULL; if (!targets->next) { target = targets->data; if (!strcmp (target->hostname, ".")) { /* 'A Target of "." means that the service is decidedly not * available at this domain.' */ g_srv_target_free (target); g_list_free (targets); return NULL; } } /* Sort input list by priority, and put the 0-weight targets first * in each priority group. Initialize output list to %NULL. */ targets = g_list_sort (targets, compare_target); out = tail = NULL; /* For each group of targets with the same priority, remove them * from @targets and append them to @out in a valid order. */ while (targets) { priority = ((GSrvTarget *)targets->data)->priority; /* Count the number of targets at this priority level, and * compute the sum of their weights. */ sum = num = 0; for (t = targets; t; t = t->next) { target = (GSrvTarget *)t->data; if (target->priority != priority) break; sum += target->weight; num++; } /* While there are still targets at this priority level... */ while (num) { /* Randomly select from the targets at this priority level, * giving precedence to the ones with higher weight, * according to the rules from RFC 2782. */ val = g_random_int_range (0, sum + 1); for (t = targets; ; t = t->next) { weight = ((GSrvTarget *)t->data)->weight; if (weight >= val) break; val -= weight; } targets = g_list_remove_link (targets, t); if (!out) out = t; else tail->next = t; tail = t; sum -= weight; num--; } } return out; }