Exemple #1
0
void host_freeAllApplications(Host* host) {
	MAGIC_ASSERT(host);
	while(!g_queue_is_empty(host->applications)) {
		process_free(g_queue_pop_head(host->applications));
	}
}
gint
xmms_xform_this_read (xmms_xform_t *xform, gpointer buf, gint siz,
                      xmms_error_t *err)
{
	gint read = 0;
	gint nexths;

	if (xform->error) {
		xmms_error_set (err, XMMS_ERROR_GENERIC, "Read on errored xform");
		return -1;
	}

	/* update hotspots */
	nexths = xmms_xform_hotspots_update (xform);
	if (nexths >= 0) {
		siz = MIN (siz, nexths);
	}

	if (xform->buffered) {
		read = MIN (siz, xform->buffered);
		memcpy (buf, xform->buffer, read);
		xform->buffered -= read;

		/* buffer edited, update hotspot positions */
		g_queue_foreach (xform->hotspots, &xmms_xform_hotspot_callback, &read);

		if (xform->buffered) {
			/* unless we are _peek:ing often
			   this should be fine */
			memmove (xform->buffer, &xform->buffer[read], xform->buffered);
		}
	}

	if (xform->eos) {
		return read;
	}

	while (read < siz) {
		gint res;

		res = xmms_xform_plugin_read (xform->plugin, xform, buf + read, siz - read, err);
		if (xform->metadata_collected && xform->metadata_changed)
			xmms_xform_metadata_update (xform);

		if (res < -1) {
			XMMS_DBG ("Read method of %s returned bad value (%d) - BUG IN PLUGIN", xmms_xform_shortname (xform), res);
			res = -1;
		}

		if (res == 0) {
			xform->eos = TRUE;
			break;
		} else if (res == -1) {
			xform->error = TRUE;
			return -1;
		} else {
			if (read == 0)
				xmms_xform_hotspots_update (xform);

			if (!g_queue_is_empty (xform->hotspots)) {
				if (xform->buffered + res > xform->buffersize) {
					xform->buffersize = MAX (xform->buffersize * 2,
					                         xform->buffersize + res);
					xform->buffer = g_realloc (xform->buffer,
					                           xform->buffersize);
				}

				g_memmove (xform->buffer + xform->buffered, buf + read, res);
				xform->buffered += res;
				break;
			}
			read += res;
		}
	}

	return read;
}
Exemple #3
0
static void gfire_server_query_read(gpointer p_data, gint p_fd, PurpleInputCondition p_condition)
{
	static unsigned char buffer[65535];

	gfire_server_query *query = (gfire_server_query*)p_data;

	// Take the time now
	GTimeVal gtv;
	g_get_current_time(&gtv);

	struct sockaddr_in addr;
	guint addr_len = sizeof(addr);
	guint len = recvfrom(p_fd, buffer, 65534, 0, (struct sockaddr*)&addr, &addr_len);

	if(len <= 0)
		return;
	buffer[len] = 0;

	// Get the responding server
	GList *cur = query->cur_servers;
	gfire_game_query_server *server = NULL;
	while(cur)
	{
		gfire_game_query_server *scur = cur->data;
		if(scur->server->ip == g_ntohl(addr.sin_addr.s_addr) && scur->server->query_port == g_ntohs(addr.sin_port))
		{
			server = scur;
			break;
		}
		cur = g_list_next(cur);
	}

	if(!server)
	{
		purple_debug_warning("gfire", "Server Query: Got packet from unknown server\n");
		return;
	}

	// Let the driver do its work
	if(query->driver->parse(server->server, (gtv.tv_sec * 1000) + (gtv.tv_usec / 1000) - server->timeout,
							query->full_query, buffer, len))
	{
		query->driver->query(server->server, query->full_query, p_fd);
		// Reset timeout
		server->timeout = (gtv.tv_sec * 1000) + (gtv.tv_usec / 1000);
	}
	else
	{
		// Server is done
		query->callback(server->server, server->p_data, query->callback_data);
		query->cur_servers = g_list_delete_link(query->cur_servers, cur);
		g_free(server);

		// Fill the list with new ones
		while(!g_queue_is_empty(query->servers) && g_list_length(query->cur_servers) != GFSQ_MAX_QUERIES)
		{
			server = g_queue_pop_tail(query->servers);
			query->cur_servers = g_list_append(query->cur_servers, server);
			query->driver->query(gfire_game_server_apply_query_port(query, server->server), query->full_query, p_fd);

			server->timeout = (gtv.tv_sec * 1000) + (gtv.tv_usec / 1000);
		}
	}
}
Exemple #4
0
static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
{
	struct _GAttrib *attrib = data;
	struct command *cmd = NULL;
	GSList *l;
	uint8_t buf[512], status;
	gsize len;
	GIOStatus iostat;
	gboolean qempty;

	if (attrib->timeout_watch > 0) {
		g_source_remove(attrib->timeout_watch);
		attrib->timeout_watch = 0;
	}

	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
		attrib->read_watch = 0;
		return FALSE;
	}

	memset(buf, 0, sizeof(buf));

	iostat = g_io_channel_read_chars(io, (gchar *) buf, sizeof(buf),
								&len, NULL);
	if (iostat != G_IO_STATUS_NORMAL) {
		status = ATT_ECODE_IO;
		goto done;
	}

	for (l = attrib->events; l; l = l->next) {
		struct event *evt = l->data;

		if (evt->expected == buf[0] ||
				evt->expected == GATTRIB_ALL_EVENTS ||
				(is_response(buf[0]) == FALSE &&
						evt->expected == GATTRIB_ALL_REQS))
			evt->func(buf, len, evt->user_data);
	}

	if (is_response(buf[0]) == FALSE)
		return TRUE;

	cmd = g_queue_pop_head(attrib->queue);
	if (cmd == NULL) {
		/* Keep the watch if we have events to report */
		return attrib->events != NULL;
	}

	if (buf[0] == ATT_OP_ERROR) {
		status = buf[4];
		goto done;
	}

	if (cmd->expected != buf[0]) {
		status = ATT_ECODE_IO;
		goto done;
	}

	status = 0;

done:
	qempty = attrib->queue == NULL || g_queue_is_empty(attrib->queue);

	if (cmd) {
		if (cmd->func)
			cmd->func(status, buf, len, cmd->user_data);

		command_destroy(cmd);
	}

	if (!qempty)
		wake_up_sender(attrib);

	return TRUE;
}
static GstFlowReturn
gst_decklink_audio_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
{
  GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc);
  GstFlowReturn flow_ret = GST_FLOW_OK;
  const guint8 *data;
  glong sample_count;
  gsize data_size;
  CapturePacket *p;
  AudioPacket *ap;
  GstClockTime timestamp, duration;
  GstClockTime start_time, end_time;
  guint64 start_offset, end_offset;
  gboolean discont = FALSE;

retry:
  g_mutex_lock (&self->lock);
  while (g_queue_is_empty (&self->current_packets) && !self->flushing) {
    g_cond_wait (&self->cond, &self->lock);
  }

  p = (CapturePacket *) g_queue_pop_head (&self->current_packets);
  g_mutex_unlock (&self->lock);

  if (self->flushing) {
    if (p)
      capture_packet_free (p);
    GST_DEBUG_OBJECT (self, "Flushing");
    return GST_FLOW_FLUSHING;
  }

  p->packet->GetBytes ((gpointer *) & data);
  sample_count = p->packet->GetSampleFrameCount ();
  data_size = self->info.bpf * sample_count;

  if (p->timestamp == GST_CLOCK_TIME_NONE && self->next_offset == (guint64) - 1) {
    GST_DEBUG_OBJECT (self,
        "Got packet without timestamp before initial "
        "timestamp after discont - dropping");
    capture_packet_free (p);
    goto retry;
  }

  ap = (AudioPacket *) g_malloc0 (sizeof (AudioPacket));

  *buffer =
      gst_buffer_new_wrapped_full ((GstMemoryFlags) GST_MEMORY_FLAG_READONLY,
      (gpointer) data, data_size, 0, data_size, ap,
      (GDestroyNotify) audio_packet_free);

  ap->packet = p->packet;
  p->packet->AddRef ();
  ap->input = self->input->input;
  ap->input->AddRef ();

  timestamp = p->timestamp;

  // Jitter and discontinuity handling, based on audiobasesrc
  start_time = timestamp;

  // Convert to the sample numbers
  start_offset =
      gst_util_uint64_scale (start_time, self->info.rate, GST_SECOND);

  end_offset = start_offset + sample_count;
  end_time = gst_util_uint64_scale_int (end_offset, GST_SECOND,
      self->info.rate);

  duration = end_time - start_time;

  if (self->next_offset == (guint64) - 1) {
    discont = TRUE;
  } else {
    guint64 diff, max_sample_diff;

    // Check discont
    if (start_offset <= self->next_offset)
      diff = self->next_offset - start_offset;
    else
      diff = start_offset - self->next_offset;

    max_sample_diff =
        gst_util_uint64_scale_int (self->alignment_threshold, self->info.rate,
        GST_SECOND);

    // Discont!
    if (G_UNLIKELY (diff >= max_sample_diff)) {
      if (self->discont_wait > 0) {
        if (self->discont_time == GST_CLOCK_TIME_NONE) {
          self->discont_time = start_time;
        } else if (start_time - self->discont_time >= self->discont_wait) {
          discont = TRUE;
          self->discont_time = GST_CLOCK_TIME_NONE;
        }
      } else {
        discont = TRUE;
      }
    } else if (G_UNLIKELY (self->discont_time != GST_CLOCK_TIME_NONE)) {
      // we have had a discont, but are now back on track!
      self->discont_time = GST_CLOCK_TIME_NONE;
    }
  }

  if (discont) {
    // Have discont, need resync and use the capture timestamps
    if (self->next_offset != (guint64) - 1)
      GST_INFO_OBJECT (self, "Have discont. Expected %"
          G_GUINT64_FORMAT ", got %" G_GUINT64_FORMAT,
          self->next_offset, start_offset);
    GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_DISCONT);
    self->next_offset = end_offset;
    // Got a discont and adjusted, reset the discont_time marker.
    self->discont_time = GST_CLOCK_TIME_NONE;
  } else {
    // No discont, just keep counting
    timestamp =
        gst_util_uint64_scale (self->next_offset, GST_SECOND, self->info.rate);
    self->next_offset += sample_count;
    duration =
        gst_util_uint64_scale (self->next_offset, GST_SECOND,
        self->info.rate) - timestamp;
  }

  if (p->no_signal)
    GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_GAP);
  GST_BUFFER_TIMESTAMP (*buffer) = timestamp;
  GST_BUFFER_DURATION (*buffer) = duration;

  GST_DEBUG_OBJECT (self,
      "Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %"
      GST_TIME_FORMAT, *buffer, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*buffer)),
      GST_TIME_ARGS (GST_BUFFER_DURATION (*buffer)));

  capture_packet_free (p);

  return flow_ret;
}
static GstFlowReturn
gst_dvbsub_overlay_chain_video (GstPad * pad, GstObject * parent,
    GstBuffer * buffer)
{
  GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (parent);
  GstFlowReturn ret = GST_FLOW_OK;
  gint64 start, stop;
  guint64 cstart, cstop;
  gboolean in_seg;
  GstClockTime vid_running_time, vid_running_time_end;

  if (GST_VIDEO_INFO_FORMAT (&overlay->info) == GST_VIDEO_FORMAT_UNKNOWN)
    return GST_FLOW_NOT_NEGOTIATED;

  if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
    goto missing_timestamp;

  start = GST_BUFFER_TIMESTAMP (buffer);

  GST_LOG_OBJECT (overlay,
      "Video segment: %" GST_SEGMENT_FORMAT " --- Subtitle position: %"
      GST_TIME_FORMAT " --- BUFFER: ts=%" GST_TIME_FORMAT,
      &overlay->video_segment,
      GST_TIME_ARGS (overlay->subtitle_segment.position),
      GST_TIME_ARGS (start));

  /* ignore buffers that are outside of the current segment */
  if (!GST_BUFFER_DURATION_IS_VALID (buffer)) {
    stop = GST_CLOCK_TIME_NONE;
  } else {
    stop = start + GST_BUFFER_DURATION (buffer);
  }

  in_seg = gst_segment_clip (&overlay->video_segment, GST_FORMAT_TIME,
      start, stop, &cstart, &cstop);
  if (!in_seg) {
    GST_DEBUG_OBJECT (overlay, "Buffer outside configured segment -- dropping");
    gst_buffer_unref (buffer);
    return GST_FLOW_OK;
  }

  buffer = gst_buffer_make_writable (buffer);
  GST_BUFFER_TIMESTAMP (buffer) = cstart;
  if (GST_BUFFER_DURATION_IS_VALID (buffer))
    GST_BUFFER_DURATION (buffer) = cstop - cstart;

  vid_running_time =
      gst_segment_to_running_time (&overlay->video_segment, GST_FORMAT_TIME,
      cstart);
  if (GST_BUFFER_DURATION_IS_VALID (buffer))
    vid_running_time_end =
        gst_segment_to_running_time (&overlay->video_segment, GST_FORMAT_TIME,
        cstop);
  else
    vid_running_time_end = vid_running_time;

  GST_DEBUG_OBJECT (overlay, "Video running time: %" GST_TIME_FORMAT,
      GST_TIME_ARGS (vid_running_time));

  overlay->video_segment.position = GST_BUFFER_TIMESTAMP (buffer);

  g_mutex_lock (&overlay->dvbsub_mutex);
  if (!g_queue_is_empty (overlay->pending_subtitles)) {
    DVBSubtitles *tmp, *candidate = NULL;

    while (!g_queue_is_empty (overlay->pending_subtitles)) {
      tmp = g_queue_peek_head (overlay->pending_subtitles);

      if (tmp->pts > vid_running_time_end) {
        /* For a future video frame */
        break;
      } else if (tmp->num_rects == 0) {
        /* Clear screen */
        if (overlay->current_subtitle)
          dvb_subtitles_free (overlay->current_subtitle);
        overlay->current_subtitle = NULL;
        if (candidate)
          dvb_subtitles_free (candidate);
        candidate = NULL;
        g_queue_pop_head (overlay->pending_subtitles);
        dvb_subtitles_free (tmp);
        tmp = NULL;
      } else if (tmp->pts + tmp->page_time_out * GST_SECOND *
          ABS (overlay->subtitle_segment.rate) >= vid_running_time) {
        if (candidate)
          dvb_subtitles_free (candidate);
        candidate = tmp;
        g_queue_pop_head (overlay->pending_subtitles);
      } else {
        /* Too late */
        dvb_subtitles_free (tmp);
        tmp = NULL;
        g_queue_pop_head (overlay->pending_subtitles);
      }
    }

    if (candidate) {
      GST_DEBUG_OBJECT (overlay,
          "Time to show the next subtitle page (%" GST_TIME_FORMAT " >= %"
          GST_TIME_FORMAT ") - it has %u regions",
          GST_TIME_ARGS (vid_running_time), GST_TIME_ARGS (candidate->pts),
          candidate->num_rects);
      dvb_subtitles_free (overlay->current_subtitle);
      overlay->current_subtitle = candidate;
      if (overlay->current_comp)
        gst_video_overlay_composition_unref (overlay->current_comp);
      overlay->current_comp =
          gst_dvbsub_overlay_subs_to_comp (overlay, overlay->current_subtitle);
    }
  }

  /* Check that we haven't hit the fallback timeout for current subtitle page */
  if (overlay->current_subtitle
      && vid_running_time >
      (overlay->current_subtitle->pts +
          overlay->current_subtitle->page_time_out * GST_SECOND *
          ABS (overlay->subtitle_segment.rate))) {
    GST_INFO_OBJECT (overlay,
        "Subtitle page not redefined before fallback page_time_out of %u seconds (missed data?) - deleting current page",
        overlay->current_subtitle->page_time_out);
    dvb_subtitles_free (overlay->current_subtitle);
    overlay->current_subtitle = NULL;
  }

  /* Now render it */
  if (g_atomic_int_get (&overlay->enable) && overlay->current_subtitle) {
    GstVideoFrame frame;

    g_assert (overlay->current_comp);
    if (overlay->attach_compo_to_buffer) {
      GST_DEBUG_OBJECT (overlay, "Attaching overlay image to video buffer");
      gst_buffer_add_video_overlay_composition_meta (buffer,
          overlay->current_comp);
    } else {
      GST_DEBUG_OBJECT (overlay, "Blending overlay image to video buffer");
      gst_video_frame_map (&frame, &overlay->info, buffer, GST_MAP_READWRITE);
      gst_video_overlay_composition_blend (overlay->current_comp, &frame);
      gst_video_frame_unmap (&frame);
    }
  }
  g_mutex_unlock (&overlay->dvbsub_mutex);

  ret = gst_pad_push (overlay->srcpad, buffer);

  return ret;

missing_timestamp:
  {
    GST_WARNING_OBJECT (overlay, "video buffer without timestamp, discarding");
    gst_buffer_unref (buffer);
    return GST_FLOW_OK;
  }
}
Exemple #7
0
static gboolean
flap_connection_destroy_cb(gpointer data)
{
	FlapConnection *conn;
	OscarData *od;
	PurpleAccount *account;
	aim_rxcallback_t userfunc;

	conn = data;
	/* Explicitly added for debugging #5927.  Don't re-order this, only
	 * consider removing it.
	 */
	purple_debug_info("oscar", "Destroying FLAP connection %p\n", conn);

	od = conn->od;
	account = purple_connection_get_account(od->gc);

	purple_debug_info("oscar", "Destroying oscar connection (%p) of "
			"type 0x%04hx.  Disconnect reason is %d\n", conn,
			conn->type, conn->disconnect_reason);

	od->oscar_connections = g_slist_remove(od->oscar_connections, conn);

	if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
		userfunc(od, conn, NULL, conn->disconnect_code, conn->error_message);

	/*
	 * TODO: If we don't have a SNAC_FAMILY_LOCATE connection then
	 * we should try to request one instead of disconnecting.
	 */
	if (!account->disconnecting && ((od->oscar_connections == NULL)
			|| (!flap_connection_getbytype(od, SNAC_FAMILY_LOCATE))))
	{
		/* No more FLAP connections!  Sign off this PurpleConnection! */
		gchar *tmp;
		PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;

		if (conn->disconnect_code == 0x0001) {
			reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
			tmp = g_strdup(_("You have signed on from another location"));
			if (!purple_account_get_remember_password(account))
				purple_account_set_password(account, NULL);
		} else if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED)
			tmp = g_strdup(_("Server closed the connection"));
		else if (conn->disconnect_reason == OSCAR_DISCONNECT_LOST_CONNECTION)
			tmp = g_strdup_printf(_("Lost connection with server: %s"),
					conn->error_message);
		else if (conn->disconnect_reason == OSCAR_DISCONNECT_INVALID_DATA)
			tmp = g_strdup(_("Received invalid data on connection with server"));
		else if (conn->disconnect_reason == OSCAR_DISCONNECT_COULD_NOT_CONNECT)
			tmp = g_strdup_printf(_("Unable to connect: %s"),
					conn->error_message);
		else
			/*
			 * We shouldn't print a message for some disconnect_reasons.
			 * Like OSCAR_DISCONNECT_LOCAL_CLOSED.
			 */
			tmp = NULL;

		if (tmp != NULL)
		{
			purple_connection_error_reason(od->gc, reason, tmp);
			g_free(tmp);
		}
	}

	flap_connection_close(od, conn);

	g_free(conn->error_message);
	g_free(conn->cookie);

	/*
	 * Free conn->internal, if necessary
	 */
	if (conn->type == SNAC_FAMILY_CHAT)
		flap_connection_destroy_chat(od, conn);

	g_slist_free(conn->groups);
	while (conn->rateclasses != NULL)
	{
		g_free(conn->rateclasses->data);
		conn->rateclasses = g_slist_delete_link(conn->rateclasses, conn->rateclasses);
	}

	g_hash_table_destroy(conn->rateclass_members);

	if (conn->queued_snacs) {
		while (!g_queue_is_empty(conn->queued_snacs))
		{
			QueuedSnac *queued_snac;
			queued_snac = g_queue_pop_head(conn->queued_snacs);
			flap_frame_destroy(queued_snac->frame);
			g_free(queued_snac);
		}
		g_queue_free(conn->queued_snacs);
	}

	if (conn->queued_lowpriority_snacs) {
		while (!g_queue_is_empty(conn->queued_lowpriority_snacs))
		{
			QueuedSnac *queued_snac;
			queued_snac = g_queue_pop_head(conn->queued_lowpriority_snacs);
			flap_frame_destroy(queued_snac->frame);
			g_free(queued_snac);
		}
		g_queue_free(conn->queued_lowpriority_snacs);
	}

	if (conn->queued_timeout > 0)
		purple_timeout_remove(conn->queued_timeout);

	g_free(conn);

	return FALSE;
}
static void
find_contiguous_region_helper (GeglBuffer          *src_buffer,
                               GeglBuffer          *mask_buffer,
                               const Babl          *format,
                               gint                 n_components,
                               gboolean             has_alpha,
                               gboolean             select_transparent,
                               GimpSelectCriterion  select_criterion,
                               gboolean             antialias,
                               gfloat               threshold,
                               gint                 x,
                               gint                 y,
                               const gfloat        *col)
{
  gint    start, end;
  gint    new_start, new_end;
  GQueue *coord_stack;

  coord_stack = g_queue_new ();

  /* To avoid excessive memory allocation (y, start, end) tuples are
   * stored in interleaved format:
   *
   * [y1] [start1] [end1] [y2] [start2] [end2]
   */
  g_queue_push_tail (coord_stack, GINT_TO_POINTER (y));
  g_queue_push_tail (coord_stack, GINT_TO_POINTER (x - 1));
  g_queue_push_tail (coord_stack, GINT_TO_POINTER (x + 1));

  do
    {
      y     = GPOINTER_TO_INT (g_queue_pop_head (coord_stack));
      start = GPOINTER_TO_INT (g_queue_pop_head (coord_stack));
      end   = GPOINTER_TO_INT (g_queue_pop_head (coord_stack));

      for (x = start + 1; x < end; x++)
        {
          gfloat val;

          gegl_buffer_sample (mask_buffer, x, y, NULL, &val,
                              babl_format ("Y float"),
                              GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
          if (val != 0.0)
            continue;

          if (! find_contiguous_segment (col, src_buffer, mask_buffer,
                                         format,
                                         n_components,
                                         has_alpha,
                                         gegl_buffer_get_width (src_buffer),
                                         select_transparent, select_criterion,
                                         antialias, threshold, x, y,
                                         &new_start, &new_end))
            continue;

          if (y + 1 < gegl_buffer_get_height (src_buffer))
            {
              g_queue_push_tail (coord_stack, GINT_TO_POINTER (y + 1));
              g_queue_push_tail (coord_stack, GINT_TO_POINTER (new_start));
              g_queue_push_tail (coord_stack, GINT_TO_POINTER (new_end));
            }

          if (y - 1 >= 0)
            {
              g_queue_push_tail (coord_stack, GINT_TO_POINTER (y - 1));
              g_queue_push_tail (coord_stack, GINT_TO_POINTER (new_start));
              g_queue_push_tail (coord_stack, GINT_TO_POINTER (new_end));
            }
        }
    }
  while (! g_queue_is_empty (coord_stack));

  g_queue_free (coord_stack);
}
Exemple #9
0
static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
{
	struct _GAttrib *attrib = data;
	struct command *cmd = NULL;
	GSList *l;
	uint8_t buf[512], status;
	gsize len;
	GIOStatus iostat;

	if (attrib->stale)
		return FALSE;

	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
		struct command *c;

		while ((c = g_queue_pop_head(attrib->requests))) {
			if (c->func)
				c->func(ATT_ECODE_IO, NULL, 0, c->user_data);
			command_destroy(c);
		}

		attrib->read_watch = 0;

		return FALSE;
	}

	memset(buf, 0, sizeof(buf));

	iostat = g_io_channel_read_chars(io, (char *) buf, sizeof(buf),
								&len, NULL);
	if (iostat != G_IO_STATUS_NORMAL) {
		status = ATT_ECODE_IO;
		goto done;
	}

	for (l = attrib->events; l; l = l->next) {
		struct event *evt = l->data;

		if (match_event(evt, buf, len))
			evt->func(buf, len, evt->user_data);
	}

	if (!is_response(buf[0]))
		return TRUE;

	if (attrib->timeout_watch > 0) {
		g_source_remove(attrib->timeout_watch);
		attrib->timeout_watch = 0;
	}

	cmd = g_queue_pop_head(attrib->requests);
	if (cmd == NULL) {
		/* Keep the watch if we have events to report */
		return attrib->events != NULL;
	}

	if (buf[0] == ATT_OP_ERROR) {
		status = buf[4];
		goto done;
	}

	if (cmd->expected != buf[0]) {
		status = ATT_ECODE_IO;
		goto done;
	}

	status = 0;

done:
	if (!g_queue_is_empty(attrib->requests) ||
					!g_queue_is_empty(attrib->responses))
		wake_up_sender(attrib);

	if (cmd) {
		if (cmd->func)
			cmd->func(status, buf, len, cmd->user_data);

		command_destroy(cmd);
	}

	return TRUE;
}
static void
process_video (GstMerger * merger)
{
  GST_DEBUG_OBJECT (merger, "Task function begin");

beg:

  GST_DEBUG_OBJECT (merger, "Task function loop");

  if ((volatile int) merger->stop) {
    GST_INFO_OBJECT (merger, "Task goto end");
    goto end;
  }


  g_mutex_trylock (&merger->task_lock);
  GST_DEBUG_OBJECT (merger, "Task waiting for cond");
  g_cond_wait (&merger->task_cond, &merger->task_lock);

  GST_DEBUG_OBJECT (merger, "Task processing");

  while (1) {
    GstBuffer *buf_l = NULL;
    GstBuffer *buf_r = NULL;

    if (GST_PAD_IS_EOS (merger->sinkl_pad)) {
      goto beg;
    }
    if (GST_PAD_IS_EOS (merger->sinkr_pad)) {
      goto beg;
    }

    if (g_queue_is_empty (&merger->bufs_l)) {
      GST_DEBUG_OBJECT (merger, "No L buffers left");
      goto beg;
    }
    if (g_queue_is_empty (&merger->bufs_r)) {
      GST_DEBUG_OBJECT (merger, "No R buffers left");
      goto beg;
    }

    GST_OBJECT_LOCK (merger);

    GstBuffer *buf_l0 = g_queue_peek_head (&merger->bufs_l);
    GstBuffer *buf_l1 = g_queue_peek_tail (&merger->bufs_l);
    GstBuffer *buf_r0 = g_queue_peek_head (&merger->bufs_r);
    GstBuffer *buf_r1 = g_queue_peek_tail (&merger->bufs_r);

    GST_DEBUG_OBJECT (merger, "L0: %" GST_PTR_FORMAT, buf_l0);
    GST_DEBUG_OBJECT (merger, "L1: %" GST_PTR_FORMAT, buf_l1);
    GST_DEBUG_OBJECT (merger, "R0: %" GST_PTR_FORMAT, buf_r0);
    GST_DEBUG_OBJECT (merger, "R1: %" GST_PTR_FORMAT, buf_r1);

    if (GST_BUFFER_PTS (buf_l0) >= GST_BUFFER_PTS (buf_r0)
        && GST_BUFFER_PTS (buf_l0) <= GST_BUFFER_PTS (buf_r0)
        + GST_BUFFER_DURATION (buf_r0)) {
      buf_l = g_queue_pop_head (&merger->bufs_l);
      buf_r = g_queue_pop_head (&merger->bufs_r);
    } else if (GST_BUFFER_PTS (buf_r0) >= GST_BUFFER_PTS (buf_l0)
        && GST_BUFFER_PTS (buf_r0) <= GST_BUFFER_PTS (buf_l0)
        + GST_BUFFER_DURATION (buf_l0)) {
      buf_l = g_queue_pop_head (&merger->bufs_l);
      buf_r = g_queue_pop_head (&merger->bufs_r);
    } else if (GST_BUFFER_PTS (buf_r0) + GST_BUFFER_DURATION (buf_r0) <
        GST_BUFFER_PTS (buf_l0)) {
      buf_r = g_queue_pop_head (&merger->bufs_r);
      gst_buffer_unref (buf_r);
      buf_r = NULL;
      GST_DEBUG_OBJECT (merger, "Discarding one R");
      GST_OBJECT_UNLOCK (merger);
      continue;
    } else if (GST_BUFFER_PTS (buf_l0) + GST_BUFFER_DURATION (buf_l0) <
        GST_BUFFER_PTS (buf_r0)) {
      buf_l = g_queue_pop_head (&merger->bufs_l);
      gst_buffer_unref (buf_l);
      buf_l = NULL;
      GST_DEBUG_OBJECT (merger, "Discarding one L");
      GST_OBJECT_UNLOCK (merger);
      continue;
    } else {
      GST_DEBUG_OBJECT (merger, "Not implemented");
    }

    if (buf_l == NULL || buf_r == NULL) {
      goto beg;
    }

    GST_OBJECT_UNLOCK (merger);

    GST_DEBUG_OBJECT (merger, "Pushing new buffer");


    gint w = 1280;
    gint h = 480;
    {
      GstCaps *caps = gst_pad_get_current_caps (merger->srcv_pad);
      GstStructure *s = gst_caps_get_structure (caps, 0);
      gst_structure_get_int (s, "width", &w);
      gst_structure_get_int (s, "height", &h);
      gst_caps_unref (caps);
    }


    GstBuffer *buf_out = gst_buffer_new_allocate (NULL, w * h * 4, NULL);

    GstMapInfo map_l;
    GstMapInfo map_r;
    GstMapInfo map_out;
    bool res = gst_buffer_map (buf_out, &map_out, GST_MAP_WRITE);
    g_assert (res);
    res = gst_buffer_map (buf_l, &map_l, GST_MAP_READ);
    g_assert (res);
    res = gst_buffer_map (buf_r, &map_r, GST_MAP_READ);
    g_assert (res);

    guint8 *a_o = (guint8 *) map_out.data;
    guint8 *a_l = (guint8 *) map_l.data;
    guint8 *a_r = (guint8 *) map_r.data;
    for (int y = 0; y < h; y++) {
      for (int x = 0; x < w / 2; x++) {
        guint8 r = a_l[3 * (y * w / 2 + x) + 0];
        guint8 g = a_l[3 * (y * w / 2 + x) + 1];
        guint8 b = a_l[3 * (y * w / 2 + x) + 2];
        a_o[4 * (y * w + x) + 0] = r;
        a_o[4 * (y * w + x) + 1] = g;
        a_o[4 * (y * w + x) + 2] = b;
        a_o[4 * (y * w + x) + 3] = 255;
      }
      for (int x = 0; x < w / 2; x++) {
        guint8 r = a_r[3 * (y * w / 2 + x) + 0];
        guint8 g = a_r[3 * (y * w / 2 + x) + 1];
        guint8 b = a_r[3 * (y * w / 2 + x) + 2];
        a_o[4 * (y * w + x + w / 2) + 0] = r;
        a_o[4 * (y * w + x + w / 2) + 1] = g;
        a_o[4 * (y * w + x + w / 2) + 2] = b;
        a_o[4 * (y * w + x + w / 2) + 3] = 255;
      }
    }

    usleep (10000);

    gst_buffer_unmap (buf_l, &map_l);
    gst_buffer_unmap (buf_r, &map_r);
    gst_buffer_unmap (buf_out, &map_out);

    GST_BUFFER_PTS (buf_out) = GST_BUFFER_PTS (buf_l);
    GST_BUFFER_DTS (buf_out) = GST_BUFFER_DTS (buf_l);
    GST_BUFFER_DURATION (buf_out) = GST_BUFFER_DURATION (buf_l);

    gst_buffer_unref (buf_l);
    gst_buffer_unref (buf_r);

    int res2 = gst_pad_push (merger->srcv_pad, buf_out);
    if (res2 != GST_FLOW_OK) {
      GST_WARNING_OBJECT (merger, "Pushing pad returned %d", res2);
      goto error;
    }

  }

  goto beg;

error:
end:

  GST_INFO_OBJECT (merger, "Task bye bye?");

  //gst_task_pause (merger->task);

  GST_INFO_OBJECT (merger, "Task bye bye");

  g_mutex_unlock (&merger->task_lock);
}
Exemple #11
0
/* ...pop buffers from a render queue */
static inline int sview_pop_buffers(app_data_t *app, GstBuffer **buf, texture_data_t **tex, GLuint *t, void **planes, s64 *ts)
{
    int     i;
    int     ready;
    
    /* ...lock access to internal data */
    pthread_mutex_lock(&app->lock);

    /* ...check for a termination request */
    if (app->flags & APP_FLAG_EOS)
    {
        /* ...drop all buffers */
        for (i = 0; i < CAMERAS_NUMBER; i++)
        {
            while (!g_queue_is_empty(&app->render[i]))
            {
                gst_buffer_unref(g_queue_pop_head(&app->render[i]));
            }
        }

        TRACE(DEBUG, _b("purged rendering queue"));
        
        /* ...mark we have no buffers to draw */
        ready = 0;
    }
    else if ((app->frames & ((1 << CAMERAS_NUMBER) - 1)) == 0)
    {
        s64     ts_acc = 0;
        
        /* ...collect the textures corresponding to the cameras */
        for (i = 0; i < CAMERAS_NUMBER; i++)
        {
            GQueue         *queue = &app->render[i];
            GstBuffer      *buffer;
            vsink_meta_t   *meta;
            texture_data_t *texture;
            
            /* ...buffer must be available */
            BUG(g_queue_is_empty(queue), _x("inconsistent state of camera-%d"), i);
            
            /* ...retrieve last (most actual) buffer */
            buf[i] = buffer = g_queue_peek_tail(queue);
            meta = gst_buffer_get_vsink_meta(buffer);
            tex[i] = texture = meta->priv;
            t[i] = texture->tex;
            planes[i] = texture->data[0];

            /* ...update timestamp accumulator */
            ts_acc += GST_BUFFER_DTS(buffer);

            /* ...drop all "previous" buffers */
            while (g_queue_peek_head(queue) != buffer)
            {
                gst_buffer_unref(g_queue_pop_head(queue));
            }
        }
        
        /* ...update accumulator */
        *ts = ts_acc / CAMERAS_NUMBER;

        /* ...return buffer readiness indication */
        ready = 1;
    }
    else
    {
        /* ...buffers not ready */
        ready = 0;
    }

    pthread_mutex_unlock(&app->lock);

    return ready;
}
Exemple #12
0
static void
on_request_ready (GObject *source,
                  GAsyncResult *result,
                  gpointer user_data) {
  ResolveClosure *closure = (ResolveClosure *) user_data;
  GrlTmdbRequest *request = GRL_TMDB_REQUEST (source);
  const GrlTmdbRequestDetail detail = grl_tmdb_request_get_detail (request);
  GError *error = NULL;
  GList *values, *iter;
  GValue *value;

  if (detail != GRL_TMDB_REQUEST_DETAIL_COUNT) {
    GRL_DEBUG ("Detail request (%s) ready for movie #%" G_GUINT64_FORMAT "...",
               grl_tmdb_request_detail_to_string (detail), closure->id);
  } else {
    GRL_DEBUG ("Detail request (aggregated) ready for movie #%" G_GUINT64_FORMAT "...",
               closure->id);
  }

  if (!grl_tmdb_request_run_finish (GRL_TMDB_REQUEST (source),
                                    result,
                                    &error)) {
    /* Just remove the request and hope the others have some data */
    GRL_WARNING ("Failed to get %s: %s",
                 grl_tmdb_request_get_uri (request),
                 error->message);
    goto out;
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_GENRE)) {
    iter = values = grl_tmdb_request_get_string_list (request, "$.genres..name");
    while (iter != NULL) {
      grl_data_add_string (GRL_DATA (closure->rs->media),
                           GRL_METADATA_KEY_GENRE, iter->data);
      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_STUDIO)) {
    iter = values = grl_tmdb_request_get_string_list (request, "$.production_companies..name");
    while (iter != NULL) {
      grl_data_add_string (GRL_DATA (closure->rs->media),
                           GRL_METADATA_KEY_STUDIO, iter->data);
      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_SITE)) {
    value = grl_tmdb_request_get (request, "$.homepage");
    if (value != NULL) {
      grl_media_set_site (closure->rs->media, g_value_get_string (value));
      g_value_unset (value);
      g_free (value);
    }
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_DESCRIPTION)) {
    value = grl_tmdb_request_get (request, "$.overview");
    if (value != NULL) {
      grl_media_set_description (closure->rs->media,
                                 g_value_get_string (value));
      g_value_unset (value);
      g_free (value);
    }
  }

  if (SHOULD_RESOLVE (GRL_TMDB_METADATA_KEY_IMDB_ID)) {
    value = grl_tmdb_request_get (request, "$.imdb_id");
    if (value != NULL) {
      grl_data_set_string (GRL_DATA (closure->rs->media),
                           GRL_TMDB_METADATA_KEY_IMDB_ID,
                           g_value_get_string (value));
      g_value_unset (value);
      g_free (value);
    }
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_RATING)) {
    value = grl_tmdb_request_get (request, "$.vote_average");
    if (value != NULL) {
      grl_media_set_rating (closure->rs->media,
                            (float) g_value_get_double (value),
                            10.0f);
      g_value_unset (value);
      g_free (value);
    }
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_ORIGINAL_TITLE)) {
    value = grl_tmdb_request_get (request, "$.original_title");
    if (value != NULL) {
      grl_media_set_original_title (closure->rs->media, g_value_get_string (value));
      g_value_unset (value);
      g_free (value);
    }
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_TITLE)) {
    value = grl_tmdb_request_get (request, "$.title");
    if (value != NULL) {
      grl_media_set_title (closure->rs->media, g_value_get_string (value));
      grl_data_set_boolean (GRL_DATA (closure->rs->media), GRL_METADATA_KEY_TITLE_FROM_FILENAME, FALSE);
      g_value_unset (value);
      g_free (value);
    }
  }

  if (!closure->slow) {
    /* Add thumbnails first and poster and backdrops later.
     * Posters more likely make a good thumbnail than backdrops.
     */
    if (SHOULD_RESOLVE (GRL_METADATA_KEY_THUMBNAIL)) {
      value = grl_tmdb_request_get (request, "$.poster_path");
      if (value != NULL) {
          add_image (closure->self, closure->rs->media,
                     GRL_METADATA_KEY_THUMBNAIL,
                     g_value_get_string (value));

          g_value_unset (value);
          g_free (value);
      }
    }

    if (SHOULD_RESOLVE (GRL_TMDB_METADATA_KEY_POSTER)) {
      value = grl_tmdb_request_get (request, "$.poster_path");
      if (value != NULL) {
          add_image (closure->self, closure->rs->media,
                     GRL_TMDB_METADATA_KEY_POSTER,
                     g_value_get_string (value));

          g_value_unset (value);
          g_free (value);
      }
    }

    if (SHOULD_RESOLVE (GRL_TMDB_METADATA_KEY_BACKDROP)) {
      value = grl_tmdb_request_get (request, "$.backdrop_path");
      if (value != NULL) {
        add_image (closure->self, closure->rs->media,
                   GRL_TMDB_METADATA_KEY_BACKDROP,
                   g_value_get_string (value));

        g_value_unset (value);
        g_free (value);
      }
    }
  }

  /* Add thumbnails first, and posters and backdrops later.
   * Posters more likely make a good thumbnail than backdrops.
   */
  if (SHOULD_RESOLVE (GRL_METADATA_KEY_THUMBNAIL)) {
    values = grl_tmdb_request_get_string_list_with_filter (request,
                                                           "$.posters",
                                                           neutral_backdrop_filter);
    if (!values)
      values = grl_tmdb_request_get_string_list_with_filter (request,
                                                             "$.images.posters",
                                                             neutral_backdrop_filter);
    iter = values;
    while (iter != NULL) {
      add_image (closure->self, closure->rs->media,
                 GRL_METADATA_KEY_THUMBNAIL,
                 iter->data);

      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_TMDB_METADATA_KEY_POSTER)) {
    values = grl_tmdb_request_get_string_list_with_filter (request,
                                                           "$.posters",
                                                           neutral_backdrop_filter);
    if (!values)
      values = grl_tmdb_request_get_string_list_with_filter (request,
                                                             "$.images.posters",
                                                             neutral_backdrop_filter);
    iter = values;
    while (iter != NULL) {
      add_image (closure->self, closure->rs->media,
                 GRL_TMDB_METADATA_KEY_POSTER,
                 iter->data);

      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_TMDB_METADATA_KEY_BACKDROP)) {
    values = grl_tmdb_request_get_string_list_with_filter (request,
                                                           "$.backdrops",
                                                           neutral_backdrop_filter);
    if (!values)
      values = grl_tmdb_request_get_string_list_with_filter (request,
                                                             "$.images.backdrops",
                                                             neutral_backdrop_filter);
    iter = values;
    while (iter != NULL) {
      add_image (closure->self, closure->rs->media,
                 GRL_TMDB_METADATA_KEY_BACKDROP,
                 iter->data);

      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_KEYWORD)) {
    values = grl_tmdb_request_get_string_list (request,
                                               "$.keywords..name");
    if (!values)
      values = grl_tmdb_request_get_string_list (request,
                                                 "$.keywords.keywords..name");
    iter = values;
    while (iter != NULL) {
      grl_media_add_keyword (closure->rs->media, iter->data);
      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_PERFORMER)) {
    values = grl_tmdb_request_get_string_list (request, "$.cast..name");
    if (!values)
      values = grl_tmdb_request_get_string_list (request, "$.casts.cast..name");
    iter = values;
    while (iter != NULL) {
      grl_media_add_performer (closure->rs->media, iter->data);
      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_PRODUCER)) {
    values = grl_tmdb_request_get_string_list_with_filter (request,
                                                           "$.crew[*]",
                                                           producer_filter);
    if (!values)
      values = grl_tmdb_request_get_string_list_with_filter (request,
                                                             "$.casts.crew[*]",
                                                             producer_filter);
    iter = values;
    while (iter != NULL) {
        grl_media_add_producer (closure->rs->media, iter->data);
      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_DIRECTOR)) {
    values = grl_tmdb_request_get_string_list_with_filter (request,
                                                           "$.crew[*]",
                                                           director_filter);
    if (!values)
      values = grl_tmdb_request_get_string_list_with_filter (request,
                                                             "$.casts.crew[*]",
                                                             director_filter);
    iter = values;
    while (iter != NULL) {
      grl_media_add_director (closure->rs->media, iter->data);
      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_AUTHOR)) {
    values = grl_tmdb_request_get_string_list_with_filter (request,
                                                           "$.crew[*]",
                                                           writer_filter);
    if (!values)
      values = grl_tmdb_request_get_string_list_with_filter (request,
                                                             "$.casts.crew[*]",
                                                             writer_filter);
    iter = values;
    while (iter != NULL) {
      grl_media_add_author (GRL_MEDIA (closure->rs->media),
                            iter->data);
      iter = iter->next;
    }
    g_list_free_full (values, g_free);
  }

  if (SHOULD_RESOLVE (GRL_METADATA_KEY_REGION) ||
          SHOULD_RESOLVE (GRL_METADATA_KEY_CERTIFICATE) ||
          SHOULD_RESOLVE (GRL_METADATA_KEY_PUBLICATION_DATE)) {
    values = grl_tmdb_request_get_list_with_filter (request,
                                                    "$.countries[*]",
                                                    NULL);
    if (!values)
      values = grl_tmdb_request_get_list_with_filter (request,
                                                      "$.releases.countries[*]",
                                                      NULL);

    for (iter = values; iter != NULL; iter = iter->next) {
      const char *region, *cert, *date;
      GDateTime *pubdate;
      JsonObject *object;

      object = json_node_get_object (iter->data);
      region = json_object_get_string_member (object, "iso_3166_1");
      cert = json_object_get_string_member (object, "certification");
      date = json_object_get_string_member (object, "release_date");
      pubdate = parse_date (date);

      grl_media_add_region_data (closure->rs->media, region, pubdate, cert);

      g_date_time_unref (pubdate);
    }

    g_list_free_full (values, (GDestroyNotify) json_node_free);
  }

out:
  if (error != NULL) {
    g_error_free (error);
  }

  remove_request (closure, request);

  if (g_queue_is_empty (closure->pending_requests)) {
    resolve_closure_callback (closure, NULL);
    resolve_closure_free (closure);
  }
}
Exemple #13
0
static void
grl_tmdb_source_resolve (GrlSource *source,
                                  GrlSourceResolveSpec *rs)
{
  ResolveClosure *closure;
  GrlTmdbRequest *request;
  const char *title = NULL;
  const char *str_movie_id;
  GrlTmdbSource *self = GRL_TMDB_SOURCE (source);
  guint64 movie_id = 0;
  GList *it;

  if (!grl_media_is_video (rs->media)) {
    /* We only entertain videos */
    rs->callback (source, rs->operation_id, rs->media, rs->user_data, NULL);
    return;
  }

  /* If the media is a TV show, don't handle it */
  if (grl_media_get_show (rs->media) != NULL) {
    rs->callback (source, rs->operation_id, rs->media, rs->user_data, NULL);
    return;
  }

  /* Prefer resolving by movie-id: This is more reliable and saves the search query. */
  str_movie_id = grl_data_get_string (GRL_DATA (rs->media),
                                      GRL_TMDB_METADATA_KEY_TMDB_ID);

  if (str_movie_id)
    movie_id = strtoull (str_movie_id, NULL, 10);

  /* Try title if no movie-id could be found. */
  if (movie_id == 0)
    title = grl_media_get_title (rs->media);

  if (movie_id == 0 && title == NULL) {
    /* Can't search for anything without a title or the movie-id ... */
    rs->callback (source, rs->operation_id, rs->media, rs->user_data, NULL);
    return;
  }

  GRL_DEBUG ("grl_tmdb_source_resolve");

  closure = g_slice_new0 (ResolveClosure);
  closure->self = g_object_ref (self);
  closure->rs = rs;
  closure->pending_requests = g_queue_new ();
  closure->keys = g_hash_table_new (g_direct_hash, g_direct_equal);
  closure->slow = FALSE;
  closure->id = movie_id;

  it = rs->keys;

  /* Copy keys to list for faster lookup */
  while (it) {
    g_hash_table_add (closure->keys, it->data);

    /* Enable slow resolution if slow keys are requested */
    closure->slow |= g_hash_table_contains (self->priv->slow_keys,
                                            it->data);
    it = it->next;
  }

  /* Disable slow resolution if slow keys where requested, but the operation
   * options explicitly ask for fast resolving only. */
  if (grl_operation_options_get_resolution_flags (rs->options) & GRL_RESOLVE_FAST_ONLY)
    closure->slow = FALSE;

  /* We did not receive the config yet, queue request. Config callback will
   * take care of flushing the queue when ready.
   */
  if (self->priv->configuration == NULL && self->priv->config_pending) {
    g_queue_push_tail (self->priv->pending_resolves, closure);
    return;
  }

  if (self->priv->configuration == NULL) {
    GRL_DEBUG ("Fetching TMDb configuration...");
    /* We need to fetch TMDb's configuration for the image paths */
    request = grl_tmdb_request_new_configuration (closure->self->priv->api_key);
    g_assert (g_queue_is_empty (closure->pending_requests));
    queue_request (closure, request, on_configuration_ready);
    self->priv->config_pending = TRUE;
  }

  if (title) {
    GRL_DEBUG ("Running initial search for title \"%s\"...", title);
    request = grl_tmdb_request_new_search (closure->self->priv->api_key, title);
    queue_request (closure, request, on_search_ready);
    run_pending_requests (closure, 1);
  } else {
    GRL_DEBUG ("Running %s lookup for movie #%" G_GUINT64_FORMAT "...",
               closure->slow ? "slow" : "fast", movie_id);

    if (closure->slow) {
      resolve_slow_details (closure);
    } else {
      queue_detail_request (closure, GRL_TMDB_REQUEST_DETAIL_MOVIE);
    }

    run_pending_requests (closure, G_MAXINT);
  }
}
/* 
 * renderer methods 
 */ 
static void 
draw_object(DiaRenderer *self,
            DiaObject   *object,
	    DiaMatrix   *matrix)
{
  DrsRenderer *renderer = DRS_RENDERER (self);
  DiaMatrix *m = g_queue_peek_tail (renderer->matrices);
  xmlNodePtr node;

  g_queue_push_tail (renderer->parents, renderer->root);
  renderer->root = node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"object", NULL);
  xmlSetProp(node, (const xmlChar *)"type", (xmlChar *)object->type->name);
  /* if it looks like intdata store it as well */
  if ((int)object->type->default_user_data > 0 && (int)object->type->default_user_data < 0xFF) {
    gchar buffer[30];
    g_snprintf(buffer, sizeof(buffer), "%d", (int)object->type->default_user_data);
    xmlSetProp(node, (const xmlChar *)"intdata", (xmlChar *)buffer);
  }
  if (renderer->save_props) {
    xmlNodePtr props_node;

    props_node = xmlNewChild(node, NULL, (const xmlChar *)"properties", NULL);
    object_save_props (object, props_node, renderer->ctx);
  }
  if (matrix) {
    DiaMatrix *m2 = g_new (DiaMatrix, 1);
    if (m)
      dia_matrix_multiply (m2, matrix, m);
    else
      *m2 = *matrix;
    g_queue_push_tail (renderer->matrices, m2);
    /* lazy creation of our transformer */
    if (!renderer->transformer)
      renderer->transformer = dia_transform_renderer_new (self);
  }
  /* special handling for group objects:
   *  - for the render branch use DiaTransformRenderer, but not it's draw_object,
   *    to see all the children's draw_object ourself
   *  - for the object branch we rely on this draw_object being called so need
   *    to inline group_draw here
   *  - to maintain the correct transform build our own queue of matrices like
   *    the DiaTransformRenderer would do through it's draw_object
   */
  {
    g_queue_push_tail (renderer->parents, renderer->root);
    renderer->root = node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"render", NULL);
    if (renderer->transformer) {
      DiaMatrix *m = g_queue_peek_tail (renderer->matrices);

      if (IS_GROUP (object)) {
	/* reimplementation of group_draw to use this draw_object method */
	GList *list;
	DiaObject *obj;

	list = group_objects (object);
	while (list != NULL) {
	  obj = (DiaObject *) list->data;

	  DIA_RENDERER_GET_CLASS(self)->draw_object(self, obj, m);
	  list = g_list_next(list);
	}
      } else {
	/* just the leaf */
	DIA_RENDERER_GET_CLASS(renderer->transformer)->draw_object(renderer->transformer, object, m);
      }
    } else {
      object->ops->draw(object, DIA_RENDERER (renderer));
    }
    renderer->root = g_queue_pop_tail (renderer->parents);
  }
  renderer->root = g_queue_pop_tail (renderer->parents);

  if (matrix)
    g_queue_pop_tail (renderer->matrices);
  /* one lost demand destruction */
  if (renderer->transformer && g_queue_is_empty (renderer->matrices)) {
    g_object_unref (renderer->transformer);
    renderer->transformer = NULL;
  }
}
Exemple #15
0
/**
 * Wait for the libcurl socket.
 *
 * @return -1 on error, 0 if no data is available yet, 1 if data is
 * available
 */
static int
input_curl_select(struct input_curl *c, GError **error_r)
{
	fd_set rfds, wfds, efds;
	int max_fd, ret;
	CURLMcode mcode;
	struct timeval timeout = {
		.tv_sec = 1,
		.tv_usec = 0,
	};

	assert(!c->eof);

	FD_ZERO(&rfds);
	FD_ZERO(&wfds);
	FD_ZERO(&efds);

	mcode = curl_multi_fdset(c->multi, &rfds, &wfds, &efds, &max_fd);
	if (mcode != CURLM_OK) {
		g_set_error(error_r, curl_quark(), mcode,
			    "curl_multi_fdset() failed: %s",
			    curl_multi_strerror(mcode));
		return -1;
	}

#if LIBCURL_VERSION_NUM >= 0x070f04
	long timeout2;
	mcode = curl_multi_timeout(c->multi, &timeout2);
	if (mcode != CURLM_OK) {
		g_warning("curl_multi_timeout() failed: %s\n",
			  curl_multi_strerror(mcode));
		return -1;
	}

	if (timeout2 >= 0) {
		if (timeout2 > 10000)
			timeout2 = 10000;

		timeout.tv_sec = timeout2 / 1000;
		timeout.tv_usec = (timeout2 % 1000) * 1000;
	}
#endif

	ret = select(max_fd + 1, &rfds, &wfds, &efds, &timeout);
	if (ret < 0)
		g_set_error(error_r, g_quark_from_static_string("errno"),
			    errno,
			    "select() failed: %s\n", g_strerror(errno));

	return ret;
}

static bool
fill_buffer(struct input_stream *is, GError **error_r)
{
	struct input_curl *c = (struct input_curl *)is;
	CURLMcode mcode = CURLM_CALL_MULTI_PERFORM;

	while (!c->eof && g_queue_is_empty(c->buffers)) {
		int running_handles;
		bool bret;

		if (mcode != CURLM_CALL_MULTI_PERFORM) {
			/* if we're still here, there is no input yet
			   - wait for input */
			int ret = input_curl_select(c, error_r);
			if (ret <= 0)
				/* no data yet or error */
				return false;
		}

		mcode = curl_multi_perform(c->multi, &running_handles);
		if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) {
			g_set_error(error_r, curl_quark(), mcode,
				    "curl_multi_perform() failed: %s",
				    curl_multi_strerror(mcode));
			c->eof = true;
			is->ready = true;
			return false;
		}

		bret = input_curl_multi_info_read(c, error_r);
		if (!bret)
			return false;
	}

	return !g_queue_is_empty(c->buffers);
}

/**
 * Mark a part of the buffer object as consumed.
 */
static struct buffer *
consume_buffer(struct buffer *buffer, size_t length)
{
	assert(buffer != NULL);
	assert(buffer->consumed < buffer->size);

	buffer->consumed += length;
	if (buffer->consumed < buffer->size)
		return buffer;

	assert(buffer->consumed == buffer->size);

	g_free(buffer);

	return NULL;
}
static Event* _schedulerpolicyhoststeal_pop(SchedulerPolicy* policy, SimulationTime barrier) {
    MAGIC_ASSERT(policy);
    HostStealPolicyData* data = policy->data;

    /* first, we try to pop a host from this thread's queue */
    g_rw_lock_reader_lock(&data->lock);
    HostStealThreadData* tdata = g_hash_table_lookup(data->threadToThreadDataMap, GUINT_TO_POINTER(pthread_self()));
    g_rw_lock_reader_unlock(&data->lock);

    /* if there is no tdata, that means this thread didn't get any hosts assigned to it */
    if(!tdata) {
        /* this thread will remain idle */
        return NULL;
    }

    /* we only need to lock this thread's lock, since it's our own queue */
    g_timer_continue(tdata->popIdleTime);
    g_mutex_lock(&(tdata->lock));
    g_timer_stop(tdata->popIdleTime);

    if(barrier > tdata->currentBarrier) {
        tdata->currentBarrier = barrier;

        /* make sure all of the hosts that were processed last time get processed in the next round */
        if(g_queue_is_empty(tdata->unprocessedHosts) && !g_queue_is_empty(tdata->processedHosts)) {
            GQueue* swap = tdata->unprocessedHosts;
            tdata->unprocessedHosts = tdata->processedHosts;
            tdata->processedHosts = swap;
        } else {
            while(!g_queue_is_empty(tdata->processedHosts)) {
                g_queue_push_tail(tdata->unprocessedHosts, g_queue_pop_head(tdata->processedHosts));
            }
        }
    }
    /* attempt to get an event from this thread's queue */
    Event* nextEvent = _schedulerpolicyhoststeal_popFromThread(policy, tdata, tdata->unprocessedHosts, barrier);
    g_mutex_unlock(&(tdata->lock));
    if(nextEvent != NULL) {
        return nextEvent;
    }

    /* no more hosts with events on this thread, try to steal a host from the other threads' queues */
    GHashTableIter iter;
    gpointer key, value;
    g_rw_lock_reader_lock(&data->lock);
    guint i, n = data->threadCount;
    g_rw_lock_reader_unlock(&data->lock);
    for(i = 1; i < n; i++) {
        guint stolenTnumber = (i + tdata->tnumber) % n;
        g_rw_lock_reader_lock(&data->lock);
        HostStealThreadData* stolenTdata = g_array_index(data->threadList, HostStealThreadData*, stolenTnumber);
        g_rw_lock_reader_unlock(&data->lock);
        /* We don't need a lock here, because we're only reading, and a misread just means either
         * we read as empty when it's not, in which case the assigned thread (or one of the others)
         * will pick it up anyway, or it reads as non-empty when it is empty, in which case we'll
         * just get a NULL event and move on. Accepting this reduces lock contention towards the end
         * of every round. */
        if(g_queue_is_empty(stolenTdata->unprocessedHosts)) {
            continue;
        }
        /* We need to lock the thread we're stealing from, to be sure that we're not stealing
         * something already being stolen, as well as our own lock, to be sure nobody steals
         * what we just stole. But we also need to do this in a well-ordered manner, to
         * prevent deadlocks. To do this, we always lock the lock with the smaller thread
         * number first. */
        g_timer_continue(tdata->popIdleTime);
        if(tdata->tnumber < stolenTnumber) {
            g_mutex_lock(&(tdata->lock));
            g_mutex_lock(&(stolenTdata->lock));
        } else {
            g_mutex_lock(&(stolenTdata->lock));
            g_mutex_lock(&(tdata->lock));
        }
        g_timer_stop(tdata->popIdleTime);

        /* attempt to get event from the other thread's queue, likely moving a host from its
         * unprocessedHosts into this threads runningHost (and eventually processedHosts) */
        nextEvent = _schedulerpolicyhoststeal_popFromThread(policy, tdata, stolenTdata->unprocessedHosts, barrier);

        /* must unlock in reverse order of locking */
        if(tdata->tnumber < stolenTnumber) {
            g_mutex_unlock(&(stolenTdata->lock));
            g_mutex_unlock(&(tdata->lock));
        } else {
            g_mutex_unlock(&(tdata->lock));
            g_mutex_unlock(&(stolenTdata->lock));
        }

        if(nextEvent != NULL) {
            break;
        }
    }
    return nextEvent;
}
Exemple #17
0
static bool
input_curl_seek(struct input_stream *is, goffset offset, int whence,
		GError **error_r)
{
	struct input_curl *c = (struct input_curl *)is;
	bool ret;

	assert(is->ready);

	if (whence == SEEK_SET && offset == is->offset)
		/* no-op */
		return true;

	if (!is->seekable)
		return false;

	/* calculate the absolute offset */

	switch (whence) {
	case SEEK_SET:
		break;

	case SEEK_CUR:
		offset += is->offset;
		break;

	case SEEK_END:
		if (is->size < 0)
			/* stream size is not known */
			return false;

		offset += is->size;
		break;

	default:
		return false;
	}

	if (offset < 0)
		return false;

	/* check if we can fast-forward the buffer */

	while (offset > is->offset && !g_queue_is_empty(c->buffers)) {
		struct buffer *buffer;
		size_t length;

		buffer = (struct buffer *)g_queue_pop_head(c->buffers);

		length = buffer->size - buffer->consumed;
		if (offset - is->offset < (goffset)length)
			length = offset - is->offset;

		buffer = consume_buffer(buffer, length);
		if (buffer != NULL)
			g_queue_push_head(c->buffers, buffer);

		is->offset += length;
	}

	if (offset == is->offset)
		return true;

	/* close the old connection and open a new one */

	input_curl_easy_free(c);

	is->offset = offset;
	if (is->offset == is->size) {
		/* seek to EOF: simulate empty result; avoid
		   triggering a "416 Requested Range Not Satisfiable"
		   response */
		c->eof = true;
		return true;
	}

	ret = input_curl_easy_init(c, error_r);
	if (!ret)
		return false;

	/* send the "Range" header */

	if (is->offset > 0) {
		c->range = g_strdup_printf("%lld-", (long long)is->offset);
		curl_easy_setopt(c->easy, CURLOPT_RANGE, c->range);
	}

	ret = input_curl_send_request(c, error_r);
	if (!ret)
		return false;

	return input_curl_multi_info_read(c, error_r);
}
Exemple #18
0
/* as-set/route-set expansion !ias-bar */
void irr_set_expand (irr_connection_t *irr, char *name)
{
    irr_database_t *database;
    time_t start_time;
    GArray *array;
    GQueue *stack;
    GHashTable *hash_member_examined;
    member_examined_hash_t *member_examined_ptr;
    LINKED_LIST *ll_setlist;
    char *set_name, *last_set_name, *mstr, *db;
    char *range_op, abuf[BUFSIZE];
    char *lasts = NULL;
    int i, first, dup, expand_flag = NO_EXPAND;
    hash_spec_t *hash_spec;

    if (strchr(name, ',') != NULL) {
        strtok_r(name, ",", &lasts);
        /* check if we are expanding a route-set */
        if ( (set_name = strchr(name, ':')) != NULL)
            set_name++;
        else
            set_name = name;
        if (!strncasecmp (set_name, "rs-", 3))
            expand_flag = ROUTE_SET_EXPAND;
        else
            expand_flag = OTHER_EXPAND;
    }

    start_time = time(NULL);
    convert_toupper (name);
    stack = g_queue_new();
    hash_member_examined = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)HashMemberExaminedDestroy);
    ll_setlist = LL_Create (LL_DestroyFunction, free, NULL);
    mstr = rpsl_macro_expand_add (" ", name, irr, NULL);
    g_queue_push_head(stack, mstr);
    member_examined_ptr = irrd_malloc(sizeof(member_examined_hash_t));
    member_examined_ptr->key = strdup(name);
    g_hash_table_insert(hash_member_examined, member_examined_ptr->key, member_examined_ptr);

    while (!g_queue_is_empty(stack)) {
        if ( IRR.expansion_timeout > 0 ) {
            if ( (time(NULL) - start_time) > IRR.expansion_timeout ) {
                trace (ERROR, default_trace, "irr_set_expand(): Set expansion timeout\n");
                sprintf(abuf, "Expansion maximum CPU time exceeded: %d seconds", IRR.expansion_timeout);
                irr_send_error(irr, abuf);
                goto getout;
            }
        }
        mstr = (char *) g_queue_pop_head(stack);
        /* might want to check the examined list to see if this set name
           has been examined already */
        first = 1;
        lasts = NULL;
        range_op = strtok_r (mstr, ",", &lasts);
        if (!strcmp (range_op, " ")) range_op = NULL;
        set_name = strtok_r (NULL, ",", &lasts);

        irr_lock_all(irr); /* lock db's while searching */
        while ((db = strtok_r (NULL, ",", &lasts)) != NULL) {
            if ((database = find_database (db)) == NULL) {
                trace (ERROR, default_trace, "irr_set_expand(): Database not found %s\n", db);
                sprintf(abuf, "Database not found: %s", db);
                irr_send_error(irr, abuf);
                goto getout;
            }
            make_setobj_key (abuf, set_name);
            if ((hash_spec = fetch_hash_spec (database, abuf, UNPACK)) != NULL) {
                first = 0;
                update_members_list (database, range_op, AF_INET, expand_flag,
                                     hash_member_examined, ll_setlist, hash_spec->ll_1,
                                     stack, irr);
                mbrs_by_ref_set (database, range_op, AF_INET, expand_flag, ll_setlist,
                                 set_name, hash_spec->ll_2, irr);
                Delete_hash_spec (hash_spec);
            }
            if (first == 0)
                break;
        }
        irr_unlock_all(irr);
        free (mstr);
    }

    first = 1;
    dup = 0;
    i = 0;
    last_set_name = "";
    array = g_array_sized_new(FALSE, TRUE, sizeof(char*), ll_setlist->count);
    LL_ContIterate (ll_setlist, set_name) {
        g_array_append_val(array, set_name);
    }
void
e_mail_formatter_format_security_header (EMailFormatter *formatter,
                                         EMailFormatterContext *context,
                                         GString *buffer,
                                         EMailPart *part,
                                         guint32 flags)
{
	const gchar* part_id;
	gchar* part_id_prefix;
	GString* tmp;
	GQueue queue = G_QUEUE_INIT;
	GList *head, *link;

	g_return_if_fail (E_IS_MAIL_PART_HEADERS (part));

	/* Get prefix of this PURI */
	part_id = e_mail_part_get_id (part);
	part_id_prefix = g_strndup (part_id, g_strrstr (part_id, ".") - part_id);

	/* Add encryption/signature header */
	tmp = g_string_new ("");

	e_mail_part_list_queue_parts (context->part_list, NULL, &queue);

	head = g_queue_peek_head_link (&queue);

	/* Find first secured part. */
	for (link = head; link != NULL; link = g_list_next(link)) {
		EMailPart *mail_part = link->data;

		if (!e_mail_part_has_validity (mail_part))
			continue;

		if (!e_mail_part_id_has_prefix (mail_part, part_id_prefix))
			continue;

		if (e_mail_part_get_validity (mail_part, E_MAIL_PART_VALIDITY_PGP | E_MAIL_PART_VALIDITY_SIGNED)) {
			g_string_append (tmp, _("GPG signed"));
		}

		if (e_mail_part_get_validity (mail_part, E_MAIL_PART_VALIDITY_PGP | E_MAIL_PART_VALIDITY_ENCRYPTED)) {
			if (tmp->len > 0)
				g_string_append (tmp, ", ");
			g_string_append (tmp, _("GPG encrypted"));
		}

		if (e_mail_part_get_validity (mail_part, E_MAIL_PART_VALIDITY_SMIME | E_MAIL_PART_VALIDITY_SIGNED)) {
			if (tmp->len > 0)
				g_string_append (tmp, ", ");
			g_string_append (tmp, _("S/MIME signed"));
		}

		if (e_mail_part_get_validity (mail_part, E_MAIL_PART_VALIDITY_SMIME | E_MAIL_PART_VALIDITY_ENCRYPTED)) {
			if (tmp->len > 0)
				g_string_append (tmp, ", ");
			g_string_append (tmp, _("S/MIME encrypted"));
		}

		break;
	}

	if (tmp->len > 0) {
		e_mail_formatter_format_header (
			formatter, buffer,
			_("Security"), tmp->str,
			flags,
			"UTF-8");
	}

	while (!g_queue_is_empty (&queue))
		g_object_unref (g_queue_pop_head (&queue));

	g_string_free (tmp, TRUE);
	g_free (part_id_prefix);
}
Exemple #20
0
void
gs_shell_change_mode (GsShell *shell,
		      GsShellMode mode,
		      GsApp *app,
		      gpointer data,
		      gboolean scroll_up)
{
	GsShellPrivate *priv = gs_shell_get_instance_private (shell);
	GsPage *new_page;
	GtkWidget *widget;
	const gchar *text;
	GtkStyleContext *context;

	if (priv->ignore_primary_buttons)
		return;

	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "header"));
	gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (widget), TRUE);

	/* hide all mode specific header widgets here, they will be shown in the
	 * refresh functions
	 */
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "application_details_header"));
	gtk_widget_hide (widget);
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "buttonbox_main"));
	gtk_widget_hide (widget);
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "header_selection_menu_button"));
	gtk_widget_hide (widget);
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "search_bar"));
	gtk_widget_hide (widget);

	context = gtk_widget_get_style_context (GTK_WIDGET (gtk_builder_get_object (priv->builder, "header")));
	gtk_style_context_remove_class (context, "selection-mode");
	/* set the window title back to default */
	/* TRANSLATORS: this is the main window title */
	gtk_window_set_title (priv->main_window, _("Software"));

	/* show the back button if needed */
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_back"));
	gtk_widget_set_visible (widget, !g_queue_is_empty (priv->back_entry_stack));

	/* update main buttons according to mode */
	priv->ignore_primary_buttons = TRUE;
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_all"));
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), mode == GS_SHELL_MODE_OVERVIEW);

	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_installed"));
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), mode == GS_SHELL_MODE_INSTALLED);

	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_updates"));
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), mode == GS_SHELL_MODE_UPDATES);
	gtk_widget_set_visible (widget, !gs_update_monitor_is_managed() || mode == GS_SHELL_MODE_UPDATES);

	priv->ignore_primary_buttons = FALSE;

	/* switch page */
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "stack_main"));
	gtk_stack_set_visible_child_name (GTK_STACK (widget), page_name[mode]);

	/* do action for mode */
	priv->mode = mode;
	switch (mode) {
	case GS_SHELL_MODE_OVERVIEW:
		new_page = GS_PAGE (priv->shell_overview);
		break;
	case GS_SHELL_MODE_INSTALLED:
		new_page = GS_PAGE (priv->shell_installed);
		break;
	case GS_SHELL_MODE_MODERATE:
		new_page = GS_PAGE (priv->shell_moderate);
		break;
	case GS_SHELL_MODE_SEARCH:
		widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "entry_search"));
		text = gtk_entry_get_text (GTK_ENTRY (widget));
		gs_shell_search_set_text (priv->shell_search, text);
		new_page = GS_PAGE (priv->shell_search);
		break;
	case GS_SHELL_MODE_UPDATES:
		new_page = GS_PAGE (priv->shell_updates);
		break;
	case GS_SHELL_MODE_DETAILS:
		if (app != NULL)
			gs_shell_details_set_app (priv->shell_details, app);
		if (data != NULL)
			gs_shell_details_set_filename (priv->shell_details, data);
		new_page = GS_PAGE (priv->shell_details);
		break;
	case GS_SHELL_MODE_CATEGORY:
		gs_shell_category_set_category (priv->shell_category,
						GS_CATEGORY (data));
		new_page = GS_PAGE (priv->shell_category);
		break;
	case GS_SHELL_MODE_EXTRAS:
		new_page = GS_PAGE (priv->shell_extras);
		break;
	default:
		g_assert_not_reached ();
	}

	gs_page_switch_to (new_page, scroll_up);

	/* update header bar widgets */
	widget = gs_page_get_header_start_widget (new_page);
	gs_shell_set_header_start_widget (shell, widget);

	widget = gs_page_get_header_end_widget (new_page);
	gs_shell_set_header_end_widget (shell, widget);

	/* destroy any existing modals */
	if (priv->modal_dialogs != NULL)
		g_ptr_array_set_size (priv->modal_dialogs, 0);
}
void
ephy_session_undo_close_tab (EphySession *session)
{
	EphySessionPrivate *priv;
	EphyEmbed *embed, *new_tab;
	ClosedTab *tab;
#ifndef HAVE_WEBKIT2
	WebKitWebBackForwardList *dest;
	GList *i;
#endif
	EphyNewTabFlags flags = EPHY_NEW_TAB_OPEN_PAGE
		| EPHY_NEW_TAB_PRESENT_WINDOW
		| EPHY_NEW_TAB_JUMP
		| EPHY_NEW_TAB_DONT_COPY_HISTORY;

	g_return_if_fail (EPHY_IS_SESSION (session));

	priv = session->priv;

	tab = g_queue_pop_head (priv->closed_tabs);
	if (tab == NULL)
		return;

	LOG ("UNDO CLOSE TAB: %s", tab->url);
	if (*tab->parent_location != NULL)
	{
		GtkWidget *window;

		flags |= EPHY_NEW_TAB_IN_EXISTING_WINDOW;

		if (tab->position > 0)
		{
			/* Append in the n-th position. */
			embed = EPHY_EMBED (gtk_notebook_get_nth_page (GTK_NOTEBOOK (*tab->parent_location),
								       tab->position - 1));
			flags |= EPHY_NEW_TAB_APPEND_AFTER;
		}
		else
		{
			/* Just prepend in the first position. */
			embed = NULL;
			flags |= EPHY_NEW_TAB_FIRST;
		}

		window = gtk_widget_get_toplevel (GTK_WIDGET (*tab->parent_location));
		new_tab = ephy_shell_new_tab (ephy_shell_get_default (),
					      EPHY_WINDOW (window), embed, tab->url,
					      flags);
		post_restore_cleanup (priv->closed_tabs, tab, FALSE);
	}
	else
	{
		EphyNotebook *notebook;
		flags |=  EPHY_NEW_TAB_IN_NEW_WINDOW;
		new_tab = ephy_shell_new_tab (ephy_shell_get_default (),
					      NULL, NULL, tab->url, flags);

		/* FIXME: This makes the assumption that the notebook
		   is the parent of the returned EphyEmbed. */
		notebook = EPHY_NOTEBOOK (gtk_widget_get_parent (GTK_WIDGET (new_tab)));
		*tab->parent_location = notebook;
		post_restore_cleanup (priv->closed_tabs, tab, TRUE);
	}

	/* This is deficient: we need to recreate the whole
	 * BackForward list. Also, WebKit2 doesn't have this API. */
#ifndef HAVE_WEBKIT2
	dest = webkit_web_view_get_back_forward_list (EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (new_tab));
	for (i = tab->bflist; i; i = i->next)
	{
		LOG ("ADDING TO BF: %s",
		     webkit_web_history_item_get_title ((WebKitWebHistoryItem*) i->data));
		webkit_web_back_forward_list_add_item (dest,
						       webkit_web_history_item_copy ((WebKitWebHistoryItem*) i->data));
	}
#endif
	closed_tab_free (tab);

	if (g_queue_is_empty (priv->closed_tabs))
		g_object_notify (G_OBJECT (session), "can-undo-tab-closed");
}
static void
mail_formatter_print_run (EMailFormatter *formatter,
                          EMailFormatterContext *context,
                          GOutputStream *stream,
                          GCancellable *cancellable)
{
	GQueue queue = G_QUEUE_INIT;
	GQueue attachments = G_QUEUE_INIT;
	GList *head, *link;
	const gchar *string;

	context->mode = E_MAIL_FORMATTER_MODE_PRINTING;

	string =
		"<!DOCTYPE HTML>\n"
		"<html>\n"
		"<head>\n"
		"<meta name=\"generator\" content=\"Evolution Mail\" />\n"
		"<title>Evolution Mail Display</title>\n"
		"<link type=\"text/css\" rel=\"stylesheet\" "
		"      media=\"print\" href=\"" STYLESHEET_URI "/>\n"
		"</head>\n"
		"<body style=\"background: #FFF; color: #000;\">";

	g_output_stream_write_all (
		stream, string, strlen (string), NULL, cancellable, NULL);

	e_mail_part_list_queue_parts (context->part_list, NULL, &queue);

	head = g_queue_peek_head_link (&queue);

	for (link = head; link != NULL; link = g_list_next (link)) {
		EMailPart *part = E_MAIL_PART (link->data);
		const gchar *mime_type;
		gboolean ok;

		if (g_cancellable_is_cancelled (cancellable))
			break;

		if (part->is_hidden && !part->is_error) {
			if (e_mail_part_id_has_suffix (part, ".rfc822")) {
				link = e_mail_formatter_find_rfc822_end_iter (link);
			}

			continue;
		}

		mime_type = e_mail_part_get_mime_type (part);
		if (mime_type == NULL)
			continue;

		if (e_mail_part_get_is_attachment (part)) {
			if (e_mail_part_get_cid (part) != NULL)
				continue;

			g_queue_push_tail (&attachments, part);
		}

		ok = e_mail_formatter_format_as (
			formatter, context, part, stream,
			mime_type, cancellable);

		/* If the written part was message/rfc822 then
		 * jump to the end of the message, because content
		 * of the whole message has been formatted by
		 * message_rfc822 formatter */
		if (ok && e_mail_part_id_has_suffix (part, ".rfc822")) {
			link = e_mail_formatter_find_rfc822_end_iter (link);

			continue;
		}
	}

	while (!g_queue_is_empty (&queue))
		g_object_unref (g_queue_pop_head (&queue));

	/* This consumes the attachments queue. */
	if (!g_queue_is_empty (&attachments))
		mail_formatter_print_write_attachments (
			formatter, &attachments,
			stream, cancellable);

	string = "</body></html>";

	g_output_stream_write_all (
		stream, string, strlen (string),
		NULL, cancellable, NULL);
}
Exemple #23
0
int owl_global_messagequeue_pending(owl_global *g)
{
  return !g_queue_is_empty(g->messagequeue);
}
static void
mail_formatter_print_write_attachments (EMailFormatter *formatter,
                                        GQueue *attachments,
                                        GOutputStream *stream,
                                        GCancellable *cancellable)
{
	GString *str;

	str = g_string_new (
		"<table border=\"0\" cellspacing=\"5\" cellpadding=\"0\" "
		"class=\"attachments-list\" >\n");
	g_string_append_printf (
		str,
		"<tr><th colspan=\"2\"><h1>%s</h1></td></tr>\n"
		"<tr><th>%s</th><th>%s</th></tr>\n",
		_("Attachments"), _("Name"), _("Size"));

	while (!g_queue_is_empty (attachments)) {
		EMailPartAttachment *part;
		EAttachment *attachment;
		GFileInfo *file_info;
		const gchar *display_name;
		gchar *description;
		gchar *name;
		gchar *size;

		part = g_queue_pop_head (attachments);
		attachment = e_mail_part_attachment_ref_attachment (part);

		file_info = e_attachment_ref_file_info (attachment);
		if (file_info == NULL) {
			g_object_unref (attachment);
			continue;
		}

		description = e_attachment_dup_description (attachment);
		display_name = g_file_info_get_display_name (file_info);

		if (description != NULL && *description != '\0') {
			name = g_strdup_printf (
				"%s (%s)", description, display_name);
		} else {
			name = g_strdup (display_name);
		}

		size = g_format_size (g_file_info_get_size (file_info));

		g_string_append_printf (
			str, "<tr><td>%s</td><td>%s</td></tr>\n",
			name, size);

		g_free (description);
		g_free (name);
		g_free (size);

		g_object_unref (attachment);
		g_object_unref (file_info);
	}

	g_string_append (str, "</table>\n");

	g_output_stream_write_all (
		stream, str->str, str->len, NULL, cancellable, NULL);

	g_string_free (str, TRUE);
}
Exemple #25
0
static GstFlowReturn
gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
{
  GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc);
  GstFlowReturn flow_ret = GST_FLOW_OK;
  const guint8 *data;
  gsize data_size;
  VideoFrame *vf;
  CaptureFrame *f;
  GstCaps *caps;
  gboolean caps_changed = FALSE;

  g_mutex_lock (&self->lock);
  while (g_queue_is_empty (&self->current_frames) && !self->flushing) {
    g_cond_wait (&self->cond, &self->lock);
  }

  f = (CaptureFrame *) g_queue_pop_head (&self->current_frames);
  g_mutex_unlock (&self->lock);

  if (self->flushing) {
    if (f)
      capture_frame_free (f);
    GST_DEBUG_OBJECT (self, "Flushing");
    return GST_FLOW_FLUSHING;
  }
  // If we're not flushing, we should have a valid frame from the queue
  g_assert (f != NULL);

  g_mutex_lock (&self->lock);
  if (self->caps_mode != f->mode) {
    if (self->mode == GST_DECKLINK_MODE_AUTO) {
      GST_DEBUG_OBJECT (self, "Mode changed from %d to %d", self->caps_mode,
          f->mode);
      caps_changed = TRUE;
      self->caps_mode = f->mode;
    } else {
      g_mutex_unlock (&self->lock);
      GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
          ("Invalid mode in captured frame"),
          ("Mode set to %d but captured %d", self->caps_mode, f->mode));
      capture_frame_free (f);
      return GST_FLOW_NOT_NEGOTIATED;
    }
  }
  if (self->caps_format != f->format) {
    if (self->video_format == GST_DECKLINK_VIDEO_FORMAT_AUTO) {
      GST_DEBUG_OBJECT (self, "Format changed from %d to %d", self->caps_format,
          f->format);
      caps_changed = TRUE;
      self->caps_format = f->format;
    } else {
      g_mutex_unlock (&self->lock);
      GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
          ("Invalid pixel format in captured frame"),
          ("Format set to %d but captured %d", self->caps_format, f->format));
      capture_frame_free (f);
      return GST_FLOW_NOT_NEGOTIATED;
    }
  }

  g_mutex_unlock (&self->lock);
  if (caps_changed) {
    caps = gst_decklink_mode_get_caps (f->mode, f->format);
    gst_video_info_from_caps (&self->info, caps);
    gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps);
    gst_element_post_message (GST_ELEMENT_CAST (self),
        gst_message_new_latency (GST_OBJECT_CAST (self)));
    gst_caps_unref (caps);

  }

  f->frame->GetBytes ((gpointer *) & data);
  data_size = self->info.size;

  vf = (VideoFrame *) g_malloc0 (sizeof (VideoFrame));

  *buffer =
      gst_buffer_new_wrapped_full ((GstMemoryFlags) GST_MEMORY_FLAG_READONLY,
      (gpointer) data, data_size, 0, data_size, vf,
      (GDestroyNotify) video_frame_free);

  vf->frame = f->frame;
  f->frame->AddRef ();
  vf->input = self->input->input;
  vf->input->AddRef ();

  GST_BUFFER_TIMESTAMP (*buffer) = f->capture_time;
  GST_BUFFER_DURATION (*buffer) = f->capture_duration;
  gst_buffer_add_video_time_code_meta (*buffer, f->tc);

  GST_DEBUG_OBJECT (self,
      "Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %"
      GST_TIME_FORMAT, *buffer, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*buffer)),
      GST_TIME_ARGS (GST_BUFFER_DURATION (*buffer)));

  capture_frame_free (f);

  return flow_ret;
}
Exemple #26
0
static GList*
get_file_actions(ThunarxMenuProvider* provider, GtkWidget* window, GList* files) {
  GList* actions = 0;
  
  if(files != 0) {
    GtkIconTheme* theme = gtk_icon_theme_get_default();
    guint n = g_list_length(files);
    gchar* three_way_compare_command;
    xdiff_ext_preferences* p = xdiff_ext_preferences_instance();

    g_object_get(G_OBJECT(p), "three-way-compare-command", &three_way_compare_command, NULL);

    g_object_unref(p);
     
    GList* scan = files;
    gboolean go = TRUE;
    
    while(scan && go) {
      gchar* scheme;

      scheme = thunarx_file_info_get_uri_scheme((ThunarxFileInfo*)(scan->data));
      go = strncmp(scheme, "file", 4) == 0;
      g_free(scheme);
      
      scan = g_list_next(scan);
    }
    
    if(go) {
      GtkAction* action = gtk_action_new("xdiff-ext::save", _("Compare later"), _("Select file for comparison"), DIFF_EXT_DATA_DIR"/icons/hicolor/16x16/actions/diff_later.png");
      g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(compare_later), window);
      g_object_set_data_full(G_OBJECT(action), "xdiff-ext::save", thunarx_file_info_list_copy(files),(GDestroyNotify)thunarx_file_info_list_free);
      actions = g_list_append(actions, action);
      
      if(n == 1) {
        if(!g_queue_is_empty(_saved)) {
          GString* caption = g_string_new("");
          GString* hint = g_string_new("");
          GList* head = g_queue_peek_head_link(_saved);
          gchar* head_file = (gchar*)head->data;
          ThunarVfsInfo* vfs_info = NULL;
          ThunarVfsPath* vfs_path = NULL;
          const gchar* icon_name;
          
          gchar* uri;
          gchar* path;

          uri = thunarx_file_info_get_uri((ThunarxFileInfo*)files->data);
          path = g_filename_from_uri(uri, NULL, NULL);
          g_free(uri);
          
          g_string_printf(caption,_("Compare to '%s'"), head_file);
          g_string_printf(hint, _("Compare '%s' and '%s'"), path, head_file);
          
          vfs_path = thunar_vfs_path_new(head_file, NULL);
          vfs_info = thunar_vfs_info_new_for_path(vfs_path, NULL);
          icon_name = thunar_vfs_info_get_custom_icon(vfs_info);
          if(icon_name == NULL) {
            icon_name = thunar_vfs_mime_info_lookup_icon_name(vfs_info->mime_info, theme);
          }
          
          g_message("icon name: '%s'", icon_name);
          thunar_vfs_path_unref(vfs_path);
          thunar_vfs_info_unref(vfs_info);
          
          action = gtk_action_new("xdiff-ext::compare_to", caption->str, hint->str, "gaim.png");
          g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(compare_to), window);
          g_object_set_data_full(G_OBJECT(action), "xdiff-ext::compare_to", thunarx_file_info_list_copy(files),(GDestroyNotify)thunarx_file_info_list_free);
          g_object_set_data(G_OBJECT(action), "xdiff-ext::saved", head);
          actions = g_list_append(actions, action);
          
          if(_saved->length > 1) {
            add_compare_to_menu(actions, window, files, _("Compare to"), make_hint, G_CALLBACK(compare_to), path);
          }
          
          g_string_free(caption, TRUE);
          g_string_free(hint, TRUE);
        }
      } else if(n == 2) {
        GtkAction* action = gtk_action_new("xdiff-ext::compare", _("Compare"), _("Compare selected files"), "diff");
        g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(compare), window);
        g_object_set_data_full(G_OBJECT(action), "xdiff-ext::compare", thunarx_file_info_list_copy(files),(GDestroyNotify)thunarx_file_info_list_free);
        actions = g_list_append(actions, action);

        if(strcmp("", three_way_compare_command) != 0) {
          if(!g_queue_is_empty(_saved)) {
            GString* caption = g_string_new("");
            GString* hint = g_string_new("");
            GList* head = g_queue_peek_head_link(_saved);
            gchar* head_file = (gchar*)head->data;
            gchar* uri;
            gchar* path1;
            gchar* path2;

            uri = thunarx_file_info_get_uri((ThunarxFileInfo*)files->data);
            path1 = g_filename_from_uri(uri, NULL, NULL);
            g_free(uri);
            files = g_list_next(files);
            uri = thunarx_file_info_get_uri((ThunarxFileInfo*)files->data);
            path2 = g_filename_from_uri(uri, NULL, NULL);
            g_free(uri);
            
            g_string_printf(caption, _("3-way compare to '%s'"), head_file);
            g_string_printf(hint, _("3-way compare '%s', '%s' and '%s'"), path1, path2, head_file);
            
            action = gtk_action_new("xdiff-ext::compare_to", caption->str, hint->str, "diff3_with");
            g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(compare3_to), window);
            g_object_set_data_full(G_OBJECT(action), "xdiff-ext::compare_to", thunarx_file_info_list_copy(files),(GDestroyNotify)thunarx_file_info_list_free);
            g_object_set_data(G_OBJECT(action), "xdiff-ext::saved", head);
            actions = g_list_append(actions, action);

            if(_saved->length > 1) {
              add_compare_to_menu(actions, window, files, _("3-way compare to"), make_hint3, G_CALLBACK(compare3_to), path1, path2);
            }
            
            g_string_free(caption, TRUE);
            g_string_free(hint, TRUE);
          }
        }
      } else if(n == 3) {
        if(strcmp("", three_way_compare_command) != 0) {
          GtkAction* action = gtk_action_new("xdiff-ext::compare3", _("3-way Compare"), _("Compare selected files"), "diff3");
          g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(compare3), window);
          g_object_set_data_full(G_OBJECT(action), "xdiff-ext::compare3", thunarx_file_info_list_copy(files),(GDestroyNotify)thunarx_file_info_list_free);
          actions = g_list_append(actions, action);
        }
      }
    }
    
    g_free(three_way_compare_command);
  }
          
  return actions;
}
Exemple #27
0
/* thumbnail_thread is invoked as a separate thread to to make thumbnails. */
static void
thumbnail_thread_func (GTask        *task,
                       gpointer      source_object,
                       gpointer      task_data,
                       GCancellable *cancellable)
{
    CajaThumbnailInfo *info = NULL;
    GdkPixbuf *pixbuf;
    time_t current_orig_mtime = 0;
    time_t current_time;
    GList *node;

    /* We loop until there are no more thumbails to make, at which point
       we exit the thread. */
    for (;;)
    {
#ifdef DEBUG_THUMBNAILS
        g_message ("(Thumbnail Thread) Locking mutex\n");
#endif
        g_mutex_lock (&thumbnails_mutex);

        /*********************************
         * MUTEX LOCKED
         *********************************/

        /* Pop the last thumbnail we just made off the head of the
           list and free it. I did this here so we only have to lock
           the mutex once per thumbnail, rather than once before
           creating it and once after.
           Don't pop the thumbnail off the queue if the original file
           mtime of the request changed. Then we need to redo the thumbnail.
        */
        if (currently_thumbnailing &&
                currently_thumbnailing->original_file_mtime == current_orig_mtime)
        {
            g_assert (info == currently_thumbnailing);
            node = g_hash_table_lookup (thumbnails_to_make_hash, info->image_uri);
            g_assert (node != NULL);
            g_hash_table_remove (thumbnails_to_make_hash, info->image_uri);
            free_thumbnail_info (info);
            g_queue_delete_link ((GQueue *)&thumbnails_to_make, node);
        }
        currently_thumbnailing = NULL;

        /* If there are no more thumbnails to make, reset the
           thumbnail_thread_is_running flag, unlock the mutex, and
           exit the thread. */
        if (g_queue_is_empty ((GQueue *)&thumbnails_to_make))
        {
#ifdef DEBUG_THUMBNAILS
            g_message ("(Thumbnail Thread) Exiting\n");
#endif
            thumbnail_thread_is_running = FALSE;
            g_mutex_unlock (&thumbnails_mutex);
            return;
        }

        /* Get the next one to make. We leave it on the list until it
           is created so the main thread doesn't add it again while we
           are creating it. */
        info = g_queue_peek_head ((GQueue *)&thumbnails_to_make);
        currently_thumbnailing = info;
        current_orig_mtime = info->original_file_mtime;
        /*********************************
         * MUTEX UNLOCKED
         *********************************/

#ifdef DEBUG_THUMBNAILS
        g_message ("(Thumbnail Thread) Unlocking mutex\n");
#endif
        g_mutex_unlock (&thumbnails_mutex);

        time (&current_time);

        /* Don't try to create a thumbnail if the file was modified recently.
           This prevents constant re-thumbnailing of changing files. */
        if (current_time < current_orig_mtime + THUMBNAIL_CREATION_DELAY_SECS &&
                current_time >= current_orig_mtime)
        {
#ifdef DEBUG_THUMBNAILS
            g_message ("(Thumbnail Thread) Skipping: %s\n",
                       info->image_uri);
#endif
            /* Reschedule thumbnailing via a change notification */
            g_timeout_add_seconds (1, thumbnail_thread_notify_file_changed,
                                   g_strdup (info->image_uri));
            continue;
        }

        /* Create the thumbnail. */
#ifdef DEBUG_THUMBNAILS
        g_message ("(Thumbnail Thread) Creating thumbnail: %s\n",
                   info->image_uri);
#endif

        pixbuf = mate_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory,
                 info->image_uri,
                 info->mime_type);

        if (pixbuf)
        {
#ifdef DEBUG_THUMBNAILS
			g_message ("(Thumbnail Thread) Saving thumbnail: %s\n",
				   info->image_uri);
#endif
            mate_desktop_thumbnail_factory_save_thumbnail (thumbnail_factory,
                    pixbuf,
                    info->image_uri,
                    current_orig_mtime);
            g_object_unref (pixbuf);
        }
        else
        {
#ifdef DEBUG_THUMBNAILS
			g_message ("(Thumbnail Thread) Thumbnail failed: %s\n",
				   info->image_uri);
#endif
            mate_desktop_thumbnail_factory_create_failed_thumbnail (thumbnail_factory,
                    info->image_uri,
                    current_orig_mtime);
        }
        /* We need to call caja_file_changed(), but I don't think that is
           thread safe. So add an idle handler and do it from the main loop. */
        g_idle_add_full (G_PRIORITY_HIGH_IDLE,
                         thumbnail_thread_notify_file_changed,
                         g_strdup (info->image_uri), NULL);
    }
}
Exemple #28
0
void
clear_queue(GQueue* queue) {
  while(!g_queue_is_empty(queue)) {
    g_queue_pop_head(queue);
  }
}
Exemple #29
0
static gssize
socket_send_message (NiceSocket *sock, const NiceOutputMessage *message)
{
  TcpPriv *priv = sock->priv;
  gssize ret;
  GError *gerr = NULL;
  gsize message_len;

  /* Don't try to access the socket if it had an error, otherwise we risk a
   * crash with SIGPIPE (Broken pipe) */
  if (priv->error)
    return -1;

  message_len = output_message_get_size (message);

  /* First try to send the data, don't send it later if it can be sent now
   * this way we avoid allocating memory on every send */
  if (g_queue_is_empty (&priv->send_queue)) {
    ret = g_socket_send_message (sock->fileno, NULL, message->buffers,
        message->n_buffers, NULL, 0, G_SOCKET_MSG_NONE, NULL, &gerr);

    if (ret < 0) {
      if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) ||
          g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_FAILED)) {
        /* Queue the message and send it later. */
        add_to_be_sent (sock, message, 0, message_len, FALSE);
        ret = message_len;
      }

      g_error_free (gerr);
    } else if ((gsize) ret < message_len) {
      /* Partial send. */
      add_to_be_sent (sock, message, ret, message_len, TRUE);
      ret = message_len;
    }
  } else {
    /* FIXME: This dropping will break http/socks5/etc
     * We probably need a way to the upper layer to control reliability
     */
    /* If the queue is too long, drop whatever packets we can. */
    if (g_queue_get_length (&priv->send_queue) >= MAX_QUEUE_LENGTH) {
      guint peek_idx = 0;
      struct to_be_sent *tbs = NULL;

      while ((tbs = g_queue_peek_nth (&priv->send_queue, peek_idx)) != NULL) {
        if (tbs->can_drop) {
          tbs = g_queue_pop_nth (&priv->send_queue, peek_idx);
          free_to_be_sent (tbs);
          break;
        } else {
          peek_idx++;
        }
      }
    }

    /* Queue the message and send it later. */
    add_to_be_sent (sock, message, 0, message_len, FALSE);
    ret = message_len;
  }

  return ret;
}
void server_wait(server *s)
{
	int maxfd = s->socket;
	fd_set rfds;
	FD_ZERO(&rfds);
	FD_SET(s->socket, &rfds);

	GList *i;
	for (i = s->connections; i != NULL; i = i->next)
	{
		connection *c = (connection *)i->data;
		int fd = connection_socket(c);
		if (fd > maxfd) maxfd = fd;
		FD_SET(fd, &rfds);
	}

	struct timeval tv;
	tv.tv_sec = TIMEOUT_SEC;
	tv.tv_usec = TIMEOUT_USEC;
	int status = select(maxfd + 1, &rfds, NULL, NULL, &tv);

	if (status > 0)
	{
		if (FD_ISSET(s->socket, &rfds))
		{
			if (!g_queue_is_empty(s->free_connections))
			{
				connection *c = (connection *)g_queue_pop_head(s->free_connections);
				s->connections = g_list_append(s->connections, c);

				connection_accept(c, s->socket);
				if (connection_socket(c) == 0) halt_error("Socket accept really shouldn't fail");
			}
		}

		GList *j = s->connections;
		while (j != NULL)
		{
			GList *next = j->next;

			connection *c = (connection *)j->data;
			if (FD_ISSET(connection_socket(c), &rfds))
			{
				if (connection_receive(c))
				{
					j->data = NULL;
					s->connections = g_list_delete_link(s->connections, j);
					g_queue_push_tail(s->free_connections, c);
				}
			}

			j = next;
		}
	}
	else if (status == 0)
	{
		// connection timeout
		GList *j = s->connections;
		while (j != NULL)
		{
			GList *next = j->next;

			connection *c = (connection *)j->data;
			connection_timeout_increment(c, TIMEOUT_SEC + (((float)TIMEOUT_USEC) / 1000000.0f));

			if (connection_timedout(c))
			{
				j->data = NULL;
				s->connections = g_list_delete_link(s->connections, j);
				g_queue_push_tail(s->free_connections, c);
			}

			j = next;
		}
	}
	else
	{
		// TODO: Don't know if this is ever a fatal error
		//halt_error("Error in socket select");
		return;
	}
}