コード例 #1
0
static gboolean
gst_ss_demux_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
{
  GstSSDemuxStream *stream = (GstSSDemuxStream *)data;
  GstSSDemux *demux = stream->parent;

  switch (GST_MESSAGE_TYPE(msg)) {
    case GST_MESSAGE_EOS: {
      guint64 download_rate = -1;

      GST_INFO_OBJECT (stream->pad, "received EOS on download pipe..");
      // increase the fragment count on EOS
      stream->frag_cnt++;

      if (g_strrstr (gst_element_get_name(stream->urisrc), "http")) {
        g_object_get (stream->urisrc, "download-rate", &download_rate, NULL);
        g_print("*********** '%s' download rate = %d bps **************\n", stream->name, download_rate);
      }

      // TODO: need to remove download_rate> 0 check.. make it generic
      if ((stream->type == SS_STREAM_VIDEO) && (demux->ss_mode != SS_MODE_AONLY) && (download_rate >= 0)) {
        if (stream->frag_cnt >= demux->fragments_cache) {
          /* for switching, we are considering video download rate only */
          demux->ss_mode = gst_ssm_parse_switch_qualitylevel (demux->parser, download_rate);
        }
      } else if (stream->type == SS_STREAM_AUDIO && (demux->ss_mode == SS_MODE_AONLY)) {
        /* when video is not present using audio download rate to calculate switching */
         demux->ss_mode = gst_ssm_parse_switch_qualitylevel (demux->parser, download_rate);
         if (demux->ss_mode != SS_MODE_AONLY) {
           g_print ("\n\nMoving to AV mode by audio considering audio download rate\n\n\n\n");
         }
      }

      g_cond_signal (stream->cond);

#ifdef SIMULATE_AUDIO_ONLY
      /* when fragment count is multiple of 4, switch to audio only case */
      if ((stream->frag_cnt % 4 == 0) && (stream->type == SS_STREAM_VIDEO) &&
	  	GST_SSM_PARSE_IS_LIVE_PRESENTATION(demux->parser)) {
        g_print ("\n\t ######## Forcibly switching to audio only for testing ##########\n");
        demux->ss_mode = SS_MODE_AONLY;
      }
  #endif
      GST_DEBUG_OBJECT (stream->pad, "Signalling eos condition...");

      GST_DEBUG_OBJECT (demux, "number of fragments downloaded = %d", stream->frag_cnt);
      break;
    }
    case GST_MESSAGE_ERROR: {
      GError *error = NULL;
      gchar* debug = NULL;

      g_print ("Error from %s\n", gst_element_get_name (GST_MESSAGE_SRC(msg)));

      gst_message_parse_error( msg, &error, &debug );
      if (error)
        GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: error= %s\n", error->message);

      GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: debug = %s\n", debug);

      /* handling error, when client requests url, which is yet to be prepared by server */
      if ((!strncmp(error->message, "Precondition Failed", strlen("Precondition Failed"))) && (5 == error->code)) {
        GstStateChangeReturn ret;

        /* wait for 1sec & request the url again */
        // TODO: need to make wait time as generic or Adding loop count to request again & again
        GST_INFO_OBJECT (demux, "ERROR : code = %d, msg = %s, NEED to request again", error->code, error->message);
        usleep (1000000); // 1 sec

        /* put the current pipeline to NULL state */
        gst_element_set_state (stream->pipe, GST_STATE_NULL);
        gst_element_get_state (stream->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
        stream->pipe = stream->urisrc = stream->parser = stream->sink = NULL;

        g_print ("Going to download fragment AGAIN : %s\n", stream->uri);
        if (!gst_ss_demux_create_download_pipe (demux, stream, stream->uri, stream->start_ts)) {
          GST_ERROR_OBJECT (demux, "failed to create download pipeline");
          if (!gst_element_post_message (GST_ELEMENT(demux), msg)) {
            GST_ERROR_OBJECT (demux, "failed to post error");
            return FALSE;
          }
        }

        ret = gst_element_set_state (stream->pipe, GST_STATE_PLAYING);
        if (ret == GST_STATE_CHANGE_FAILURE) {
          if (!gst_element_post_message (GST_ELEMENT(demux), msg)) {
            GST_ERROR_OBJECT (demux, "failed to post error");
            return FALSE;
          }
        }

        } else {
          if (error)
          g_print ("GST_MESSAGE_ERROR: error= %s\n", error->message);

          g_print ("GST_MESSAGE_ERROR: debug = %s\n", debug);
          if (!gst_element_post_message (GST_ELEMENT(demux), msg)) {
            GST_ERROR_OBJECT (demux, "failed to post error");
            gst_ss_demux_stop (demux, stream);
            g_free( debug);
            debug = NULL;
            g_error_free( error);
            return FALSE;
        }
        gst_ss_demux_stop (demux, stream);
      }

      g_free( debug);
      debug = NULL;
      g_error_free( error);
      break;
    }
    case GST_MESSAGE_WARNING: {
      char* debug = NULL;
      GError* error = NULL;
      gst_message_parse_warning(msg, &error, &debug);
      GST_WARNING_OBJECT(demux, "warning : %s\n", error->message);
      GST_WARNING_OBJECT(demux, "debug : %s\n", debug);
      g_error_free( error );
      g_free( debug);
      break;
    }
    default : {
      GST_LOG_OBJECT(demux, "unhandled message : %s\n", gst_message_type_get_name (GST_MESSAGE_TYPE (msg)));
      break;
    }
  }

  return TRUE;
}
コード例 #2
0
ファイル: decoder_api.c プロジェクト: GunioRobot/mpd
enum decoder_command
decoder_data(struct decoder *decoder,
	     struct input_stream *is,
	     const void *_data, size_t length,
	     uint16_t kbit_rate)
{
	struct decoder_control *dc = decoder->dc;
	const char *data = _data;
	GError *error = NULL;
	enum decoder_command cmd;

	assert(dc->state == DECODE_STATE_DECODE);
	assert(dc->pipe != NULL);
	assert(length % audio_format_frame_size(&dc->in_audio_format) == 0);

	decoder_lock(dc);
	cmd = dc->command;
	decoder_unlock(dc);

	if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
	    length == 0)
		return cmd;

	/* send stream tags */

	if (update_stream_tag(decoder, is)) {
		if (decoder->decoder_tag != NULL) {
			/* merge with tag from decoder plugin */
			struct tag *tag;

			tag = tag_merge(decoder->decoder_tag,
					decoder->stream_tag);
			cmd = do_send_tag(decoder, is, tag);
			tag_free(tag);
		} else
			/* send only the stream tag */
			cmd = do_send_tag(decoder, is, decoder->stream_tag);

		if (cmd != DECODE_COMMAND_NONE)
			return cmd;
	}

	if (!audio_format_equals(&dc->in_audio_format, &dc->out_audio_format)) {
		data = pcm_convert(&decoder->conv_state,
				   &dc->in_audio_format, data, length,
				   &dc->out_audio_format, &length,
				   &error);
		if (data == NULL) {
			/* the PCM conversion has failed - stop
			   playback, since we have no better way to
			   bail out */
			g_warning("%s", error->message);
			return DECODE_COMMAND_STOP;
		}
	}

	while (length > 0) {
		struct music_chunk *chunk;
		char *dest;
		size_t nbytes;
		bool full;

		chunk = decoder_get_chunk(decoder, is);
		if (chunk == NULL) {
			assert(dc->command != DECODE_COMMAND_NONE);
			return dc->command;
		}

		dest = music_chunk_write(chunk, &dc->out_audio_format,
					 decoder->timestamp -
					 dc->song->start_ms / 1000.0,
					 kbit_rate, &nbytes);
		if (dest == NULL) {
			/* the chunk is full, flush it */
			decoder_flush_chunk(decoder);
			g_cond_signal(dc->client_cond);
			continue;
		}

		assert(nbytes > 0);

		if (nbytes > length)
			nbytes = length;

		/* copy the buffer */

		memcpy(dest, data, nbytes);

		/* expand the music pipe chunk */

		full = music_chunk_expand(chunk, &dc->out_audio_format, nbytes);
		if (full) {
			/* the chunk is full, flush it */
			decoder_flush_chunk(decoder);
			g_cond_signal(dc->client_cond);
		}

		data += nbytes;
		length -= nbytes;

		decoder->timestamp += (double)nbytes /
			audio_format_time_to_size(&dc->out_audio_format);

		if (dc->song->end_ms > 0 &&
		    decoder->timestamp >= dc->song->end_ms / 1000.0)
			/* the end of this range has been reached:
			   stop decoding */
			return DECODE_COMMAND_STOP;
	}

	return DECODE_COMMAND_NONE;
}
コード例 #3
0
//gboolean
//gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error)
static gpointer
gst_gl_context_create_thread (GstGLContext * context)
{
  GstGLContextClass *context_class;
  GstGLWindowClass *window_class;
  GstGLFuncs *gl;
  GstGLAPI compiled_api, user_api, gl_api, display_api;
  gchar *api_string;
  gchar *compiled_api_s;
  gchar *user_api_s;
  gchar *display_api_s;
  const gchar *user_choice;
  GError **error;
  GstGLContext *other_context;

  g_mutex_lock (&context->priv->render_lock);

  GST_DEBUG_OBJECT (context, "Creating thread");

  error = context->priv->error;
  other_context = g_weak_ref_get (&context->priv->other_context_ref);

  context_class = GST_GL_CONTEXT_GET_CLASS (context);
  window_class = GST_GL_WINDOW_GET_CLASS (context->window);

  display_api = gst_gl_display_get_gl_api_unlocked (context->priv->display);
  if (display_api == GST_GL_API_NONE) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
        "Cannot create context with satisfying requested apis "
        "(display has no GL api!)");
    goto failure;
  }

  if (window_class->open) {
    if (!window_class->open (context->window, error)) {
      GST_WARNING_OBJECT (context, "Failed to open window");
      g_assert (error == NULL || *error != NULL);
      goto failure;
    }
  }

  gl = context->gl_vtable;
  compiled_api = _compiled_api ();
  compiled_api_s = gst_gl_api_to_string (compiled_api);

  user_choice = g_getenv ("GST_GL_API");
  user_api = gst_gl_api_from_string (user_choice);
  user_api_s = gst_gl_api_to_string (user_api);

  display_api_s = gst_gl_api_to_string (display_api);

  if ((user_api & compiled_api & display_api) == GST_GL_API_NONE) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
        "Cannot create context with the user requested api (%s).  "
        "We have support for (%s), display api (%s)", user_api_s,
        compiled_api_s, display_api_s);
    g_free (user_api_s);
    g_free (compiled_api_s);
    g_free (display_api_s);
    goto failure;
  }

  if (context_class->choose_format &&
      !context_class->choose_format (context, error)) {
    GST_WARNING ("Failed to choose format");
    g_assert (error == NULL || *error != NULL);
    g_free (compiled_api_s);
    g_free (user_api_s);
    g_free (display_api_s);
    goto failure;
  }

  GST_INFO_OBJECT (context,
      "Attempting to create opengl context. user chosen api(s) (%s), "
      "compiled api support (%s) display api (%s)", user_api_s, compiled_api_s,
      display_api_s);

  if (!context_class->create_context (context,
          compiled_api & user_api & display_api, other_context, error)) {
    GST_WARNING_OBJECT (context, "Failed to create context");
    g_assert (error == NULL || *error != NULL);
    g_free (compiled_api_s);
    g_free (user_api_s);
    g_free (display_api_s);
    goto failure;
  }
  GST_INFO_OBJECT (context, "created context");

  if (!gst_gl_context_activate (context, TRUE)) {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
        "Failed to activate the GL Context");
    g_free (compiled_api_s);
    g_free (user_api_s);
    g_free (display_api_s);
    goto failure;
  }

  gl_api = gst_gl_context_get_gl_api (context);
  g_assert (gl_api != GST_GL_API_NONE && gl_api != GST_GL_API_ANY);

  api_string = gst_gl_api_to_string (gl_api);
  GST_INFO_OBJECT (context, "available GL APIs: %s", api_string);

  if (((compiled_api & gl_api & display_api) & user_api) == GST_GL_API_NONE) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
        "failed to create context, context "
        "could not provide correct api. user (%s), compiled (%s), context (%s)",
        user_api_s, compiled_api_s, api_string);
    g_free (api_string);
    g_free (compiled_api_s);
    g_free (user_api_s);
    g_free (display_api_s);
    goto failure;
  }

  g_free (api_string);
  g_free (compiled_api_s);
  g_free (user_api_s);
  g_free (display_api_s);

  GST_DEBUG_OBJECT (context, "Filling info");
  if (!gst_gl_context_fill_info (context, error)) {
    g_assert (error == NULL || *error != NULL);
    goto failure;
  }

  context->priv->alive = TRUE;

  if (gl->DebugMessageCallback) {
#if !defined(GST_DISABLE_GST_DEBUG)
    GST_INFO_OBJECT (context, "Enabling GL context debugging");
    /* enable them all */
    gl->DebugMessageControl (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0,
        GL_TRUE);
    gl->DebugMessageCallback (_gst_gl_debug_callback, context);
#endif
  }

  if (other_context) {
    GST_DEBUG_OBJECT (context, "Unreffing other_context %" GST_PTR_FORMAT,
        other_context);
    gst_object_unref (other_context);
  }

  g_cond_signal (&context->priv->create_cond);

//  g_mutex_unlock (&context->priv->render_lock);
  gst_gl_window_send_message_async (context->window,
      (GstGLWindowCB) _unlock_create_thread, context, NULL);

  gst_gl_window_run (context->window);

  GST_INFO_OBJECT (context, "loop exited");

  g_mutex_lock (&context->priv->render_lock);

  context->priv->alive = FALSE;

  gst_gl_context_activate (context, FALSE);

  context_class->destroy_context (context);

  /* User supplied callback */
  if (context->window->close)
    context->window->close (context->window->close_data);

  /* window specific shutdown */
  if (window_class->close) {
    window_class->close (context->window);
  }

  g_cond_signal (&context->priv->destroy_cond);

  g_mutex_unlock (&context->priv->render_lock);

  return NULL;

failure:
  {
    if (other_context)
      gst_object_unref (other_context);

    g_cond_signal (&context->priv->create_cond);
    g_mutex_unlock (&context->priv->render_lock);
    return NULL;
  }
}
コード例 #4
0
static void
gst_droidcamsrc_dev_video_frame_callback (void *user,
    DroidMediaCameraRecordingData * video_data)
{
  GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user;
  GstDroidCamSrc *src = GST_DROIDCAMSRC (GST_PAD_PARENT (dev->imgsrc->pad));
  void *data = droid_media_camera_recording_frame_get_data (video_data);
  GstBuffer *buffer;
  GstMemory *mem;
  GstDroidCamSrcDevVideoData *mem_data;
  gboolean drop_buffer;

  GST_DEBUG_OBJECT (src, "dev video frame callback");

  g_mutex_lock (&dev->vid->lock);

  /* TODO: not sure what to do with timestamp */

  /* unlikely but just in case */
  if (G_UNLIKELY (!data)) {
    GST_ERROR ("invalid memory from camera HAL");
    droid_media_camera_release_recording_frame (dev->cam, video_data);
    goto unlock_and_out;
  }

  /* TODO: this is bad */
  mem_data = g_slice_new0 (GstDroidCamSrcDevVideoData);
  mem_data->dev = dev;
  mem_data->data = video_data;

  buffer = gst_buffer_new ();
  mem = gst_wrapped_memory_allocator_wrap (dev->wrap_allocator,
      data, droid_media_camera_recording_frame_get_size (video_data),
      (GFunc) gst_droidcamsrc_dev_release_recording_frame, mem_data);
  gst_buffer_insert_memory (buffer, 0, mem);

  GST_BUFFER_OFFSET (buffer) = dev->vid->video_frames;
  GST_BUFFER_OFFSET_END (buffer) = ++dev->vid->video_frames;
  gst_droidcamsrc_timestamp (src, buffer);

  g_rec_mutex_lock (dev->lock);
  ++dev->vid->queued_frames;
  g_rec_mutex_unlock (dev->lock);

  drop_buffer = !dev->vid->running;

  if (drop_buffer) {
    GST_INFO_OBJECT (src,
        "dropping buffer because video recording is not running");
    gst_buffer_unref (buffer);
  } else {
    g_mutex_lock (&dev->vidsrc->lock);
    g_queue_push_tail (dev->vidsrc->queue, buffer);
    g_cond_signal (&dev->vidsrc->cond);
    g_mutex_unlock (&dev->vidsrc->lock);
  }

unlock_and_out:
  /* in case stop_video_recording() is waiting for us */
  g_cond_signal (&dev->vid->cond);
  g_mutex_unlock (&dev->vid->lock);
}
コード例 #5
0
static gboolean
gst_dshowvideosrc_push_buffer (guint8 * buffer, guint size, gpointer src_object,
    GstClockTime duration)
{
  GstDshowVideoSrc *src = GST_DSHOWVIDEOSRC (src_object);
  GstBuffer *buf = NULL;
  IPin *pPin = NULL;
  HRESULT hres = S_FALSE;
  AM_MEDIA_TYPE *pMediaType = NULL;
  GstMapInfo info;

  if (!buffer || size == 0 || !src) {
    return FALSE;
  }

  /* create a new buffer assign to it the clock time as timestamp */
  buf = gst_buffer_new_and_alloc (size);

  gst_buffer_set_size(buf, size);

  GstClock *clock = gst_element_get_clock (GST_ELEMENT (src));
  GST_BUFFER_TIMESTAMP (buf) =
    GST_CLOCK_DIFF (gst_element_get_base_time (GST_ELEMENT (src)), gst_clock_get_time (clock));
  gst_object_unref (clock);

  GST_BUFFER_DURATION (buf) = duration;

  if (!gst_buffer_map(buf, &info, GST_MAP_WRITE)) {
	  gst_buffer_unref(buf);
	  GST_ERROR("Failed to map buffer");
	  return FALSE;
  }

  if (src->is_rgb) {
    /* FOR RGB directshow decoder will return bottom-up BITMAP
     * There is probably a way to get top-bottom video frames from
     * the decoder...
     */
    gint line = 0;
    gint stride = size / src->height;

    for (; line < src->height; line++) {
      memcpy (info.data + (line * stride),
          buffer + (size - ((line + 1) * (stride))), stride);
    }
  } else {
    memcpy (info.data, buffer, size);
  }

  gst_buffer_unmap(buf, &info);

  GST_DEBUG ("push_buffer => pts %" GST_TIME_FORMAT "duration %"
      GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
      GST_TIME_ARGS (duration));

  g_mutex_lock (&src->buffer_mutex);
  if (src->buffer != NULL)
    gst_buffer_unref (src->buffer);
  src->buffer = buf;
  g_cond_signal (&src->buffer_cond);
  g_mutex_unlock (&src->buffer_mutex);

  return TRUE;
}
コード例 #6
0
ファイル: type_decoder.c プロジェクト: karlp/libsigrokdecode
static PyObject *Decoder_wait(PyObject *self, PyObject *args)
{
	int ret;
	unsigned int i;
	gboolean found_match;
	struct srd_decoder_inst *di;
	PyObject *py_pinvalues, *py_matched;

	if (!self || !args)
		return NULL;

	if (!(di = srd_inst_find_by_obj(NULL, self))) {
		PyErr_SetString(PyExc_Exception, "decoder instance not found");
		Py_RETURN_NONE;
	}

	ret = set_new_condition_list(self, args);
	if (ret < 0) {
		srd_dbg("%s: %s: Aborting wait().", di->inst_id, __func__);
		return NULL;
	}
	if (ret == 9999) {
		/* Empty condition list, automatic match. */
		PyObject_SetAttrString(di->py_inst, "matched", Py_None);
		/* Leave self.samplenum unchanged (== di->abs_cur_samplenum). */
		return get_current_pinvalues(di);
	}

	while (1) {
		/* Wait for new samples to process, or termination request. */
		g_mutex_lock(&di->data_mutex);
		while (!di->got_new_samples && !di->want_wait_terminate)
			g_cond_wait(&di->got_new_samples_cond, &di->data_mutex);

		/*
		 * Check whether any of the current condition(s) match.
		 * Arrange for termination requests to take a code path which
		 * won't find new samples to process, pretends to have processed
		 * previously stored samples, and returns to the main thread,
		 * while the termination request still gets signalled.
		 */
		found_match = FALSE;
		ret = process_samples_until_condition_match(di, &found_match);

		/* If there's a match, set self.samplenum etc. and return. */
		if (found_match) {
			/* Set self.samplenum to the (absolute) sample number that matched. */
			PyObject_SetAttrString(di->py_inst, "samplenum",
				PyLong_FromLong(di->abs_cur_samplenum));

			if (di->match_array && di->match_array->len > 0) {
				py_matched = PyTuple_New(di->match_array->len);
				for (i = 0; i < di->match_array->len; i++)
					PyTuple_SetItem(py_matched, i, PyBool_FromLong(di->match_array->data[i]));
				PyObject_SetAttrString(di->py_inst, "matched", py_matched);
				match_array_free(di);
			} else {
				PyObject_SetAttrString(di->py_inst, "matched", Py_None);
			}
	
			py_pinvalues = get_current_pinvalues(di);

			g_mutex_unlock(&di->data_mutex);

			return py_pinvalues;
		}

		/* No match, reset state for the next chunk. */
		di->got_new_samples = FALSE;
		di->handled_all_samples = TRUE;
		di->abs_start_samplenum = 0;
		di->abs_end_samplenum = 0;
		di->inbuf = NULL;
		di->inbuflen = 0;

		/* Signal the main thread that we handled all samples. */
		g_cond_signal(&di->handled_all_samples_cond);

		/*
		 * When termination of wait() and decode() was requested,
		 * then exit the loop after releasing the mutex.
		 */
		if (di->want_wait_terminate) {
			srd_dbg("%s: %s: Will return from wait().",
				di->inst_id, __func__);
			g_mutex_unlock(&di->data_mutex);
			return NULL;
		}

		g_mutex_unlock(&di->data_mutex);
	}

	Py_RETURN_NONE;
}
コード例 #7
0
ファイル: gdigi.c プロジェクト: andrewshadura/gdigi
void push_message(GString *msg)
{
    MessageID msgid = get_message_id(msg);
    if (((unsigned char)msg->str[0] == 0xF0) &&
            ((unsigned char)msg->str[msg->len-1] == 0xF7)) {
        debug_msg(DEBUG_VERBOSE, "Pushing correct message!");
    } else {
        g_warning("Pushing incorrect message!");
    }

    int x;
    if (debug_flag_is_set(DEBUG_HEX)) {
        for (x = 0; x<msg->len; x++) {
            if (x && (x % HEX_WIDTH) == 0) {
                printf("\n");
            }
            printf("%02x ", (unsigned char)msg->str[x]);
        }
        if (x % HEX_WIDTH) {
            printf("\n");
        }
    }
    debug_msg(DEBUG_VERBOSE, "Received %s", get_message_name(msgid));

    SettingParam *param;
    switch (msgid) {
    case ACK:
        g_string_free(msg, TRUE);
        return;

    case NACK:
        g_warning("Received NACK!");
        g_string_free(msg, TRUE);
        return;

    case RECEIVE_PARAMETER_VALUE:
    {
        unpack_message(msg);
        param = setting_param_new_from_data(&msg->str[8], NULL);
        if (debug_flag_is_set(DEBUG_MSG2HOST)) {
            GString *ipv = format_ipv(param->id,
                                      param->position,
                                      param->value);
            debug_msg(DEBUG_MSG2HOST, "Receive RECEIVE_PARAMETER_VALUE: %s",
                      ipv->str);
            g_string_free(ipv, TRUE);
        }

        GDK_THREADS_ENTER();
        apply_setting_param_to_gui(param);
        GDK_THREADS_LEAVE();

        setting_param_free(param);
        g_string_free(msg, TRUE);
        return;
    }

    case RECEIVE_DEVICE_NOTIFICATION:
    {
        unsigned char *str = (unsigned char*)msg->str;

        unpack_message(msg);
        switch (str[8]) {
        case NOTIFY_PRESET_MOVED:
            if (str[11] == PRESETS_EDIT_BUFFER && str[12] == 0) {

                GDK_THREADS_ENTER();
                g_timeout_add(0, apply_current_preset_to_gui, NULL);
                GDK_THREADS_LEAVE();
                debug_msg(DEBUG_MSG2HOST,
                          "Receive RECEIVE_DEVICE_NOTIFICATION: Loaded preset "
                          "%d from bank %d",
                          str[10], str[9]);
            } else {
                debug_msg(DEBUG_MSG2HOST,
                          "Receive RECEIVE_DEVICE_NOTIFICATION: %d %d moved to "
                          "%d %d",
                          str[9], str[10],
                          str[11], str[12]);
            }
            break;

        case NOTIFY_MODIFIER_GROUP_CHANGED:
        {
            int i;
            if (debug_flag_is_set(DEBUG_HEX)) {
                printf("\n");
                for (i = 0; i < msg->len; i++) {
                    printf(" %02x", (unsigned char) str[i]);
                }
                printf("\n");
            }
            debug_msg(DEBUG_MSG2HOST,
                      "Receive NOTIFY_MODIFIER_GROUP_CHANGED: Modifier group "
                      "id %d changed",
                      (str[9] << 8) | (str[10]));
            break;
        }

        default:
            g_warning("Received unhandled device notification 0x%x", str[11]);
            break;
        }
        g_string_free(msg, TRUE);
        return;
    }

    case RECEIVE_GLOBAL_PARAMETERS:
    {
        gint tot, n, x;

        unpack_message(msg);
        tot = (unsigned char)msg->str[9];
        if (debug_flag_is_set(DEBUG_HEX)) {
            for (n = 0; n < msg->len; n++) {
                printf("%02x ",(unsigned char) msg->str[n]);
            }
            printf("\n");
        }

        n = 0;
        x = 10;
        do {
            param = setting_param_new_from_data(&msg->str[x], &x);
            debug_msg(DEBUG_MSG2HOST,
                      "Receive RECEIVE_GLOBAL_PARAMETERS ID: %5d "
                      "Position: %2.1d Value: %6.1d: %s",
                      param->id,
                      param->position, param->value, "XXX");
            setting_param_free(param);
        } while ( (x < msg->len) && n < tot);

        g_string_free(msg, TRUE);
        return;
    }

    case RECEIVE_MODIFIER_LINKABLE_LIST:
    {
        gint tot, n;

        unpack_message(msg);
        tot = (unsigned char)msg->str[9];

        if (debug_flag_is_set(DEBUG_HEX)) {
            for (n = 0; n < msg->len; n++) {
                printf("%02x ",(unsigned char) msg->str[n]);
            }
            printf("\n");
        }

        modifier_linkable_list(msg);

        g_string_free(msg, TRUE);
        return;
    }

    default:
        g_mutex_lock(message_queue_mutex);
        g_queue_push_tail(message_queue, msg);
        g_cond_signal(message_queue_cond);
        g_mutex_unlock(message_queue_mutex);
        break;
    }
}
コード例 #8
0
static gpointer
gegl_tile_backend_swap_writer_thread (gpointer ignored)
{
  while (TRUE)
    {
      ThreadParams *params;

      g_mutex_lock (&mutex);

      while (g_queue_is_empty (queue) && !exit_thread)
        g_cond_wait (&queue_cond, &mutex);

      if (exit_thread)
        {
          g_mutex_unlock (&mutex);
          GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "exiting writer thread");
          return NULL;
        }

      params = (ThreadParams *)g_queue_pop_head (queue);
      if (params->operation == OP_WRITE)
        {
          in_progress = params;
          params->entry->link = NULL;
        }

      g_mutex_unlock (&mutex);

      switch (params->operation)
        {
        case OP_WRITE:
          gegl_tile_backend_swap_write (params);
          break;
        case OP_TRUNCATE:
          if (ftruncate (out_fd, total) != 0)
            g_warning ("failed to resize swap file: %s", g_strerror (errno));
          break;
        }

      g_mutex_lock (&mutex);

      in_progress = NULL;

      if (params->operation == OP_WRITE)
        {
          queue_size -= params->length + sizeof (GList) +
            sizeof (ThreadParams);
          g_free (params->source);

          /* unblock the main thread if the queue had gotten too big */
          if (queue_size < gegl_config ()->queue_size)
            g_cond_signal (&max_cond);
        }

      g_slice_free (ThreadParams, params);

      g_mutex_unlock (&mutex);
    }

  return NULL;
}
コード例 #9
0
static OMX_ERRORTYPE
EventHandler (OMX_HANDLETYPE omx_handle,
              OMX_PTR app_data,
              OMX_EVENTTYPE event,
              OMX_U32 data_1,
              OMX_U32 data_2,
              OMX_PTR event_data)
{
    GOmxCore *core;

    core = (GOmxCore *) app_data;

    switch (event)
    {
        case OMX_EventCmdComplete:
            {
                OMX_COMMANDTYPE cmd;

                cmd = (OMX_COMMANDTYPE) data_1;

                GST_DEBUG_OBJECT (core->object, "OMX_EventCmdComplete: %d", cmd);

                switch (cmd)
                {
                    case OMX_CommandStateSet:
                        complete_change_state (core, data_2);
                        break;
                    case OMX_CommandFlush:
                        g_sem_up (core->flush_sem);
                        break;
                    case OMX_CommandPortDisable:
                    case OMX_CommandPortEnable:
                        g_sem_up (core->port_sem);
                    default:
                        break;
                }
                break;
            }
        case OMX_EventBufferFlag:
            {
                GST_DEBUG_OBJECT (core->object, "OMX_EventBufferFlag");
                if (data_2 & OMX_BUFFERFLAG_EOS)
                {
                    g_omx_core_set_done (core);
                }
                break;
            }
        case OMX_EventPortSettingsChanged:
            {
                GST_DEBUG_OBJECT (core->object, "OMX_EventPortSettingsChanged");
                /** @todo only on the relevant port. */
                if (core->settings_changed_cb)
                {
                    core->settings_changed_cb (core);
                }
                break;
            }
        case OMX_EventIndexSettingChanged:
            {
                GST_DEBUG_OBJECT (core->object,
                        "OMX_EventIndexSettingsChanged");
                if (core->index_settings_changed_cb)
                {
                    core->index_settings_changed_cb (core, data_1, data_2);
                }
                break;
            }
        case OMX_EventError:
            {
                core->omx_error = data_1;
                GST_ERROR_OBJECT (core->object, "unrecoverable error: %s (0x%lx)",
                                  g_omx_error_to_str (data_1), data_1);
                /* component might leave us waiting for buffers, unblock */
                g_omx_core_flush_start (core);
                /* unlock wait_for_state */
                g_mutex_lock (core->omx_state_mutex);
                g_cond_signal (core->omx_state_condition);
                g_mutex_unlock (core->omx_state_mutex);
                break;
            }
#ifdef USE_OMXTICORE
        case OMX_TI_EventBufferRefCount:
            {
                OMX_BUFFERHEADERTYPE *omx_buffer = (OMX_BUFFERHEADERTYPE *)data_1;
                GOmxPort *port = get_port (core, omx_buffer->nOutputPortIndex);

                GST_DEBUG_OBJECT (core->object, "unref: omx_buffer=%p, pAppPrivate=%p, pBuffer=%p",
                        omx_buffer, omx_buffer->pAppPrivate, omx_buffer->pBuffer);

                g_mutex_lock (core->omx_state_mutex);
                omx_buffer->nFlags |= GST_BUFFERFLAG_UNREF_CHECK;
                g_mutex_unlock (core->omx_state_mutex);

                g_omx_port_push_buffer (port, omx_buffer);
                break;
            }
#endif
        default:
            GST_WARNING_OBJECT (core->object, "unhandled event: %d", event);
            break;
    }

    return OMX_ErrorNone;
}
コード例 #10
0
ファイル: vhost-user-test.c プロジェクト: heiher/qemu
static void chr_read(void *opaque, const uint8_t *buf, int size)
{
    TestServer *s = opaque;
    CharDriverState *chr = s->chr;
    VhostUserMsg msg;
    uint8_t *p = (uint8_t *) &msg;
    int fd;

    if (s->test_fail) {
        qemu_chr_disconnect(chr);
        /* now switch to non-failure */
        s->test_fail = false;
    }

    if (size != VHOST_USER_HDR_SIZE) {
        g_test_message("Wrong message size received %d\n", size);
        return;
    }

    g_mutex_lock(&s->data_mutex);
    memcpy(p, buf, VHOST_USER_HDR_SIZE);

    if (msg.size) {
        p += VHOST_USER_HDR_SIZE;
        size = qemu_chr_fe_read_all(chr, p, msg.size);
        if (size != msg.size) {
            g_test_message("Wrong message size received %d != %d\n",
                           size, msg.size);
            return;
        }
    }

    switch (msg.request) {
    case VHOST_USER_GET_FEATURES:
        /* send back features to qemu */
        msg.flags |= VHOST_USER_REPLY_MASK;
        msg.size = sizeof(m.payload.u64);
        msg.payload.u64 = 0x1ULL << VHOST_F_LOG_ALL |
            0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
        if (s->queues > 1) {
            msg.payload.u64 |= 0x1ULL << VIRTIO_NET_F_MQ;
        }
        if (s->test_flags >= TEST_FLAGS_BAD) {
            msg.payload.u64 = 0;
            s->test_flags = TEST_FLAGS_END;
        }
        p = (uint8_t *) &msg;
        qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
        break;

    case VHOST_USER_SET_FEATURES:
	g_assert_cmpint(msg.payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES),
			!=, 0ULL);
        if (s->test_flags == TEST_FLAGS_DISCONNECT) {
            qemu_chr_disconnect(chr);
            s->test_flags = TEST_FLAGS_BAD;
        }
        break;

    case VHOST_USER_GET_PROTOCOL_FEATURES:
        /* send back features to qemu */
        msg.flags |= VHOST_USER_REPLY_MASK;
        msg.size = sizeof(m.payload.u64);
        msg.payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
        if (s->queues > 1) {
            msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_MQ;
        }
        p = (uint8_t *) &msg;
        qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
        break;

    case VHOST_USER_GET_VRING_BASE:
        /* send back vring base to qemu */
        msg.flags |= VHOST_USER_REPLY_MASK;
        msg.size = sizeof(m.payload.state);
        msg.payload.state.num = 0;
        p = (uint8_t *) &msg;
        qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);

        assert(msg.payload.state.index < s->queues * 2);
        s->rings &= ~(0x1ULL << msg.payload.state.index);
        break;

    case VHOST_USER_SET_MEM_TABLE:
        /* received the mem table */
        memcpy(&s->memory, &msg.payload.memory, sizeof(msg.payload.memory));
        s->fds_num = qemu_chr_fe_get_msgfds(chr, s->fds, G_N_ELEMENTS(s->fds));

        /* signal the test that it can continue */
        g_cond_signal(&s->data_cond);
        break;

    case VHOST_USER_SET_VRING_KICK:
    case VHOST_USER_SET_VRING_CALL:
        /* consume the fd */
        qemu_chr_fe_get_msgfds(chr, &fd, 1);
        /*
         * This is a non-blocking eventfd.
         * The receive function forces it to be blocking,
         * so revert it back to non-blocking.
         */
        qemu_set_nonblock(fd);
        break;

    case VHOST_USER_SET_LOG_BASE:
        if (s->log_fd != -1) {
            close(s->log_fd);
            s->log_fd = -1;
        }
        qemu_chr_fe_get_msgfds(chr, &s->log_fd, 1);
        msg.flags |= VHOST_USER_REPLY_MASK;
        msg.size = 0;
        p = (uint8_t *) &msg;
        qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE);

        g_cond_signal(&s->data_cond);
        break;

    case VHOST_USER_SET_VRING_BASE:
        assert(msg.payload.state.index < s->queues * 2);
        s->rings |= 0x1ULL << msg.payload.state.index;
        break;

    case VHOST_USER_GET_QUEUE_NUM:
        msg.flags |= VHOST_USER_REPLY_MASK;
        msg.size = sizeof(m.payload.u64);
        msg.payload.u64 = s->queues;
        p = (uint8_t *) &msg;
        qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
        break;

    default:
        break;
    }

    g_mutex_unlock(&s->data_mutex);
}
コード例 #11
0
/**
 * hls_progress_buffer_sink_event()
 *
 * Receives event from the sink pad (currently, data from javasource).  When an event comes in,
 * we get the data from the pad by getting at the ProgressBuffer* object associated with the pad.
 */
static gboolean hls_progress_buffer_sink_event(GstPad *pad, GstEvent *event)
{
    HLSProgressBuffer *element = HLS_PROGRESS_BUFFER(GST_PAD_PARENT(pad));
    gboolean ret = FALSE;

    switch (GST_EVENT_TYPE (event))
    {
    case GST_EVENT_NEWSEGMENT:
        {
            gboolean update;
            GstFormat format;
            gdouble rate, arate;
            gint64 start, stop, time;

            g_mutex_lock(element->lock);
            if (element->srcresult != GST_FLOW_OK)
            {
                // INLINE - gst_event_unref()
                gst_event_unref(event);
                g_mutex_unlock(element->lock);
                return TRUE;
            }
            g_mutex_unlock(element->lock);

            if (element->is_eos)
            {
                element->is_eos = FALSE;
                element->srcresult = GST_FLOW_OK;
                if (gst_pad_is_linked(element->srcpad))
                    gst_pad_start_task(element->srcpad, hls_progress_buffer_loop, element);
            }

            // In HLS mode javasource will set time to correct position in time unit, even if segment in byte units.
            // Maybe not perfect, but works.
            gst_event_parse_new_segment_full(event, &update, &rate, &arate, &format, &start, &stop, &time);
            // INLINE - gst_event_unref()
            gst_event_unref(event);
            ret = TRUE;

            if (stop - start <= 0)
            {
                gst_element_message_full(GST_ELEMENT(element), GST_MESSAGE_ERROR, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE, g_strdup("Only limited content is supported by hlsprogressbuffer."), NULL, ("hlsprogressbuffer.c"), ("hls_progress_buffer_src_event"), 0);
                return TRUE;
            }

            if (element->send_new_segment)
            {
                event = gst_event_new_new_segment(update, rate, GST_FORMAT_TIME, 0, -1, time);
                element->send_new_segment = FALSE;
                ret = gst_pad_push_event(element->srcpad, event);
            }

            // Get and prepare next write segment
            g_mutex_lock(element->lock);
            element->cache_write_index = (element->cache_write_index + 1) % NUM_OF_CACHED_SEGMENTS;

            while (element->srcresult == GST_FLOW_OK && !element->cache_write_ready[element->cache_write_index])
            {
                g_mutex_unlock(element->lock);
                send_hls_full_message(element);
                g_mutex_lock(element->lock);
                g_cond_wait(element->del_cond, element->lock);
                if (element->srcresult != GST_FLOW_OK)
                {
                    g_mutex_unlock(element->lock);
                    return TRUE;
                }
            }
            element->cache_size[element->cache_write_index] = stop;
            element->cache_write_ready[element->cache_write_index] = FALSE;
            cache_set_write_position(element->cache[element->cache_write_index], 0);
            cache_set_read_position(element->cache[element->cache_write_index], 0);

            g_mutex_unlock(element->lock);

            send_hls_resume_message(element); // Send resume message for each segment
        }
        break;
    case GST_EVENT_FLUSH_START:
        g_mutex_lock(element->lock);
        element->is_flushing = TRUE;
        g_mutex_unlock(element->lock);

        ret = gst_pad_push_event(element->srcpad, event);
        hls_progress_buffer_flush_data(element);

        if (gst_pad_is_linked(element->srcpad))
            gst_pad_pause_task(element->srcpad);

        break;
    case GST_EVENT_FLUSH_STOP:
        ret = gst_pad_push_event(element->srcpad, event);

        g_mutex_lock(element->lock);

        element->send_new_segment = TRUE;
        element->is_flushing = FALSE;
        element->srcresult = GST_FLOW_OK;
        
        if (!element->is_eos && gst_pad_is_linked(element->srcpad))
            gst_pad_start_task(element->srcpad, hls_progress_buffer_loop, element);

        g_mutex_unlock(element->lock);

        break;
    case GST_EVENT_EOS:
        send_hls_eos_message(element); // Just in case we stall

        g_mutex_lock(element->lock);
        element->is_eos = TRUE;
        g_cond_signal(element->add_cond);
        g_mutex_unlock(element->lock);
        // INLINE - gst_event_unref()
        gst_event_unref(event);
        ret = TRUE;

        break;
    default:
        ret = gst_pad_push_event(element->srcpad, event);
        break;
    }

    return ret;
}
//gboolean
//gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error)
static gpointer
gst_gl_context_create_thread (GstGLContext * context)
{
  GstGLContextClass *context_class;
  GstGLWindowClass *window_class;
  GstGLDisplay *display;
  GstGLFuncs *gl;
  gint gl_major = 0, gl_minor = 0;
  gboolean ret = FALSE;
  GstGLAPI compiled_api, user_api;
  gchar *api_string;
  gchar *compiled_api_s;
  gchar *user_api_string;
  const gchar *user_choice, *extensions;
  GError **error;
  GstGLContext *other_context;

  g_mutex_lock (&context->priv->render_lock);

  error = context->priv->error;
  other_context = context->priv->other_context;

  context_class = GST_GL_CONTEXT_GET_CLASS (context);
  window_class = GST_GL_WINDOW_GET_CLASS (context->window);

  if (window_class->open) {
    if (!window_class->open (context->window, error))
      goto failure;
  }

  display = context->priv->display;
  gl = context->gl_vtable;
  compiled_api = _compiled_api ();

  user_choice = g_getenv ("GST_GL_API");

  user_api = gst_gl_api_from_string (user_choice);
  user_api_string = gst_gl_api_to_string (user_api);

  compiled_api_s = gst_gl_api_to_string (compiled_api);

  if ((user_api & compiled_api) == GST_GL_API_NONE) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
        "Cannot create context with the user requested api (%s).  "
        "We have support for (%s)", user_api_string, compiled_api_s);
    g_free (user_api_string);
    g_free (compiled_api_s);
    goto failure;
  }

  if (context_class->choose_format &&
      !context_class->choose_format (context, error)) {
    g_assert (error == NULL || *error != NULL);
    g_free (compiled_api_s);
    g_free (user_api_string);
    goto failure;
  }

  GST_INFO ("Attempting to create opengl context. user chosen api(s) (%s), "
      "compiled api support (%s)", user_api_string, compiled_api_s);

  if (!context_class->create_context (context, compiled_api & user_api,
          other_context, error)) {
    g_assert (error == NULL || *error != NULL);
    g_free (compiled_api_s);
    g_free (user_api_string);
    goto failure;
  }
  GST_INFO ("created context");

  if (!context_class->activate (context, TRUE)) {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
        "Failed to activate the GL Context");
    g_free (compiled_api_s);
    g_free (user_api_string);
    goto failure;
  }

  display->gl_api = gst_gl_context_get_gl_api (context);
  g_assert (display->gl_api != GST_GL_API_NONE
      && display->gl_api != GST_GL_API_ANY);

  api_string = gst_gl_api_to_string (display->gl_api);
  GST_INFO ("available GL APIs: %s", api_string);

  if (((compiled_api & display->gl_api) & user_api) == GST_GL_API_NONE) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
        "failed to create context, context "
        "could not provide correct api. user (%s), compiled (%s), context (%s)",
        user_api_string, compiled_api_s, api_string);
    g_free (api_string);
    g_free (compiled_api_s);
    g_free (user_api_string);
    goto failure;
  }

  g_free (api_string);
  g_free (compiled_api_s);
  g_free (user_api_string);

  gl->GetError = gst_gl_context_get_proc_address (context, "glGetError");
  gl->GetString = gst_gl_context_get_proc_address (context, "glGetString");
  gl->GetStringi = gst_gl_context_get_proc_address (context, "glGetStringi");
  gl->GetIntegerv = gst_gl_context_get_proc_address (context, "glGetIntegerv");

  if (!gl->GetError || !gl->GetString) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
        "could not GetProcAddress core opengl functions");
    goto failure;
  }

  /* gl api specific code */
  if (!ret && USING_OPENGL (display))
    ret = _create_context_opengl (context, &gl_major, &gl_minor, error);
  if (!ret && USING_GLES2 (display))
    ret = _create_context_gles2 (context, &gl_major, &gl_minor, error);

  if (!ret)
    goto failure;

  /* GL core contexts and GLES3 */
  if (gl->GetIntegerv && gl->GetStringi) {
    extensions = _build_extension_string (context);
  } else {
    extensions = (const gchar *) gl->GetString (GL_EXTENSIONS);
  }

  _gst_gl_feature_check_ext_functions (context, gl_major, gl_minor, extensions);

  context->priv->alive = TRUE;

  g_cond_signal (&context->priv->create_cond);

//  g_mutex_unlock (&context->priv->render_lock);
  gst_gl_window_send_message_async (context->window,
      (GstGLWindowCB) _unlock_create_thread, context, NULL);

  gst_gl_window_run (context->window);

  GST_INFO ("loop exited\n");

  g_mutex_lock (&context->priv->render_lock);

  context->priv->alive = FALSE;

  context_class->activate (context, FALSE);

  context_class->destroy_context (context);

  /* User supplied callback */
  if (context->window->close)
    context->window->close (context->window->close_data);

  /* window specific shutdown */
  if (window_class->close) {
    window_class->close (context->window);
  }

  g_cond_signal (&context->priv->destroy_cond);

  g_mutex_unlock (&context->priv->render_lock);

  return NULL;

failure:
  {
    g_cond_signal (&context->priv->create_cond);
    g_mutex_unlock (&context->priv->render_lock);
    return NULL;
  }
}
コード例 #13
0
/* Called in the gl thread */
void
gst_gl_window_run_loop (GstGLWindow * window)
{
    GstGLWindowPrivate *priv = window->priv;

    g_debug ("begin loop\n");

    g_mutex_lock (priv->x_lock);

    while (priv->running) {
        XEvent event;
        XEvent pending_event;

        g_mutex_unlock (priv->x_lock);

        /* XSendEvent (which are called in other threads) are done from another display structure */
        XNextEvent (priv->device, &event);

        g_mutex_lock (priv->x_lock);

        // use in generic/cube and other related uses
        priv->allow_extra_expose_events = XPending (priv->device) <= 2;

        switch (event.type) {
        case ClientMessage:
        {

            Atom wm_delete = XInternAtom (priv->device, "WM_DELETE_WINDOW", True);
            Atom wm_gl = XInternAtom (priv->device, "WM_GL_WINDOW", True);
            Atom wm_quit_loop = XInternAtom (priv->device, "WM_QUIT_LOOP", True);

            if (wm_delete == None)
                g_debug ("Cannot create WM_DELETE_WINDOW\n");
            if (wm_gl == None)
                g_debug ("Cannot create WM_GL_WINDOW\n");
            if (wm_quit_loop == None)
                g_debug ("Cannot create WM_QUIT_LOOP\n");

            /* Message sent with gst_gl_window_send_message */
            if (wm_gl != None && event.xclient.message_type == wm_gl) {
                if (priv->running) {
#if SIZEOF_VOID_P == 8
                    GstGLWindowCB custom_cb =
                        (GstGLWindowCB) (((event.xclient.data.
                                           l[0] & 0xffffffff) << 32) | (event.xclient.data.
                                                   l[1] & 0xffffffff));
                    gpointer custom_data =
                        (gpointer) (((event.xclient.data.
                                      l[2] & 0xffffffff) << 32) | (event.xclient.data.
                                              l[3] & 0xffffffff));
#else
                    GstGLWindowCB custom_cb = (GstGLWindowCB) event.xclient.data.l[0];
                    gpointer custom_data = (gpointer) event.xclient.data.l[1];
#endif

                    if (!custom_cb || !custom_data)
                        g_debug ("custom cb not initialized\n");

                    custom_cb (custom_data);
                }

                g_cond_signal (priv->cond_send_message);
            }

            /* User clicked on the cross */
            else if (wm_delete != None
                     && (Atom) event.xclient.data.l[0] == wm_delete) {
                g_debug ("Close %lud\n", (gulong) priv->internal_win_id);

                if (priv->close_cb)
                    priv->close_cb (priv->close_data);

                priv->draw_cb = NULL;
                priv->draw_data = NULL;
                priv->resize_cb = NULL;
                priv->resize_data = NULL;
                priv->close_cb = NULL;
                priv->close_data = NULL;
            }

            /* message sent with gst_gl_window_quit_loop */
            else if (wm_quit_loop != None
                     && event.xclient.message_type == wm_quit_loop) {
#if SIZEOF_VOID_P == 8
                GstGLWindowCB destroy_cb =
                    (GstGLWindowCB) (((event.xclient.data.
                                       l[0] & 0xffffffff) << 32) | (event.xclient.data.
                                               l[1] & 0xffffffff));
                gpointer destroy_data =
                    (gpointer) (((event.xclient.data.
                                  l[2] & 0xffffffff) << 32) | (event.xclient.data.
                                          l[3] & 0xffffffff));
#else
                GstGLWindowCB destroy_cb = (GstGLWindowCB) event.xclient.data.l[0];
                gpointer destroy_data = (gpointer) event.xclient.data.l[1];
#endif

                g_debug ("Quit loop message %lud\n", (gulong) priv->internal_win_id);

                /* exit loop */
                priv->running = FALSE;

                /* make sure last pendings send message calls are executed */
                XFlush (priv->device);
                while (XCheckTypedEvent (priv->device, ClientMessage, &pending_event)) {
#if SIZEOF_VOID_P == 8
                    GstGLWindowCB custom_cb =
                        (GstGLWindowCB) (((event.xclient.data.
                                           l[0] & 0xffffffff) << 32) | (event.xclient.data.
                                                   l[1] & 0xffffffff));
                    gpointer custom_data =
                        (gpointer) (((event.xclient.data.
                                      l[2] & 0xffffffff) << 32) | (event.xclient.data.
                                              l[3] & 0xffffffff));
#else
                    GstGLWindowCB custom_cb = (GstGLWindowCB) event.xclient.data.l[0];
                    gpointer custom_data = (gpointer) event.xclient.data.l[1];
#endif
                    g_debug ("execute last pending custom x events\n");

                    if (!custom_cb || !custom_data)
                        g_debug ("custom cb not initialized\n");

                    custom_cb (custom_data);

                    g_cond_signal (priv->cond_send_message);
                }

                /* Finally we can destroy opengl ressources (texture/shaders/fbo) */
                if (!destroy_cb || !destroy_data)
                    g_debug ("destroy cb not correclty set\n");

                destroy_cb (destroy_data);

            } else
                g_debug ("client message not reconized \n");
            break;
        }

        case CreateNotify:
        case ConfigureNotify:
        {
            if (priv->resize_cb)
                priv->resize_cb (priv->resize_data, event.xconfigure.width,
                                 event.xconfigure.height);
            break;
        }

        case DestroyNotify:
            g_debug ("DestroyNotify\n");
            break;

        case Expose:
            if (priv->draw_cb) {
                priv->draw_cb (priv->draw_data);
                glFlush ();
                eglSwapBuffers (priv->gl_display, priv->gl_surface);
            }
            break;

        case VisibilityNotify:
        {
            switch (event.xvisibility.state) {
            case VisibilityUnobscured:
                if (priv->draw_cb)
                    priv->draw_cb (priv->draw_data);
                break;

            case VisibilityPartiallyObscured:
                if (priv->draw_cb)
                    priv->draw_cb (priv->draw_data);
                break;

            case VisibilityFullyObscured:
                break;

            default:
                g_debug ("unknown xvisibility event: %d\n",
                         event.xvisibility.state);
                break;
            }
            break;
        }

        default:
            g_debug ("unknown XEvent type: %ud\n", event.type);
            break;

        }                           // switch

    }                             // while running

    g_mutex_unlock (priv->x_lock);

    g_debug ("end loop\n");
}
コード例 #14
0
ファイル: wavpack.c プロジェクト: Falcon-peregrinus/mlplayer
static gboolean wv_play (InputPlayback * playback, const gchar * filename,
 VFSFile * file, gint start_time, gint stop_time, gboolean pause)
{
    if (file == NULL)
        return FALSE;

    gint32 *input = NULL;
    void *output = NULL;
    gint sample_rate, num_channels, bits_per_sample;
    guint num_samples;
    WavpackContext *ctx = NULL;
    VFSFile *wvc_input = NULL;
    gboolean error = FALSE;

    if (! wv_attach (filename, file, & wvc_input, & ctx, NULL, OPEN_TAGS |
     OPEN_WVC))
    {
        g_warning("Error opening Wavpack file '%s'.", filename);
        error = TRUE;
        goto error_exit;
    }

    sample_rate = WavpackGetSampleRate(ctx);
    num_channels = WavpackGetNumChannels(ctx);
    bits_per_sample = WavpackGetBitsPerSample(ctx);
    num_samples = WavpackGetNumSamples(ctx);

    if (!playback->output->open_audio(SAMPLE_FMT(bits_per_sample), sample_rate, num_channels))
    {
        g_warning("Error opening audio output.");
        error = TRUE;
        goto error_exit;
    }

    if (pause)
        playback->output->pause(TRUE);

    input = g_malloc(BUFFER_SIZE * num_channels * sizeof(guint32));
    output = g_malloc(BUFFER_SIZE * num_channels * SAMPLE_SIZE(bits_per_sample));
    if (input == NULL || output == NULL)
        goto error_exit;

    playback->set_gain_from_playlist(playback);

    g_mutex_lock(ctrl_mutex);

    playback->set_params(playback, (gint) WavpackGetAverageBitrate(ctx, num_channels),
        sample_rate, num_channels);

    seek_value = (start_time > 0) ? start_time : -1;
    stop_flag = FALSE;

    playback->set_pb_ready(playback);

    g_mutex_unlock(ctrl_mutex);

    while (!stop_flag && (stop_time < 0 ||
     playback->output->written_time () < stop_time))
    {
        gint ret;
        guint samples_left;

        /* Handle seek and pause requests */
        g_mutex_lock(ctrl_mutex);

        if (seek_value >= 0)
        {
            playback->output->flush (seek_value);
            WavpackSeekSample (ctx, (gint64) seek_value * sample_rate / 1000);
            seek_value = -1;
            g_cond_signal(ctrl_cond);
        }

        g_mutex_unlock(ctrl_mutex);

        /* Decode audio data */
        samples_left = num_samples - WavpackGetSampleIndex(ctx);

        ret = WavpackUnpackSamples(ctx, input, BUFFER_SIZE);
        if (samples_left == 0)
            stop_flag = TRUE;
        else if (ret < 0)
        {
            g_warning("Error decoding file.\n");
            break;
        }
        else
        {
            /* Perform audio data conversion and output */
            guint i;
            gint32 *rp = input;
            gint8 *wp = output;
            gint16 *wp2 = output;
            gint32 *wp4 = output;

            if (bits_per_sample == 8)
            {
                for (i = 0; i < ret * num_channels; i++, wp++, rp++)
                    *wp = *rp & 0xff;
            }
            else if (bits_per_sample == 16)
            {
                for (i = 0; i < ret * num_channels; i++, wp2++, rp++)
                    *wp2 = *rp & 0xffff;
            }
            else if (bits_per_sample == 24 || bits_per_sample == 32)
            {
                for (i = 0; i < ret * num_channels; i++, wp4++, rp++)
                    *wp4 = *rp;
            }

            playback->output->write_audio(output, ret * num_channels * SAMPLE_SIZE(bits_per_sample));
        }
    }

    /* Flush buffer */
    g_mutex_lock(ctrl_mutex);

    while (!stop_flag && playback->output->buffer_playing())
        g_usleep(20000);

    g_cond_signal(ctrl_cond);
    g_mutex_unlock(ctrl_mutex);

error_exit:

    g_free(input);
    g_free(output);
    wv_deattach (wvc_input, ctx);

    stop_flag = TRUE;
    playback->output->close_audio();
    return ! error;
}
コード例 #15
0
ファイル: sview.c プロジェクト: A1ve5/slurm
void *_page_thr(void *arg)
{
	page_thr_t *page = (page_thr_t *)arg;
	int num = page->page_num;
	GtkTable *table = page->table;
	display_data_t *display_data = &main_display_data[num];
	static int thread_count = 0;
	bool reset_highlight = true;

	xfree(page);
	if (!grid_init) {
		/* we need to signal any threads that are waiting */
		g_mutex_lock(grid_mutex);
		g_cond_signal(grid_cond);
		g_mutex_unlock(grid_mutex);

		/* wait for the grid to be inited */
		g_mutex_lock(grid_mutex);
		g_cond_wait(grid_cond, grid_mutex);
		g_mutex_unlock(grid_mutex);

		/* if the grid isn't there just return */
		if (!grid_init)
			return NULL;
	}

	g_mutex_lock(sview_mutex);
	thread_count++;
	g_mutex_unlock(sview_mutex);
	while (page_running == num) {
#if _DEBUG
		DEF_TIMERS;
		START_TIMER;
#endif
//		g_mutex_lock(sview_mutex);
		gdk_threads_enter();
		sview_init_grid(reset_highlight);
		reset_highlight=false;
		(display_data->get_info)(table, display_data);
		//gdk_flush();
		gdk_threads_leave();
//		g_mutex_unlock(sview_mutex);
#if _DEBUG
		END_TIMER;
		g_print("got for iteration: %s\n", TIME_STR);
#endif
		sleep(working_sview_config.refresh_delay);
		g_mutex_lock(sview_mutex);
		if (thread_count > 1) {
			g_mutex_unlock(sview_mutex);
			break;
		}
		g_mutex_unlock(sview_mutex);
	}
	g_mutex_lock(sview_mutex);
	//g_print("now here\n");
	thread_count--;
	//g_print("done decrementing\n");
	g_mutex_unlock(sview_mutex);
	//g_print("done\n");
	return NULL;
}
コード例 #16
0
ファイル: cache.c プロジェクト: redcurrant/redcurrant
GError *
sqlx_cache_open_and_lock_base(sqlx_cache_t *cache, const hashstr_t *hname,
                              gint *result)
{
    gint bd;
    GError *err = NULL;
    sqlx_base_t *base = NULL;
    GTimeVal *deadline = g_alloca(sizeof(GTimeVal));

    GRID_TRACE2("%s(%p,%s,%p)", __FUNCTION__, (void*)cache,
                hname ? hashstr_str(hname) : "NULL", (void*)result);
    EXTRA_ASSERT(cache != NULL);
    EXTRA_ASSERT(hname != NULL);
    EXTRA_ASSERT(result != NULL);

    if (cache->open_timeout >= 0) {
        g_get_current_time(deadline);
        g_time_val_add(deadline, cache->open_timeout * 1000);
    } else {
        // wait forever
        deadline = NULL;
    }

    g_mutex_lock(cache->lock);
    cache->used = TRUE;
retry:
    bd = sqlx_lookup_id(cache, hname);
    if (bd < 0) {
        if (!(err = sqlx_base_reserve(cache, hname, &base))) {
            bd = base->index;
            *result = base->index;
            sqlx_base_debug("OPEN", base);
        }
        else {
            GRID_DEBUG("No base available for [%s] (%d %s)",
                       hashstr_str(hname), err->code, err->message);
            if (sqlx_expire_first_idle_base(cache, NULL) >= 0) {
                g_clear_error(&err);
                goto retry;
            }
        }
    }
    else {
        base = GET(cache, bd);
        switch (base->status) {

        case SQLX_BASE_FREE:
            EXTRA_ASSERT(base->count_open == 0);
            EXTRA_ASSERT(base->owner == NULL);
            GRID_ERROR("free base referenced");
            g_assert_not_reached();
            break;

        case SQLX_BASE_IDLE:
        case SQLX_BASE_IDLE_HOT:
            EXTRA_ASSERT(base->count_open == 0);
            EXTRA_ASSERT(base->owner == NULL);
            sqlx_base_move_to_list(cache, base, SQLX_BASE_USED);
            base->count_open ++;
            base->owner = g_thread_self();
            *result = base->index;
            break;

        case SQLX_BASE_USED:
            EXTRA_ASSERT(base->count_open > 0);
            EXTRA_ASSERT(base->owner != NULL);
            if (base->owner != g_thread_self()) {
                // The lock is held by another thread/request
                GRID_DEBUG("Base [%s] in use by another thread (%X), waiting...",
                           hashstr_str(hname), compute_thread_id(base->owner));

                /* This is to avoid server thread starvation,
                 * due to all threads waiting on the same base. */
                if (cache->max_waiting > 0 &&
                        base->count_waiting >= cache->max_waiting) {
                    err = NEWERROR(CODE_UNAVAILABLE,
                                   "database currently in use by another request, "
                                   "and %d others threads already waiting",
                                   base->count_waiting);
                    break;
                }
                base->count_waiting++;

                if (g_cond_timed_wait(base->cond, cache->lock, deadline)) {
                    // Thread was woken up before deadline
                    GRID_DEBUG("Retrying to open [%s]", hashstr_str(hname));
                    base->count_waiting--;
                    goto retry;
                } else {
                    // Deadline has been reached
                    base->count_waiting--;
                    if (cache->open_timeout > 0) {
                        err = NEWERROR(CODE_UNAVAILABLE,
                                       "database currently in use by another request"
                                       " (we waited %ldms)",
                                       cache->open_timeout);
                    } else {
                        err = NEWERROR(CODE_UNAVAILABLE,
                                       "database currently in use by another request");
                    }
                    GRID_DEBUG("failed to open base: "
                               "in use by another request (thread %X)",
                               compute_thread_id(base->owner));
                    break;
                }
            }
            base->owner = g_thread_self();
            base->count_open ++;
            *result = base->index;
            break;

        case SQLX_BASE_CLOSING:
            EXTRA_ASSERT(base->owner != NULL);
            // Just wait for a notification then retry
            if (g_cond_timed_wait(base->cond, cache->lock, deadline))
                goto retry;
            else {
                err = NEWERROR(CODE_UNAVAILABLE,
                               "Database stuck in closing state");
                break;
            }
        }
    }

    if (base) {
        if (!err) {
            sqlx_base_debug(__FUNCTION__, base);
            EXTRA_ASSERT(base->owner == g_thread_self());
            EXTRA_ASSERT(base->count_open > 0);
        }
        g_cond_signal(base->cond);
    }
    g_mutex_unlock(cache->lock);
    return err;
}
コード例 #17
0
ファイル: find.c プロジェクト: tomszilagyi/owl
void find_stop( find_context_t* fc ) {
    fc->running = 0;

    g_cond_signal( &fc->find_cond );
}
コード例 #18
0
ファイル: cache.c プロジェクト: redcurrant/redcurrant
GError *
sqlx_cache_unlock_and_close_base(sqlx_cache_t *cache, gint bd, gboolean force)
{
    GError *err = NULL;
    sqlx_base_t *base;

    GRID_TRACE2("%s(%p,%d,%d)", __FUNCTION__, (void*)cache, bd, force);

    EXTRA_ASSERT(cache != NULL);
    if (base_id_out(cache, bd))
        return NEWERROR(500, "invalid base id=%d", bd);

    g_mutex_lock(cache->lock);
    cache->used = TRUE;

    base = GET(cache,bd);
    switch (base->status) {

    case SQLX_BASE_FREE:
        EXTRA_ASSERT(base->count_open == 0);
        EXTRA_ASSERT(base->owner == NULL);
        GRID_ERROR("Trying to close a free base");
        g_assert_not_reached();
        break;

    case SQLX_BASE_IDLE:
    case SQLX_BASE_IDLE_HOT:
        EXTRA_ASSERT(base->count_open == 0);
        EXTRA_ASSERT(base->owner == NULL);
        GRID_ERROR("Trying to close a closed base");
        g_assert_not_reached();
        break;

    case SQLX_BASE_USED:
        EXTRA_ASSERT(base->count_open > 0);
        // held by the current thread
        if (!(-- base->count_open)) { // to be closed
            if (force) {
                _expire_base(cache, base);
            }
            else {
                sqlx_base_debug("CLOSING", base);
                base->owner = NULL;
                if (base->heat >= cache->heat_threshold)
                    sqlx_base_move_to_list(cache, base, SQLX_BASE_IDLE_HOT);
                else
                    sqlx_base_move_to_list(cache, base, SQLX_BASE_IDLE);
            }
        }
        break;

    case SQLX_BASE_CLOSING:
        EXTRA_ASSERT(base->owner != NULL);
        EXTRA_ASSERT(base->owner != g_thread_self());
        GRID_ERROR("Trying to close a base being closed");
        g_assert_not_reached();
        break;
    }

    if (base && !err)
        sqlx_base_debug(__FUNCTION__, base);
    g_cond_signal(base->cond);
    g_mutex_unlock(cache->lock);
    return err;
}
コード例 #19
0
static gpointer
book_view_thread (gpointer data)
{
    EBookBackendScalix *bs;
    gboolean stopped;
    const char *query;
    EDataBookView *book_view;
    EBookBackendScalixPrivate *priv;
    ScalixBackendSearchClosure *closure;
    GList *iter;
    ScanContext context;
    gboolean res;

    book_view = data;
    closure = closure_get (book_view);
    bs = closure->bs;
    priv = E_BOOK_BACKEND_SCALIX_GET_PRIVATE (bs);
    stopped = FALSE;

    bonobo_object_ref (book_view);

    if (priv->container == NULL) {
        e_data_book_view_notify_complete (book_view,
                                          GNOME_Evolution_Addressbook_AuthenticationRequired);

        bonobo_object_unref (book_view);
        return NULL;
    }

    query = e_data_book_view_get_card_query (book_view);
    context.sexp = e_book_backend_sexp_new (query);
    context.backend = E_BOOK_BACKEND (bs);
    context.obj_list = NULL;
    context.return_objects = TRUE;

    if (!(context.search_needed = query_is_search (query))) {
        e_data_book_view_notify_status_message (book_view, _("Loading..."));
    } else {
        e_data_book_view_notify_status_message (book_view, _("Searching..."));
    }

    g_mutex_lock (closure->mutex);
    g_cond_signal (closure->cond);
    g_mutex_unlock (closure->mutex);

    res = scalix_container_foreach (priv->container, scan_objects, &context);

    if (res == FALSE) {
        e_data_book_view_notify_complete (book_view,
                                          GNOME_Evolution_Addressbook_OtherError);
        bonobo_object_unref (book_view);
        return NULL;
    }

    for (iter = context.obj_list; iter; iter = iter->next) {

        g_mutex_lock (closure->mutex);
        stopped = closure->stopped;
        g_mutex_unlock (closure->mutex);

        if (stopped) {
            break;
        }

        e_data_book_view_notify_update (book_view, iter->data);
        g_object_unref (iter->data);
    }

    /*FIXME: we leek objects if stopped */
    g_list_free (context.obj_list);

    if (!stopped) {
        e_data_book_view_notify_complete (book_view,
                                          GNOME_Evolution_Addressbook_Success);
    }

    bonobo_object_unref (book_view);

    return NULL;
}
コード例 #20
0
ファイル: dispatcher.c プロジェクト: Torture/MegaTunix
/*!
 \brief gui_dispatcher() is a GTK+ timeout that runs 30 tiems per second checking
 for message on the dispatch queue which handles gui operations after a thread
 function runs, This will attempt to handle multiple messages at a time if the
 queue has multiple message queued up.
 \param data (gpointer) unused
 \returns TRUE 
 */
gboolean gui_dispatcher(gpointer data)
{
	gint len=0;
	gint i=0;
	UpdateFunction val = 0;
	gint count = 0;
	GtkWidget *widget = NULL;
	Io_Message *message = NULL;
	Text_Message *t_message = NULL;
	Widget_Update *w_update = NULL;
	QFunction *qfunc = NULL;
	extern volatile gboolean leaving;
	/*extern gint mem_view_style[];*/

	if (!gui_dispatch_queue) /*queue not built yet... */
	{
		g_cond_signal(gui_dispatch_cond);
		return TRUE;
	}
	/* Endless Loop, wait for message, processs and repeat... */
trypop:
	/*printf("gui_dispatch queue length is %i\n",g_async_queue_length(gui_dispatch_queue));*/
	if (leaving)
	{
		g_cond_signal(gui_dispatch_cond);
		return TRUE;
	}
	message = g_async_queue_try_pop(gui_dispatch_queue);
	if (!message)
	{
		/*	printf("no messages waiting, returning\n");*/
		g_cond_signal(gui_dispatch_cond);
		return TRUE;
	}

	if (message->functions != NULL)
	{
		len = message->functions->len;
		for (i=0;i<len;i++)
		{
			if (leaving)
			{
				dealloc_message(message);
				g_cond_signal(gui_dispatch_cond);
				return TRUE;
			}

			val = g_array_index(message->functions,UpdateFunction, i);
			/*printf("gui_dispatcher\n");*/
			switch ((UpdateFunction)val)
			{
				case UPD_LOGBAR:
					/*printf("logbar update\n");*/
					t_message = (Text_Message *)message->payload;
					gdk_threads_enter();
					update_logbar(t_message->view_name,t_message->tagname,t_message->msg,t_message->count,t_message->clear);
					gdk_threads_leave();
					dealloc_textmessage(t_message);
					message->payload = NULL;
					break;
				case UPD_RUN_FUNCTION:
					/*printf("run function\n");*/
					qfunc = (QFunction *)message->payload;
					gdk_threads_enter();
					run_post_functions(qfunc->func_name);
					gdk_threads_leave();
					dealloc_qfunction(qfunc);
					message->payload = NULL;
					break;

				case UPD_WIDGET:
					/*printf("widget update\n");*/
					widget = NULL;
					w_update = (Widget_Update *)message->payload;
					switch (w_update->type)
					{
						case MTX_ENTRY:
							/*printf("entry\n");*/
							if (NULL == (widget = lookup_widget(w_update->widget_name)))
								break;
							gdk_threads_enter();
							gtk_entry_set_text(GTK_ENTRY(widget),w_update->msg);
							gdk_threads_leave();
							break;
						case MTX_LABEL:
							/*printf("label\n");*/
							if (NULL == (widget = lookup_widget(w_update->widget_name)))
								break;
							gdk_threads_enter();
							gtk_label_set_text(GTK_LABEL(widget),w_update->msg);
							gdk_threads_leave();
							break;
						case MTX_TITLE:
							/*printf("title\n");*/
							gdk_threads_enter();
							set_title(g_strdup(w_update->msg));
							gdk_threads_leave();
							break;
						case MTX_SENSITIVE:
							/*printf("sensitivity change\n");*/
							if (NULL == (widget = lookup_widget(w_update->widget_name)))
								break;
							gdk_threads_enter();
							gtk_widget_set_sensitive(GTK_WIDGET(widget),w_update->state);
							gdk_threads_leave();
							break;
						default:
							break;
					}
					dealloc_w_update(w_update);
					message->payload = NULL;
					break;
					gdk_threads_enter();
					reset_temps(OBJ_GET(global_data,"temp_units"));
					gdk_threads_leave();
					/*
					   case UPD_RAW_MEMORY:
					   update_raw_memory_view(mem_view_style[message->offset],message->offset);
					   break;
					 */
			}

			gdk_threads_enter();
			while (gtk_events_pending())
			{
				if (leaving)
					goto dealloc;
				gtk_main_iteration();
			}
			gdk_threads_leave();
		}
	}
dealloc:
	dealloc_message(message);
	/*printf ("deallocation of dispatch message complete\n");*/
	count++;
	/* try to handle up to 4 messages at a time.  If this is 
	 * set too high, we can cause the timeout to hog the gui if it's
	 * too low, things can fall behind. (GL redraw ;( )
	 * */
	if ((count < 3) && (!leaving))
	{
		/*printf("trying to handle another message\n");*/
		goto trypop;
	}
	/*printf("returning\n");*/
	g_cond_signal(gui_dispatch_cond);
	return TRUE;
}
コード例 #21
0
static void
gst_droidcamsrc_dev_compressed_image_callback (void *user, DroidMediaData * mem)
{
  GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user;
  GstDroidCamSrc *src = GST_DROIDCAMSRC (GST_PAD_PARENT (dev->imgsrc->pad));
  size_t size = mem->size;
  void *data = mem->data;
  GstBuffer *buffer;
  GstTagList *tags;
  GstEvent *event = NULL;
  void *d;

  GST_DEBUG_OBJECT (src, "dev compressed image callback");

  if (!data) {
    GST_ERROR_OBJECT (src, "invalid memory from camera hal");
    return;
  }

  /* TODO: research a way to get rid of the memcpy */
  d = g_malloc (size);
  memcpy (d, data, size);
  buffer = gst_buffer_new_wrapped (d, size);
  if (!dev->img->image_preview_sent) {
    gst_droidcamsrc_post_message (src,
        gst_structure_new_empty (GST_DROIDCAMSRC_CAPTURE_END));
    /* TODO: generate and send preview if we don't get it from HAL */
    dev->img->image_preview_sent = TRUE;
  }

  gst_droidcamsrc_timestamp (src, buffer);

  tags = gst_droidcamsrc_exif_tags_from_jpeg_data (d, size);
  if (tags) {
    GST_INFO_OBJECT (src, "pushing tags %" GST_PTR_FORMAT, tags);
    event = gst_event_new_tag (tags);
  }

  g_mutex_lock (&dev->imgsrc->lock);

  // TODO: get the correct lock
  if (event) {
    src->imgsrc->pending_events =
        g_list_append (src->imgsrc->pending_events, event);
  }

  g_queue_push_tail (dev->imgsrc->queue, buffer);
  g_cond_signal (&dev->imgsrc->cond);
  g_mutex_unlock (&dev->imgsrc->lock);

  /* we need to start restart the preview
   * android demands this but GStreamer does not know about it.
   */
  g_rec_mutex_lock (dev->lock);
  dev->running = FALSE;
  g_rec_mutex_unlock (dev->lock);

  gst_droidcamsrc_dev_start (dev, TRUE);

  g_mutex_lock (&src->capture_lock);
  --src->captures;
  g_mutex_unlock (&src->capture_lock);

  g_object_notify (G_OBJECT (src), "ready-for-capture");
}
コード例 #22
0
ファイル: dispatcher.c プロジェクト: Torture/MegaTunix
/*!
 \brief pf_dispatcher() is a GTK+ timeout that runs 10 times per second checking
 for message on the dispatch queue which handles gui operations after a thread
 function runs, This will attempt to handle multiple messages at a time if the
 queue has multiple message queued up.
 \param data (gpointer) unused
 \returns TRUE 
 */
gboolean pf_dispatcher(gpointer data)
{
	gint len=0;
	gint i=0;
	PostFunction *pf=NULL;
	gint count = 0;
	Io_Message *message = NULL;
	extern volatile gboolean leaving;

	if (!pf_dispatch_queue) /*queue not built yet... */
	{
		g_cond_signal(pf_dispatch_cond);
		return TRUE;
	}
trypop:
	/*printf("pf_dispatch queue length is %i\n",g_async_queue_length(pf_dispatch_queue));*/
	if (leaving)
	{
		g_cond_signal(pf_dispatch_cond);
		return TRUE;
	}
	/*
	if (g_async_queue_length(pf_dispatch_queue) >40)
		printf("WARNING: Postfunction dispatch queue is over 40\n");
	*/
		
	message = g_async_queue_try_pop(pf_dispatch_queue);
	if (!message)
	{
		/*	printf("no messages waiting, returning\n");*/
		g_cond_signal(pf_dispatch_cond);
		return TRUE;
	}
	if (!message->status)
	{
		/* Message failed at some point, do NOT run post functions
		 * in this case.
		 */
		dealloc_message(message);
		g_cond_signal(pf_dispatch_cond);
		return TRUE;
	}

	if (message->command->post_functions != NULL)
	{
		len = message->command->post_functions->len;
		for (i=0;i<len;i++)
		{
			if (leaving)
			{
				dealloc_message(message);
				g_cond_signal(pf_dispatch_cond);
				return TRUE;
			}

			pf = g_array_index(message->command->post_functions,PostFunction *, i);
			/*printf("dispatching post function %s\n",pf->name);*/
			if (!pf)
			{
				printf(_("ERROR postfunction was NULL, continuing\n"));
				continue;
			}
			if (pf->w_arg)
			{
				if (!pf->function_w_arg)
					printf(_("ERROR, couldn't find function with arg \"%s\"\n"),pf->name);
				else
					pf->function_w_arg(message);
			}
			else
			{
				if (!pf->function)
					printf(_("ERROR, couldn't find function \"%s\"\n"),pf->name);
				else
					pf->function();
			}

			gdk_threads_enter();
			while (gtk_events_pending())
			{
				if (leaving)
				{
					gdk_threads_leave();
					goto dealloc;
				}
				gtk_main_iteration();
			}
			gdk_threads_leave();
		}
	}
コード例 #23
0
static void
gst_droidcamsrc_dev_frame_available (void *user)
{
  GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user;
  GstDroidCamSrc *src = GST_DROIDCAMSRC (GST_PAD_PARENT (dev->imgsrc->pad));
  GstDroidCamSrcPad *pad = dev->vfsrc;
  DroidMediaBuffer *buffer;
  GstMemory *mem;
  DroidMediaRect rect;
  guint width, height;
  GstBuffer *buff;
  DroidMediaBufferCallbacks cb;
  GstFlowReturn flow_ret;
  DroidMediaBufferInfo info;

  GST_DEBUG_OBJECT (src, "frame available");

  if (!pad->running) {
    GST_DEBUG_OBJECT (src, "vfsrc pad task is not running");

    goto acquire_and_release;
  }

  /* We are accessing this without a lock because:
   * 1) We should not be called while preview is stopped and this is when we manipulate this flag
   * 2) We can get called when we start the preview and we will deadlock because the lock is already held
   */
  if (dev->use_raw_data) {
    goto acquire_and_release;
  }

  flow_ret = gst_buffer_pool_acquire_buffer (dev->pool, &buff, NULL);
  if (flow_ret != GST_FLOW_OK) {
    GST_WARNING_OBJECT (src, "failed to acquire buffer from pool: %s",
        gst_flow_get_name (flow_ret));

    goto acquire_and_release;
  }

  cb.ref = (DroidMediaCallback) gst_buffer_ref;
  cb.unref = (DroidMediaCallback) gst_buffer_unref;
  cb.data = buff;

  mem =
      gst_droid_media_buffer_allocator_alloc (dev->media_allocator, dev->queue,
      &cb);
  if (!mem) {
    GST_ERROR_OBJECT (src, "failed to acquire buffer from droidmedia");
    gst_buffer_unref (buff);
    return;
  }

  buffer = gst_droid_media_buffer_memory_get_buffer (mem);

  gst_buffer_insert_memory (buff, 0, mem);
  gst_droidcamsrc_timestamp (src, buff);

  rect = droid_media_buffer_get_crop_rect (buffer);
  width = droid_media_buffer_get_width (buffer);
  height = droid_media_buffer_get_height (buffer);

  gst_droidcamsrc_dev_prepare_buffer (dev, buff, rect, width, height,
      GST_VIDEO_FORMAT_YV12);

  g_mutex_lock (&pad->lock);
  g_queue_push_tail (pad->queue, buff);
  g_cond_signal (&pad->cond);
  g_mutex_unlock (&pad->lock);

  GST_OBJECT_LOCK (src);
  src->crop_rect = rect;
  GST_OBJECT_UNLOCK (src);
  return;

acquire_and_release:
  if (droid_media_buffer_queue_acquire_and_release (dev->queue, &info)) {
    GST_OBJECT_LOCK (src);
    src->crop_rect = info.crop_rect;
    GST_OBJECT_UNLOCK (src);
  }
}
コード例 #24
0
ファイル: gstappsink.c プロジェクト: fanc999/gst-plugins-base
static gboolean
gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
{
  GstAppSink *appsink = GST_APP_SINK_CAST (sink);
  GstAppSinkPrivate *priv = appsink->priv;

  switch (event->type) {
    case GST_EVENT_SEGMENT:
      g_mutex_lock (&priv->mutex);
      GST_DEBUG_OBJECT (appsink, "receiving SEGMENT");
      g_queue_push_tail (priv->queue, gst_event_ref (event));
      if (!priv->preroll)
        gst_event_copy_segment (event, &priv->preroll_segment);
      g_mutex_unlock (&priv->mutex);
      break;
    case GST_EVENT_EOS:{
      gboolean emit = TRUE;

      g_mutex_lock (&priv->mutex);
      GST_DEBUG_OBJECT (appsink, "receiving EOS");
      priv->is_eos = TRUE;
      g_cond_signal (&priv->cond);
      g_mutex_unlock (&priv->mutex);

      g_mutex_lock (&priv->mutex);
      /* wait until all buffers are consumed or we're flushing.
       * Otherwise we might signal EOS before all buffers are
       * consumed, which is a bit confusing for the application
       */
      while (priv->num_buffers > 0 && !priv->flushing && priv->wait_on_eos)
        g_cond_wait (&priv->cond, &priv->mutex);
      if (priv->flushing)
        emit = FALSE;
      g_mutex_unlock (&priv->mutex);

      if (emit) {
        /* emit EOS now */
        if (priv->callbacks.eos)
          priv->callbacks.eos (appsink, priv->user_data);
        else
          g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_EOS], 0);
      }

      break;
    }
    case GST_EVENT_FLUSH_START:
      /* we don't have to do anything here, the base class will call unlock
       * which will make sure we exit the _render method */
      GST_DEBUG_OBJECT (appsink, "received FLUSH_START");
      break;
    case GST_EVENT_FLUSH_STOP:
      g_mutex_lock (&priv->mutex);
      GST_DEBUG_OBJECT (appsink, "received FLUSH_STOP");
      gst_app_sink_flush_unlocked (appsink);
      g_mutex_unlock (&priv->mutex);
      break;
    default:
      break;
  }
  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
}
コード例 #25
0
ファイル: flush_worker.c プロジェクト: Aruiwen/cloudxy
int flush_work(gpointer data){
	int ret = 0;
	CACHE_CTRL *cctrl = (CACHE_CTRL*)data;
	GTimeVal expired;
	char *tmp_buf = (char *)g_malloc0(cctrl->block_size \
			*cctrl->flush_once_size);
	g_assert(tmp_buf);
	while (!cctrl->flush_worker_should_exit) {
		HLOG_DEBUG("-- flush worker doing --");
		g_get_current_time(&expired);
		g_time_val_add(&expired, cctrl->flush_interval * 1000 * 1000);
		g_mutex_lock(cctrl->cache_mutex);
		gboolean res = g_cond_timed_wait(cctrl->flush_waken_cond, \
				cctrl->cache_mutex, &expired);
		g_mutex_unlock(cctrl->cache_mutex); 
		HLOG_DEBUG(" time wait res for cond is :%d !",res);
		if (cctrl->flush_worker_should_exit) {
			HLOG_INFO("-- flush worker should exit --");
			break;
		}

		do {
			GSList *continue_blocks = NULL;
			ret = get_continues_blocks(cctrl, &continue_blocks);
			g_assert(ret==0);
			uint32_t blocks_count = g_slist_length(continue_blocks);
			uint32_t buff_len = blocks_count *cctrl->block_size;
			HLOG_DEBUG("--blocks_count:%d, buff_len:%d--", \
					blocks_count, buff_len);
			if (res == TRUE && buff_len == 0) {
				HLOG_ERROR("Never reach here");
				g_assert(0);
			}


			if (buff_len == 0) {
				HLOG_DEBUG("do not need flush now");
				break;
			}
			if (NULL == cctrl->write_callback_func) {
				HLOG_WARN("--not given flush callback func--");
				break;
			} 
			//char* tmp_buf = g_malloc0(buff_len);
			//g_assert(tmp_buf!=NULL);
			uint32_t start_no;
			uint32_t end_no; 
			int i = 0;
			for (i = 0; i < blocks_count; i++) {
				block_t *block = g_slist_nth_data(continue_blocks, i);
				if (i == 0) {
					start_no = block->block_no;
				}
				if (i == blocks_count-1) {
					end_no = block->block_no;
				}
				memcpy(tmp_buf + i * cctrl->block_size, \
						block->block, cctrl->block_size);
			}
			//HLOG_DEBUG("--tmp_buf:%p",tmp_buf);
			ret = cctrl->write_callback_func(cctrl->write_callback_user_param, \
					tmp_buf, start_no,end_no);
			g_assert(ret >= 0);
			//g_free(tmp_buf);
			if (ret >= 0 ) {
				HLOG_DEBUG("--signal write thread--");
				g_mutex_lock(cctrl->cache_mutex);
				__free_from_cache(cctrl, continue_blocks);
				//g_cond_broadcast(cctrl->writer_waken_cond);
				g_cond_signal(cctrl->writer_waken_cond);
				g_mutex_unlock(cctrl->cache_mutex);
				g_slist_free(continue_blocks);
				//HLOG_DEBUG("--return blocks to cache over--");
			}
		} while (get_cache_free_size(cctrl) < cctrl->flush_trigger_level \
				*cctrl->cache_size / 100 || (res == 0 && get_cache_free_size(cctrl) != 0));
	}
	g_free(tmp_buf);
	HLOG_INFO("--flush worker exit--");
	return 0;
}                        
コード例 #26
0
ファイル: gstappsink.c プロジェクト: fanc999/gst-plugins-base
static GstFlowReturn
gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
{
  GstFlowReturn ret;
  GstAppSink *appsink = GST_APP_SINK_CAST (psink);
  GstAppSinkPrivate *priv = appsink->priv;
  gboolean emit;

restart:
  g_mutex_lock (&priv->mutex);
  if (priv->flushing)
    goto flushing;

  /* queue holding caps event might have been FLUSHed,
   * but caps state still present in pad caps */
  if (G_UNLIKELY (!priv->last_caps &&
          gst_pad_has_current_caps (GST_BASE_SINK_PAD (psink)))) {
    priv->last_caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (psink));
    GST_DEBUG_OBJECT (appsink, "activating pad caps %" GST_PTR_FORMAT,
        priv->last_caps);
  }

  GST_DEBUG_OBJECT (appsink, "pushing render buffer %p on queue (%d)",
      buffer, priv->num_buffers);

  while (priv->max_buffers > 0 && priv->num_buffers >= priv->max_buffers) {
    if (priv->drop) {
      GstBuffer *old;

      /* we need to drop the oldest buffer and try again */
      if ((old = dequeue_buffer (appsink))) {
        GST_DEBUG_OBJECT (appsink, "dropping old buffer %p", old);
        gst_buffer_unref (old);
      }
    } else {
      GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d",
          priv->num_buffers, priv->max_buffers);

      if (priv->unlock) {
        /* we are asked to unlock, call the wait_preroll method */
        g_mutex_unlock (&priv->mutex);
        if ((ret = gst_base_sink_wait_preroll (psink)) != GST_FLOW_OK)
          goto stopping;

        /* we are allowed to continue now */
        goto restart;
      }

      /* wait for a buffer to be removed or flush */
      g_cond_wait (&priv->cond, &priv->mutex);
      if (priv->flushing)
        goto flushing;
    }
  }
  /* we need to ref the buffer when pushing it in the queue */
  g_queue_push_tail (priv->queue, gst_buffer_ref (buffer));
  priv->num_buffers++;
  g_cond_signal (&priv->cond);
  emit = priv->emit_signals;
  g_mutex_unlock (&priv->mutex);

  if (priv->callbacks.new_sample) {
    ret = priv->callbacks.new_sample (appsink, priv->user_data);
  } else {
    ret = GST_FLOW_OK;
    if (emit)
      g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_SAMPLE], 0, &ret);
  }
  return ret;

flushing:
  {
    GST_DEBUG_OBJECT (appsink, "we are flushing");
    g_mutex_unlock (&priv->mutex);
    return GST_FLOW_FLUSHING;
  }
stopping:
  {
    GST_DEBUG_OBJECT (appsink, "we are stopping");
    return ret;
  }
}
コード例 #27
0
ファイル: gdigi.c プロジェクト: afflerbach/gdigi
void push_message(GString *msg)
{
    if (((unsigned char)msg->str[0] == 0xF0) && ((unsigned char)msg->str[msg->len-1] == 0xF7))
        g_message("Pushing correct message!");
    else
        g_warning("Pushing incorrect message!");

    int x;
    for (x = 0; x<msg->len; x++)
        printf("%02x ", (unsigned char)msg->str[x]);
    printf("\n");

    switch (get_message_id(msg)) {
        case ACK:
            g_message("Received ACK");
            g_string_free(msg, TRUE);
            return;

        case NACK:
            g_message("Received NACK");
            g_string_free(msg, TRUE);
            return;

        case RECEIVE_PARAMETER_VALUE:
            unpack_message(msg);
            SettingParam *param = setting_param_new_from_data(&msg->str[8], NULL);
            g_message("Received parameter change ID: %d Position: %d Value: %d", param->id, param->position, param->value);

            GDK_THREADS_ENTER();
            apply_setting_param_to_gui(param);
            GDK_THREADS_LEAVE();

            setting_param_free(param);
            g_string_free(msg, TRUE);
            return;

        case RECEIVE_DEVICE_NOTIFICATION:
            unpack_message(msg);
            unsigned char *str = (unsigned char*)msg->str;
            switch (str[8]) {
                case NOTIFY_PRESET_MOVED:
                    if (str[11] == PRESETS_EDIT_BUFFER && str[12] == 0) {
                        g_message("Loaded preset %d from bank %d", str[10], str[9]);

                        GDK_THREADS_ENTER();
                        g_timeout_add(0, apply_current_preset_to_gui, NULL);
                        GDK_THREADS_LEAVE();
                    } else
                        g_message("%d %d moved to %d %d", str[9], str[10], str[11], str[12]);
                default:
                    g_message("Received unhandled device notification");
            }
            g_string_free(msg, TRUE);
            return;
        default:
            g_mutex_lock(message_queue_mutex);
            g_queue_push_tail(message_queue, msg);
            g_cond_signal(message_queue_cond);
            g_mutex_unlock(message_queue_mutex);
    }
}
コード例 #28
0
static gboolean
do_manage_comp_idle (struct _manage_comp *mc)
{
	GError *error = NULL;
	ECalClientSourceType source_type = E_CAL_CLIENT_SOURCE_TYPE_LAST;
	ECalComponent *edit_comp = NULL;

	g_return_val_if_fail (mc, FALSE);

	source_type = e_cal_client_get_source_type (mc->client);

	if (source_type == E_CAL_CLIENT_SOURCE_TYPE_LAST) {
		free_manage_comp_struct (mc);

		g_warning ("mail-to-task: Incorrect call of %s, no data given", G_STRFUNC);
		return FALSE;
	}

	if (mc->stored_comp) {
		const gchar *ask = get_question_edit_old (source_type);

		if (ask) {
			gchar *msg = g_strdup_printf (ask, icalcomponent_get_summary (mc->stored_comp) ? icalcomponent_get_summary (mc->stored_comp) : _("[No Summary]"));
			gint chosen;

			chosen = do_ask (msg, TRUE);

			if (chosen == GTK_RESPONSE_YES) {
				edit_comp = e_cal_component_new ();
				if (!e_cal_component_set_icalcomponent (edit_comp, icalcomponent_new_clone (mc->stored_comp))) {
					g_object_unref (edit_comp);
					edit_comp = NULL;
					error = g_error_new (
						E_CAL_CLIENT_ERROR,
						E_CAL_CLIENT_ERROR_INVALID_OBJECT,
						"%s", _("Invalid object returned from a server"));

				}
			} else if (chosen == GTK_RESPONSE_NO) {
				/* user wants to create a new event, thus generate a new UID */
				gchar *new_uid = e_cal_component_gen_uid ();
				edit_comp = mc->comp;
				e_cal_component_set_uid (edit_comp, new_uid);
				e_cal_component_set_recurid (edit_comp, NULL);
				g_free (new_uid);
			}
			g_free (msg);
		}
	} else {
		edit_comp = mc->comp;
	}

	if (edit_comp) {
		EShell *shell;
		ECompEditor *comp_editor;

		/* FIXME Pass in the EShell instance. */
		shell = e_shell_get_default ();
		comp_editor = get_component_editor (
			shell, mc->client, edit_comp,
			edit_comp == mc->comp, &error);

		if (comp_editor && !error) {
			comp_editor_title_changed (GTK_WIDGET (comp_editor), NULL, mc);

			e_signal_connect_notify (
				comp_editor, "notify::title",
				G_CALLBACK (comp_editor_title_changed), mc);
			g_signal_connect (
				comp_editor, "editor-closed",
				G_CALLBACK (comp_editor_closed), mc);

			gtk_window_present (GTK_WINDOW (comp_editor));

			if (edit_comp != mc->comp)
				g_object_unref (edit_comp);
		} else {
			g_warning ("Failed to create event editor: %s", error ? error->message : "Unknown error");
			g_cond_signal (&mc->cond);
		}
	} else {
		/* User canceled editing already existing event, so
		 * treat it as if he just closed the editor window. */
		comp_editor_closed (NULL, FALSE, mc);
	}

	if (error != NULL) {
		e_notice (
			NULL, GTK_MESSAGE_ERROR,
			_("An error occurred during processing: %s"),
			error->message);
		g_clear_error (&error);
	}

	return FALSE;
}
コード例 #29
0
static int
gst_droidcamsrc_stream_window_enqueue_buffer (struct preview_stream_ops *w,
    buffer_handle_t * buffer)
{
  GstDroidCamSrcStreamWindow *win;
  GstDroidCamSrc *src;
  GstBuffer *buff;
  int ret;
  GstVideoCropMeta *meta;

  GST_DEBUG ("enqueue buffer %p", buffer);

  win = container_of (w, GstDroidCamSrcStreamWindow, window);

  g_mutex_lock (&win->lock);

  src = GST_DROIDCAMSRC (GST_PAD_PARENT (win->pad->pad));

  buff = gst_droidcamsrc_stream_window_get_buffer (buffer);

  if (!buff) {
    GST_ERROR ("no buffer corresponding to handle %p", buffer);
    ret = -1;
    goto unlock_and_out;
  }

  /* if the buffer pool is not our current pool then just release it */
  if (buff->pool != GST_BUFFER_POOL (win->pool)) {
    GST_DEBUG ("releasing old buffer %p", buffer);
    gst_buffer_unref (buff);
    ret = 0;
    goto unlock_and_out;
  }

  /* now update crop meta */
  meta = gst_buffer_get_video_crop_meta (buff);
  meta->x = win->left;
  meta->y = win->top;
  meta->width = win->right - win->left;
  meta->height = win->bottom - win->top;

  GST_LOG
      ("window width = %d, height = %d, crop info: left = %d, top = %d, right = %d, bottom = %d",
      win->width, win->height, win->left, win->top, win->right, win->bottom);

  g_mutex_unlock (&win->lock);

  /* it should be safe to access that variable without locking.
   * pad gets activated during READY_TO_PAUSED and deactivated during
   * PAUSED_TO_READY while we start the preview during PAUSED_TO_PLAYING
   * and stop it during PLAYING_TO_PAUSED.
   */
  if (!win->pad->running) {
    gst_buffer_unref (buff);
    GST_DEBUG ("unreffing buffer because pad task is not running");
    ret = 0;
    goto unlock_pad_and_out;
  }
  // TODO: duration, offset, offset_end ...
  gst_droidcamsrc_timestamp (src, buff);

  g_mutex_lock (&win->pad->queue_lock);

  g_queue_push_tail (win->pad->queue, buff);

  g_cond_signal (&win->pad->cond);

  ret = 0;
  goto unlock_pad_and_out;

unlock_and_out:
  g_mutex_unlock (&win->lock);

  return ret;

unlock_pad_and_out:
  g_mutex_unlock (&win->pad->queue_lock);

  return ret;
}
コード例 #30
0
static gboolean
gst_ss_demux_handle_src_event (GstPad * pad, GstEvent * event)
{
  GstSSDemux *demux = GST_SS_DEMUX (gst_pad_get_parent (pad));

  switch (event->type) {
    case GST_EVENT_SEEK:
    {
      gdouble rate;
      GstFormat format;
      GstSeekFlags flags;
      GstSeekType start_type, stop_type;
      gint64 start, stop;
      gint i = 0;
      GstSSDemuxStream *stream = NULL;

      GST_INFO_OBJECT (demux, "Received GST_EVENT_SEEK");

      // TODO: should be able to seek in DVR window
      if (GST_SSM_PARSE_IS_LIVE_PRESENTATION (demux->parser)) {
        GST_WARNING_OBJECT (demux, "Received seek event for live stream");
        return FALSE;
      }

      gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
          &stop_type, &stop);

      if (format != GST_FORMAT_TIME) {
        GST_WARNING_OBJECT (demux, "Only time format is supported in seek");
        return FALSE;
      }

      GST_DEBUG_OBJECT (demux, "seek event, rate: %f start: %" GST_TIME_FORMAT
          " stop: %" GST_TIME_FORMAT, rate, GST_TIME_ARGS (start),
          GST_TIME_ARGS (stop));


      for( i = 0; i < SS_STREAM_NUM; i++) {
        if (stream = demux->streams[i]) {
          g_cond_signal (stream->cond);
          gst_task_stop (stream->stream_task);
        }
      }

      if (flags & GST_SEEK_FLAG_FLUSH) {
        GST_INFO_OBJECT (demux, "sending flush start");

        for( i = 0; i < SS_STREAM_NUM; i++) {
          if (stream = demux->streams[i]) {
            gst_pad_push_event (stream->pad, gst_event_new_flush_start ());
          }
        }
      }

      gst_ssm_parse_seek_manifest (demux->parser, start);

      if (flags & GST_SEEK_FLAG_FLUSH) {
        GST_INFO_OBJECT (demux, "sending flush stop");
        for( i = 0; i < SS_STREAM_NUM; i++) {
          if (stream = demux->streams[i]) {
            gst_pad_push_event (stream->pad, gst_event_new_flush_stop ());
            GST_LOG_OBJECT (stream->pad, "Starting pad TASK again...\n");
            stream->sent_ns = FALSE;
            stream->frag_cnt = 0; /*resetting to start buffering on SEEK */
            gst_task_start (stream->stream_task);
          }
        }
      }

      return TRUE;
    }
    default:
      break;
  }

  return gst_pad_event_default (pad, event);
}