示例#1
0
文件: rules.c 项目: alga/lines
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);
}
示例#3
0
文件: xchat.c 项目: TingPing/conspire
/*
 * 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;
}
示例#6
0
/* 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;  
}
示例#7
0
文件: sq.c 项目: MrJoe/gtk-gnutella
/**
 * 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;
}
示例#8
0
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;
}
示例#9
0
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;
}
示例#10
0
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();
}
示例#11
0
文件: gsrvtarget.c 项目: Andais/glib
/**
 * 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;
}