void
gst_audio_fx_base_fir_filter_set_kernel (GstAudioFXBaseFIRFilter * self,
    gdouble * kernel, guint kernel_length, guint64 latency,
    const GstAudioInfo * info)
{
  gboolean latency_changed;
  GstAudioFormat format;
  gint channels;

  g_return_if_fail (kernel != NULL);
  g_return_if_fail (self != NULL);

  g_mutex_lock (&self->lock);

  latency_changed = (self->latency != latency
      || (!self->low_latency && self->kernel_length < FFT_THRESHOLD
          && kernel_length >= FFT_THRESHOLD)
      || (!self->low_latency && self->kernel_length >= FFT_THRESHOLD
          && kernel_length < FFT_THRESHOLD));

  /* FIXME: If the latency changes, the buffer size changes too and we
   * have to drain in any case until this is fixed in the future */
  if (self->buffer && (!self->drain_on_changes || latency_changed)) {
    gst_audio_fx_base_fir_filter_push_residue (self);
    self->start_ts = GST_CLOCK_TIME_NONE;
    self->start_off = GST_BUFFER_OFFSET_NONE;
    self->nsamples_out = 0;
    self->nsamples_in = 0;
    self->buffer_fill = 0;
  }

  g_free (self->kernel);
  if (!self->drain_on_changes || latency_changed) {
    g_free (self->buffer);
    self->buffer = NULL;
    self->buffer_fill = 0;
    self->buffer_length = 0;
  }

  self->kernel = kernel;
  self->kernel_length = kernel_length;

  if (info) {
    format = GST_AUDIO_INFO_FORMAT (info);
    channels = GST_AUDIO_INFO_CHANNELS (info);
  } else {
    format = GST_AUDIO_FILTER_FORMAT (self);
    channels = GST_AUDIO_FILTER_CHANNELS (self);
  }

  gst_audio_fx_base_fir_filter_calculate_frequency_response (self);
  gst_audio_fx_base_fir_filter_select_process_function (self, format, channels);

  if (latency_changed) {
    self->latency = latency;
    gst_element_post_message (GST_ELEMENT (self),
        gst_message_new_latency (GST_OBJECT (self)));
  }

  g_mutex_unlock (&self->lock);
}
static GstFlowReturn
gst_amc_audio_dec_drain (GstAmcAudioDec * self)
{
  GstFlowReturn ret;
  gint idx;

  GST_DEBUG_OBJECT (self, "Draining codec");
  if (!self->started) {
    GST_DEBUG_OBJECT (self, "Codec not started yet");
    return GST_FLOW_OK;
  }

  /* Don't send EOS buffer twice, this doesn't work */
  if (self->eos) {
    GST_DEBUG_OBJECT (self, "Codec is EOS already");
    return GST_FLOW_OK;
  }

  /* Make sure to release the base class stream lock, otherwise
   * _loop() can't call _finish_frame() and we might block forever
   * because no input buffers are released */
  GST_AUDIO_DECODER_STREAM_UNLOCK (self);
  /* Send an EOS buffer to the component and let the base
   * class drop the EOS event. We will send it later when
   * the EOS buffer arrives on the output port.
   * Wait at most 0.5s here. */
  idx = gst_amc_codec_dequeue_input_buffer (self->codec, 500000);
  GST_AUDIO_DECODER_STREAM_LOCK (self);

  if (idx >= 0 && idx < self->n_input_buffers) {
    GstAmcBufferInfo buffer_info;

    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    g_mutex_lock (&self->drain_lock);
    self->draining = TRUE;

    memset (&buffer_info, 0, sizeof (buffer_info));
    buffer_info.size = 0;
    buffer_info.presentation_time_us =
        gst_util_uint64_scale (self->last_upstream_ts, 1, GST_USECOND);
    buffer_info.flags |= BUFFER_FLAG_END_OF_STREAM;

    if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info)) {
      GST_DEBUG_OBJECT (self, "Waiting until codec is drained");
      g_cond_wait (&self->drain_cond, &self->drain_lock);
      GST_DEBUG_OBJECT (self, "Drained codec");
      ret = GST_FLOW_OK;
    } else {
      GST_ERROR_OBJECT (self, "Failed to queue input buffer");
      ret = GST_FLOW_ERROR;
    }

    g_mutex_unlock (&self->drain_lock);
    GST_AUDIO_DECODER_STREAM_LOCK (self);
  } else if (idx >= self->n_input_buffers) {
    GST_ERROR_OBJECT (self, "Invalid input buffer index %d of %d",
        idx, self->n_input_buffers);
    ret = GST_FLOW_ERROR;
  } else {
    GST_ERROR_OBJECT (self, "Failed to acquire buffer for EOS: %d", idx);
    ret = GST_FLOW_ERROR;
  }

  return ret;
}
Beispiel #3
0
/**
 * gvir_storage_pool_refresh:
 * @pool: the storage pool
 * @cancellable: (allow-none)(transfer none): cancellation object
 */
gboolean gvir_storage_pool_refresh(GVirStoragePool *pool,
                                   GCancellable *cancellable,
                                   GError **err)
{
    GVirStoragePoolPrivate *priv;
    GHashTable *vol_hash;
    gchar **volumes = NULL;
    gint nvolumes = 0;
    gboolean ret = FALSE;
    gint i;
    virStoragePoolPtr vpool = NULL;
    GError *lerr = NULL;

    g_return_val_if_fail(GVIR_IS_STORAGE_POOL(pool), FALSE);
    g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable),
                         FALSE);
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);

    priv = pool->priv;
    vpool = priv->handle;

    if (virStoragePoolRefresh(vpool, 0) < 0) {
        gvir_set_error_literal(err, GVIR_STORAGE_POOL_ERROR,
                               0,
                               "Unable to refresh storage pool");
        goto cleanup;
    }

    volumes = fetch_list(vpool,
                         "Storage Volumes",
                         virStoragePoolNumOfVolumes,
                         virStoragePoolListVolumes,
                         cancellable,
                         &nvolumes,
                         &lerr);
    if (lerr) {
        g_propagate_error(err, lerr);
        lerr = NULL;
        goto cleanup;
    }

    if (g_cancellable_set_error_if_cancelled(cancellable, err))
        goto cleanup;

    vol_hash = g_hash_table_new_full(g_str_hash,
                                     g_str_equal,
                                     g_free,
                                     g_object_unref);

    for (i = 0 ; i < nvolumes ; i++) {
        if (g_cancellable_set_error_if_cancelled(cancellable, err))
            goto cleanup;

        virStorageVolPtr vvolume;
        GVirStorageVol *volume;

        vvolume = virStorageVolLookupByName(vpool, volumes[i]);
        if (!vvolume)
            continue;

        volume = GVIR_STORAGE_VOL(g_object_new(GVIR_TYPE_STORAGE_VOL,
                                               "handle", vvolume,
                                               "pool", pool,
                                               NULL));

        g_hash_table_insert(vol_hash, g_strdup(volumes[i]), volume);
    }

    g_mutex_lock(priv->lock);
    if (priv->volumes)
        g_hash_table_unref(priv->volumes);
    priv->volumes = vol_hash;
    g_mutex_unlock(priv->lock);

    ret = TRUE;

cleanup:
    for (i = 0 ; i < nvolumes ; i++)
        g_free(volumes[i]);
    g_free(volumes);
    return ret;
}
Beispiel #4
0
static gpointer
brasero_burn_uri_thread (gpointer data)
{
	BraseroBurnURI *self = BRASERO_BURN_URI (data);
	BraseroTrack *current = NULL;
	BraseroBurnURIPrivate *priv;
	BraseroTrackData *track;
	GSList *excluded = NULL;
	GSList *grafts = NULL;
	guint64 num = 0;
	GSList *src;

	priv = BRASERO_BURN_URI_PRIVATE (self);
	brasero_job_set_current_action (BRASERO_JOB (self),
					BRASERO_BURN_ACTION_FILE_COPY,
					_("Copying files locally"),
					TRUE);

	brasero_job_get_current_track (BRASERO_JOB (self), &current);

	/* This is for IMAGE tracks */
	if (BRASERO_IS_TRACK_IMAGE (current)) {
		gchar *uri;
		gchar *path_toc;
		gchar *path_image;
		goffset blocks = 0;
		BraseroTrackImage *image;

		path_image = NULL;
		uri = brasero_track_image_get_source (BRASERO_TRACK_IMAGE (current), TRUE);
		if (!brasero_burn_uri_retrieve_path (self, uri, &path_image)) {
			g_free (uri);
			goto end;
		}
		g_free (uri);

		path_toc = NULL;
		uri = brasero_track_image_get_toc_source (BRASERO_TRACK_IMAGE (current), TRUE);
		if (uri) {
			/* NOTE: if it's a .bin image there is not .toc file */
			if (!brasero_burn_uri_retrieve_path (self, uri, &path_toc)) {
				g_free (path_image);
				g_free (uri);
				goto end;
			}
			g_free (uri);
		}

		brasero_track_get_size (current, &blocks, NULL);

		image = brasero_track_image_new ();
		brasero_track_tag_copy_missing (BRASERO_TRACK (image), current);
		brasero_track_image_set_source (image,
						path_image,
						path_toc,
						brasero_track_image_get_format (BRASERO_TRACK_IMAGE (current)));
		brasero_track_image_set_block_num (image, blocks);

		priv->track = BRASERO_TRACK (image);

		g_free (path_toc);
		g_free (path_image);
		goto end;
	}

	/* This is for DATA tracks */
	for (src = brasero_track_data_get_grafts (BRASERO_TRACK_DATA (current)); src; src = src->next) {
		GFile *file;
		GFileInfo *info;
		BraseroGraftPt *graft;

		graft = src->data;

		if (!graft->uri) {
			grafts = g_slist_prepend (grafts, brasero_graft_point_copy (graft));
			continue;
		}

		if (!g_str_has_prefix (graft->uri, "burn://")) {
			grafts = g_slist_prepend (grafts, brasero_graft_point_copy (graft));
			continue;
		}

		BRASERO_JOB_LOG (self, "Information retrieval for %s", graft->uri);

		file = g_file_new_for_uri (graft->uri);
		info = g_file_query_info (file,
					  G_FILE_ATTRIBUTE_STANDARD_NAME ","
					  G_FILE_ATTRIBUTE_STANDARD_TYPE ","
					  "burn::backing-file",
					  G_FILE_QUERY_INFO_NONE,
					  priv->cancel,
					  &priv->error);

		if (priv->error) {
			g_object_unref (file);
			goto end;
		}

		if (g_cancellable_is_cancelled (priv->cancel)) {
			g_object_unref (file);
			goto end;
		}

		if (!info) {
			/* Error */
			g_object_unref (file);
			g_object_unref (info);
			goto end;
		}

		/* See if we were passed the burn:/// uri itself (the root).
		 * Then skip graft point addition */
		if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
			if (g_file_info_get_name (info)
			&&  strcmp (g_file_info_get_name (info), "/")) {
				BraseroGraftPt *newgraft;

				/* we need a dummy directory */
				newgraft = g_new0 (BraseroGraftPt, 1);
				newgraft->uri = NULL;
				newgraft->path = g_strdup (graft->path);
				grafts = g_slist_prepend (grafts, newgraft);

				BRASERO_JOB_LOG (self,
						 "Adding directory %s at %s",
						 newgraft->uri,
						 newgraft->path);
				grafts = brasero_burn_uri_explore_directory (self,
									     grafts,
									     file,
									     newgraft->path,
									     priv->cancel,
									     &priv->error);
			}
			else {
				BRASERO_JOB_LOG (self, "Directory is root");
				grafts = brasero_burn_uri_explore_directory (self,
									     grafts,
									     file,
									     "/",
									     priv->cancel,
									     &priv->error);
			}

			if (!grafts) {
				g_object_unref (info);
				g_object_unref (file);
				goto end;
			}
		}
		else if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR
		     /* NOTE: burn:// URI allows symlink */
		     ||  g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK) {
			const gchar *real_path;
			BraseroGraftPt *newgraft;

			real_path = g_file_info_get_attribute_byte_string (info, "burn::backing-file");
			if (!real_path) {
				priv->error = g_error_new (BRASERO_BURN_ERROR,
							   BRASERO_BURN_ERROR_GENERAL,
							   _("Impossible to retrieve local file path"));

				g_slist_foreach (grafts, (GFunc) brasero_graft_point_free, NULL);
				g_slist_free (grafts);
				g_object_unref (info);
				g_object_unref (file);
				goto end;
			}

			newgraft = brasero_graft_point_copy (graft);
			g_free (newgraft->uri);

			newgraft->uri = g_strdup (real_path);
			/* FIXME: maybe one day, graft->uri will always be an URI */
			/* newgraft->uri = g_filename_to_uri (real_path, NULL, NULL); */

			BRASERO_JOB_LOG (self,
					 "Added file %s at %s",
					 newgraft->uri,
					 newgraft->path);
			grafts = g_slist_prepend (grafts, newgraft);
		}

		g_object_unref (info);
		g_object_unref (file);
	}
	grafts = g_slist_reverse (grafts);

	/* remove all excluded starting by burn:// from the list */
	for (src = brasero_track_data_get_excluded_list (BRASERO_TRACK_DATA (current)); src; src = src->next) {
		gchar *uri;

		uri = src->data;

		if (uri && g_str_has_prefix (uri, "burn://"))
			continue;

		uri = g_strdup (uri);
		excluded = g_slist_prepend (excluded, uri);

		BRASERO_JOB_LOG (self, "Added excluded file %s", uri);
	}
	excluded = g_slist_reverse (excluded);

	track = brasero_track_data_new ();
	brasero_track_tag_copy_missing (BRASERO_TRACK (track), current);
	
	brasero_track_data_add_fs (track, brasero_track_data_get_fs (BRASERO_TRACK_DATA (current)));

	brasero_track_data_get_file_num (BRASERO_TRACK_DATA (current), &num);
	brasero_track_data_set_file_num (track, num);

	brasero_track_data_set_source (track,
				       grafts,
				       excluded);
	priv->track = BRASERO_TRACK (track);

end:

	if (!g_cancellable_is_cancelled (priv->cancel))
		priv->thread_id = g_idle_add ((GSourceFunc) brasero_burn_uri_thread_finished, self);

	/* End thread */
	g_mutex_lock (priv->mutex);
	g_atomic_pointer_set (&priv->thread, NULL);
	g_cond_signal (priv->cond);
	g_mutex_unlock (priv->mutex);

	g_thread_exit (NULL);

	return NULL;
}
Beispiel #5
0
int network_backends_save_to_config(network_backends_t *bs, gchar* config_path) {
        int i, len, file_size = 0, first_append_master = 1, first_append_slave = 1, first_append_standby = 1;
        GKeyFile* keyfile;
        network_backend_t *backend;
        GString *master, *slave, *standby;
        GError *gerr = NULL;
        gchar* file_buf = NULL;

        master = g_string_new(NULL);
        slave = g_string_new(NULL);
        standby = g_string_new(NULL);
        keyfile = g_key_file_new();
        g_key_file_set_list_separator(keyfile, ',');
        if (FALSE == g_key_file_load_from_file(keyfile, config_path, G_KEY_FILE_NONE, NULL)) {
                g_message("%s:load %s error,load config file failed", G_STRLOC, config_path);
                g_string_free(master, TRUE);
                g_string_free(slave, TRUE);
                g_string_free(standby, TRUE);
                g_key_file_free(keyfile);
                return -1;
        }
        g_mutex_lock(bs->backends_mutex);
        len = bs->backends->len;
        for (i = 0; i < len; i++) {
                backend = g_ptr_array_index(bs->backends, i);
                if (backend->type == BACKEND_TYPE_RW) {
                        if (first_append_master) {
                                g_string_append(master, backend->addr->name->str);
                                first_append_master = 0;
                        } else {
                                g_string_append_c(master, ',');
                                g_string_append(master, backend->addr->name->str);
                        }
                } else if (backend->type == BACKEND_TYPE_RO) {
                        if (first_append_slave) {
                                g_string_append(slave, backend->addr->name->str);
                                first_append_slave = 0;
                        } else {
                                g_string_append_c(slave, ',');
                                g_string_append(slave, backend->addr->name->str);
                        }
                } else if (backend->type == BACKEND_TYPE_SY) {
                        if (first_append_standby) {
                                g_string_append(standby, backend->addr->name->str);
                                first_append_standby = 0;
                        } else {
                                g_string_append_c(standby, ',');
                                g_string_append(standby, backend->addr->name->str);
                        }
                }
        }
        g_mutex_unlock(bs->backends_mutex);
        if (master->len != 0)
                g_key_file_set_string(keyfile, "mysql-proxy", "proxy-backend-addresses", master->str);
        else
                g_key_file_set_string(keyfile, "mysql-proxy", "proxy-backend-addresses", "");

        if (slave->len != 0)
                g_key_file_set_string(keyfile, "mysql-proxy", "proxy-read-only-backend-addresses", slave->str);
        else
                g_key_file_set_string(keyfile, "mysql-proxy", "proxy-read-only-backend-addresses", "");

        if (standby->len != 0)
                g_key_file_set_string(keyfile, "mysql-proxy", "proxy-master-standby-address", standby->str);
        else
                g_key_file_set_string(keyfile, "mysql-proxy", "proxy-master-standby-address", "");
        file_buf = g_key_file_to_data(keyfile, &file_size, &gerr);
        if (file_buf) {
                if (FALSE == g_file_set_contents(config_path, file_buf, file_size, &gerr)) {
                        g_message("%s:g_file_set_contents, gerr is:%s", G_STRLOC, gerr->message);
                        g_error_free(gerr);
                        gerr = NULL;
                        g_message("%s:save to config failure", G_STRLOC);
                } else {
                        g_message("%s:save to config success", G_STRLOC);
                }
                g_free(file_buf);
        } else {
                g_message("%s:save to config failure", G_STRLOC); 
        }
        g_string_free(master, TRUE);
        g_string_free(slave, TRUE);
        g_string_free(standby, TRUE);
        g_key_file_free(keyfile);
        return 0;
}                          
Beispiel #6
0
/* always call with stream lock */
static GstFlowReturn
gst_droidadec_finish (GstAudioDecoder * decoder)
{
  GstDroidADec *dec = GST_DROIDADEC (decoder);
  gint available;

  GST_DEBUG_OBJECT (dec, "finish");

  if (!dec->running) {
    GST_DEBUG_OBJECT (dec, "decoder is not running");
    goto finish;
  }

  g_mutex_lock (&dec->eos_lock);
  dec->eos = TRUE;

  if (dec->codec) {
    droid_media_codec_drain (dec->codec);
  } else {
    goto out;
  }

  /* release the lock to allow _data_available () to do its job */
  GST_AUDIO_DECODER_STREAM_UNLOCK (decoder);
  /* Now we wait for the codec to signal EOS */
  g_cond_wait (&dec->eos_cond, &dec->eos_lock);
  GST_AUDIO_DECODER_STREAM_LOCK (decoder);

finish:
  /* We drained the codec. Better to recreate it. */
  if (dec->codec) {
    droid_media_codec_stop (dec->codec);
    droid_media_codec_destroy (dec->codec);
    dec->codec = NULL;
  }

  if (dec->spf != -1) {
    available = gst_adapter_available (dec->adapter);
    if (available > 0) {
      gint size = dec->spf * dec->info->bpf;
      gint nframes = available / size;
      GstBuffer *out;
      GstFlowReturn ret G_GNUC_UNUSED;

      GST_INFO_OBJECT (dec, "pushing remaining %d bytes", available);
      if (nframes > 0) {
        out = gst_adapter_take_buffer (dec->adapter, nframes * size);
        available -= (nframes * size);
      } else {
        out = gst_adapter_take_buffer (dec->adapter, available);
        nframes = 1;
        available = 0;
      }

      ret = gst_audio_decoder_finish_frame (decoder, out, nframes);


      GST_INFO_OBJECT (dec, "pushed %d frames. flow return: %s", nframes,
          gst_flow_get_name (ret));

      if (available > 0) {
        GST_ERROR_OBJECT (dec, "%d bytes remaining", available);
      }
    }
  }

  dec->dirty = TRUE;

out:
  dec->eos = FALSE;

  g_mutex_unlock (&dec->eos_lock);

  return GST_FLOW_OK;
}
Beispiel #7
0
void rm_trie_iter(RmTrie *self, RmNode *root, bool pre_order, bool all_nodes,
                  RmTrieIterCallback callback, void *user_data) {
    g_mutex_lock(&self->lock);
    _rm_trie_iter(self, root, pre_order, all_nodes, callback, user_data, 0);
    g_mutex_unlock(&self->lock);
}
Beispiel #8
0
static GstFlowReturn
gst_spectrum_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
{
  GstSpectrum *spectrum = GST_SPECTRUM (trans);
  guint rate = GST_AUDIO_FILTER_RATE (spectrum);
  guint channels = GST_AUDIO_FILTER_CHANNELS (spectrum);
  guint bps = GST_AUDIO_FILTER_BPS (spectrum);
  guint bpf = GST_AUDIO_FILTER_BPF (spectrum);
  guint output_channels = spectrum->multi_channel ? channels : 1;
  guint c;
  gfloat max_value = (1UL << ((bps << 3) - 1)) - 1;
  guint bands = spectrum->bands;
  guint nfft = 2 * bands - 2;
  guint input_pos;
  gfloat *input;
  GstMapInfo map;
  const guint8 *data;
  gsize size;
  guint fft_todo, msg_todo, block_size;
  gboolean have_full_interval;
  GstSpectrumChannel *cd;
  GstSpectrumInputData input_data;

  g_mutex_lock (&spectrum->lock);
  gst_buffer_map (buffer, &map, GST_MAP_READ);
  data = map.data;
  size = map.size;

  GST_LOG_OBJECT (spectrum, "input size: %" G_GSIZE_FORMAT " bytes", size);

  if (GST_BUFFER_IS_DISCONT (buffer)) {
    GST_DEBUG_OBJECT (spectrum, "Discontinuity detected -- flushing");
    gst_spectrum_flush (spectrum);
  }

  /* If we don't have a FFT context yet (or it was reset due to parameter
   * changes) get one and allocate memory for everything
   */
  if (spectrum->channel_data == NULL) {
    GST_DEBUG_OBJECT (spectrum, "allocating for bands %u", bands);

    gst_spectrum_alloc_channel_data (spectrum);

    /* number of sample frames we process before posting a message
     * interval is in ns */
    spectrum->frames_per_interval =
        gst_util_uint64_scale (spectrum->interval, rate, GST_SECOND);
    spectrum->frames_todo = spectrum->frames_per_interval;
    /* rounding error for frames_per_interval in ns,
     * aggregated it in accumulated_error */
    spectrum->error_per_interval = (spectrum->interval * rate) % GST_SECOND;
    if (spectrum->frames_per_interval == 0)
      spectrum->frames_per_interval = 1;

    GST_INFO_OBJECT (spectrum, "interval %" GST_TIME_FORMAT ", fpi %"
        G_GUINT64_FORMAT ", error %" GST_TIME_FORMAT,
        GST_TIME_ARGS (spectrum->interval), spectrum->frames_per_interval,
        GST_TIME_ARGS (spectrum->error_per_interval));

    spectrum->input_pos = 0;

    gst_spectrum_flush (spectrum);
  }

  if (spectrum->num_frames == 0)
    spectrum->message_ts = GST_BUFFER_TIMESTAMP (buffer);

  input_pos = spectrum->input_pos;
  input_data = spectrum->input_data;

  while (size >= bpf) {
    /* run input_data for a chunk of data */
    fft_todo = nfft - (spectrum->num_frames % nfft);
    msg_todo = spectrum->frames_todo - spectrum->num_frames;
    GST_LOG_OBJECT (spectrum,
        "message frames todo: %u, fft frames todo: %u, input frames %"
        G_GSIZE_FORMAT, msg_todo, fft_todo, (size / bpf));
    block_size = msg_todo;
    if (block_size > (size / bpf))
      block_size = (size / bpf);
    if (block_size > fft_todo)
      block_size = fft_todo;

    for (c = 0; c < output_channels; c++) {
      cd = &spectrum->channel_data[c];
      input = cd->input;
      /* Move the current frames into our ringbuffers */
      input_data (data + c * bps, input, block_size, channels, max_value,
          input_pos, nfft);
    }
    data += block_size * bpf;
    size -= block_size * bpf;
    input_pos = (input_pos + block_size) % nfft;
    spectrum->num_frames += block_size;

    have_full_interval = (spectrum->num_frames == spectrum->frames_todo);

    GST_LOG_OBJECT (spectrum,
        "size: %" G_GSIZE_FORMAT ", do-fft = %d, do-message = %d", size,
        (spectrum->num_frames % nfft == 0), have_full_interval);

    /* If we have enough frames for an FFT or we have all frames required for
     * the interval and we haven't run a FFT, then run an FFT */
    if ((spectrum->num_frames % nfft == 0) ||
        (have_full_interval && !spectrum->num_fft)) {
      for (c = 0; c < output_channels; c++) {
        cd = &spectrum->channel_data[c];
        gst_spectrum_run_fft (spectrum, cd, input_pos);
      }
      spectrum->num_fft++;
    }

    /* Do we have the FFTs for one interval? */
    if (have_full_interval) {
      GST_DEBUG_OBJECT (spectrum, "nfft: %u frames: %" G_GUINT64_FORMAT
          " fpi: %" G_GUINT64_FORMAT " error: %" GST_TIME_FORMAT, nfft,
          spectrum->num_frames, spectrum->frames_per_interval,
          GST_TIME_ARGS (spectrum->accumulated_error));

      spectrum->frames_todo = spectrum->frames_per_interval;
      if (spectrum->accumulated_error >= GST_SECOND) {
        spectrum->accumulated_error -= GST_SECOND;
        spectrum->frames_todo++;
      }
      spectrum->accumulated_error += spectrum->error_per_interval;

      if (spectrum->post_messages) {
        GstMessage *m;

        for (c = 0; c < output_channels; c++) {
          cd = &spectrum->channel_data[c];
          gst_spectrum_prepare_message_data (spectrum, cd);
        }

        m = gst_spectrum_message_new (spectrum, spectrum->message_ts,
            spectrum->interval);

        gst_element_post_message (GST_ELEMENT (spectrum), m);
      }

      if (GST_CLOCK_TIME_IS_VALID (spectrum->message_ts))
        spectrum->message_ts +=
            gst_util_uint64_scale (spectrum->num_frames, GST_SECOND, rate);

      for (c = 0; c < output_channels; c++) {
        cd = &spectrum->channel_data[c];
        gst_spectrum_reset_message_data (spectrum, cd);
      }
      spectrum->num_frames = 0;
      spectrum->num_fft = 0;
    }
  }

  spectrum->input_pos = input_pos;

  gst_buffer_unmap (buffer, &map);
  g_mutex_unlock (&spectrum->lock);

  g_assert (size == 0);

  return GST_FLOW_OK;
}
Beispiel #9
0
/**
 * gst_bus_post:
 * @bus: a #GstBus to post on
 * @message: (transfer full): the #GstMessage to post
 *
 * Post a message on the given bus. Ownership of the message
 * is taken by the bus.
 *
 * Returns: %TRUE if the message could be posted, %FALSE if the bus is flushing.
 *
 * MT safe.
 */
gboolean
gst_bus_post (GstBus * bus, GstMessage * message)
{
  GstBusSyncReply reply = GST_BUS_PASS;
  GstBusSyncHandler handler;
  gboolean emit_sync_message;
  gpointer handler_data;

  g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
  g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE);

  GST_DEBUG_OBJECT (bus, "[msg %p] posting on bus %" GST_PTR_FORMAT, message,
      message);

  /* check we didn't accidentally add a public flag that maps to same value */
  g_assert (!GST_MINI_OBJECT_FLAG_IS_SET (message,
          GST_MESSAGE_FLAG_ASYNC_DELIVERY));

  GST_OBJECT_LOCK (bus);
  /* check if the bus is flushing */
  if (GST_OBJECT_FLAG_IS_SET (bus, GST_BUS_FLUSHING))
    goto is_flushing;

  handler = bus->priv->sync_handler;
  handler_data = bus->priv->sync_handler_data;
  emit_sync_message = bus->priv->num_sync_message_emitters > 0;
  GST_OBJECT_UNLOCK (bus);

  /* first call the sync handler if it is installed */
  if (handler)
    reply = handler (bus, message, handler_data);

  /* emit sync-message if requested to do so via
     gst_bus_enable_sync_message_emission. terrible but effective */
  if (emit_sync_message && reply != GST_BUS_DROP
      && handler != gst_bus_sync_signal_handler)
    gst_bus_sync_signal_handler (bus, message, NULL);

  /* If this is a bus without async message delivery
   * always drop the message */
  if (!bus->priv->poll)
    reply = GST_BUS_DROP;

  /* now see what we should do with the message */
  switch (reply) {
    case GST_BUS_DROP:
      /* drop the message */
      GST_DEBUG_OBJECT (bus, "[msg %p] dropped", message);
      break;
    case GST_BUS_PASS:
      /* pass the message to the async queue, refcount passed in the queue */
      GST_DEBUG_OBJECT (bus, "[msg %p] pushing on async queue", message);
      gst_atomic_queue_push (bus->priv->queue, message);
      gst_poll_write_control (bus->priv->poll);
      GST_DEBUG_OBJECT (bus, "[msg %p] pushed on async queue", message);

      break;
    case GST_BUS_ASYNC:
    {
      /* async delivery, we need a mutex and a cond to block
       * on */
      GCond *cond = GST_MESSAGE_GET_COND (message);
      GMutex *lock = GST_MESSAGE_GET_LOCK (message);

      g_cond_init (cond);
      g_mutex_init (lock);

      GST_MINI_OBJECT_FLAG_SET (message, GST_MESSAGE_FLAG_ASYNC_DELIVERY);

      GST_DEBUG_OBJECT (bus, "[msg %p] waiting for async delivery", message);

      /* now we lock the message mutex, send the message to the async
       * queue. When the message is handled by the app and destroyed,
       * the cond will be signalled and we can continue */
      g_mutex_lock (lock);

      gst_atomic_queue_push (bus->priv->queue, message);
      gst_poll_write_control (bus->priv->poll);

      /* now block till the message is freed */
      g_cond_wait (cond, lock);

      /* we acquired a new ref from gst_message_dispose() so we can clean up */
      g_mutex_unlock (lock);

      GST_DEBUG_OBJECT (bus, "[msg %p] delivered asynchronously", message);

      GST_MINI_OBJECT_FLAG_UNSET (message, GST_MESSAGE_FLAG_ASYNC_DELIVERY);

      g_mutex_clear (lock);
      g_cond_clear (cond);

      gst_message_unref (message);
      break;
    }
    default:
      g_warning ("invalid return from bus sync handler");
      break;
  }
  return TRUE;

  /* ERRORS */
is_flushing:
  {
    GST_DEBUG_OBJECT (bus, "bus is flushing");
    GST_OBJECT_UNLOCK (bus);
    gst_message_unref (message);

    return FALSE;
  }
}
static gboolean
interpolate_trigger_get_value_array (GstTimedValueControlSource * self,
    GstClockTime timestamp, GstClockTime interval, guint n_values,
    gdouble * values)
{
  gboolean ret = FALSE;
  guint i;
  GstClockTime ts = timestamp;
  GstClockTime next_ts = 0;
  gdouble val;
  GSequenceIter *iter1 = NULL, *iter2 = NULL;
  gboolean triggered = FALSE;

  g_mutex_lock (&self->lock);
  for (i = 0; i < n_values; i++) {
    val = NAN;
    if (ts >= next_ts) {
      iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts);
      if (!iter1) {
        if (G_LIKELY (self->values))
          iter2 = g_sequence_get_begin_iter (self->values);
        else
          iter2 = NULL;
      } else {
        iter2 = g_sequence_iter_next (iter1);
      }

      if (iter2 && !g_sequence_iter_is_end (iter2)) {
        GstControlPoint *cp;

        cp = g_sequence_get (iter2);
        next_ts = cp->timestamp;
      } else {
        next_ts = GST_CLOCK_TIME_NONE;
      }

      if (iter1) {
        val = _interpolate_trigger (self, iter1, ts);
        if (!isnan (val))
          ret = TRUE;
      } else {
        g_mutex_unlock (&self->lock);
        return FALSE;
      }
      triggered = TRUE;
    } else if (triggered) {
      if (iter1) {
        val = _interpolate_trigger (self, iter1, ts);
        if (!isnan (val))
          ret = TRUE;
      } else {
        g_mutex_unlock (&self->lock);
        return FALSE;
      }
      triggered = FALSE;
    }
    *values = val;
    ts += interval;
    values++;
  }
  g_mutex_unlock (&self->lock);
  return ret;
}
static void
gst_lfo_control_source_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (object);

  switch (prop_id) {
    case PROP_WAVEFORM:
      g_mutex_lock (self->lock);
      gst_lfo_control_source_set_waveform (self, g_value_get_enum (value));
      g_mutex_unlock (self->lock);
      break;
    case PROP_FREQUENCY:{
      gdouble frequency = g_value_get_double (value);

      g_return_if_fail (frequency > 0
          || ((GstClockTime) (GST_SECOND / frequency)) != 0);

      g_mutex_lock (self->lock);
      self->priv->frequency = frequency;
      self->priv->period = GST_SECOND / frequency;
      g_mutex_unlock (self->lock);
      break;
    }
    case PROP_TIMESHIFT:
      g_mutex_lock (self->lock);
      self->priv->timeshift = g_value_get_uint64 (value);
      g_mutex_unlock (self->lock);
      break;
    case PROP_AMPLITUDE:{
      GValue *val = g_value_get_boxed (value);

      if (self->priv->type != G_TYPE_INVALID) {
        g_return_if_fail (g_value_type_transformable (self->priv->type,
                G_VALUE_TYPE (val)));

        g_mutex_lock (self->lock);
        if (G_IS_VALUE (&self->priv->amplitude))
          g_value_unset (&self->priv->amplitude);

        g_value_init (&self->priv->amplitude, self->priv->type);
        g_value_transform (val, &self->priv->amplitude);
        g_mutex_unlock (self->lock);
      } else {
        g_mutex_lock (self->lock);
        if (G_IS_VALUE (&self->priv->amplitude))
          g_value_unset (&self->priv->amplitude);

        g_value_init (&self->priv->amplitude, G_VALUE_TYPE (val));
        g_value_copy (val, &self->priv->amplitude);
        g_mutex_unlock (self->lock);
      }

      break;
    }
    case PROP_OFFSET:{
      GValue *val = g_value_get_boxed (value);

      if (self->priv->type != G_TYPE_INVALID) {
        g_return_if_fail (g_value_type_transformable (self->priv->type,
                G_VALUE_TYPE (val)));

        g_mutex_lock (self->lock);
        if (G_IS_VALUE (&self->priv->offset))
          g_value_unset (&self->priv->offset);

        g_value_init (&self->priv->offset, self->priv->type);
        g_value_transform (val, &self->priv->offset);
        g_mutex_unlock (self->lock);
      } else {
        g_mutex_lock (self->lock);
        if (G_IS_VALUE (&self->priv->offset))
          g_value_unset (&self->priv->offset);

        g_value_init (&self->priv->offset, G_VALUE_TYPE (val));
        g_value_copy (val, &self->priv->offset);
        g_mutex_unlock (self->lock);
      }

      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
Beispiel #12
0
static void angel_connection_io_cb(liEventBase *watcher, int events) {
	liAngelConnection *acon = LI_CONTAINER_OF(li_event_io_from(watcher), liAngelConnection, fd_watcher);

	if (events | LI_EV_WRITE) {
		GString *out_str;
		int i;
		ssize_t written, len;
		gchar *data;
		gboolean out_queue_empty;
		angel_connection_send_item_t *send_item;
		int fd = li_event_io_fd(&acon->fd_watcher);

		g_mutex_lock(acon->mutex);
			send_item = g_queue_peek_head(acon->out);
		g_mutex_unlock(acon->mutex);

		for (i = 0; send_item && (i < 10); i++) { /* don't send more than 10 chunks */
			switch (send_item->type) {
			case ANGEL_CONNECTION_ITEM_GSTRING:
				out_str = send_item->value.string.buf;
				written = send_item->value.string.pos;
				data = out_str->str + written;
				len = out_str->len - written;
				while (len > 0) {
					written = write(fd, data, len);
					if (written < 0) {
						switch (errno) {
						case EINTR:
							continue;
						case EAGAIN:
#if EWOULDBLOCK != EAGAIN
						case EWOULDBLOCK:
#endif
							goto write_eagain;
						default: /* Fatal error, connection has to be closed */
							li_event_clear(&acon->out_notify_watcher);
							li_event_clear(&acon->fd_watcher);
							acon->close_cb(acon, NULL); /* TODO: set err */
							return;
						}
					} else {
						data += written;
						len -= written;
						send_item->value.string.pos += written;
					}
				}
				break;

			case ANGEL_CONNECTION_ITEM_FDS:
				while (send_item->value.fds.pos < send_item->value.fds.fds->len) {
					switch (li_send_fd(fd, g_array_index(send_item->value.fds.fds, int, send_item->value.fds.pos))) {
					case  0:
						send_item->value.fds.pos++;
						continue;
					case -1: /* Fatal error, connection has to be closed */
						li_event_clear(&acon->out_notify_watcher);
						li_event_clear(&acon->fd_watcher);
						acon->close_cb(acon, NULL); /* TODO: set err */
						return;
					case -2: goto write_eagain;
					}
				}
				break;
			}

			g_mutex_lock(acon->mutex);
				send_queue_clean(acon->out);
				send_item = g_queue_peek_head(acon->out);
			g_mutex_unlock(acon->mutex);
		}

write_eagain:
		g_mutex_lock(acon->mutex);
		send_queue_clean(acon->out);
		out_queue_empty = (0 == acon->out->length);
		g_mutex_unlock(acon->mutex);

		if (out_queue_empty) li_event_io_rem_events(&acon->fd_watcher, LI_EV_WRITE);
	}
Beispiel #13
0
static gboolean angel_dispatch(liAngelConnection *acon, GError **err) {
	gint32 id = acon->parse.id, type = acon->parse.type;
	liAngelCall *call;

	switch (type) {
	case ANGEL_CALL_SEND_SIMPLE:
		if (-1 != id) {
			g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
				"Invalid id: %i, should be -1 for simple call", (gint) id);
			close_fd_array(acon->parse.fds);
			return FALSE;
		}

		if (acon->parse.error->len > 0 || acon->parse.fds->len > 0) {
			g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
				"Wrong data in call");
			close_fd_array(acon->parse.fds);
			return FALSE;
		}
		acon->recv_call(acon, GSTR_LEN(acon->parse.mod), GSTR_LEN(acon->parse.action),
			id, acon->parse.data);
		break;
	case ANGEL_CALL_SEND_CALL:
		if (-1 == id) {
			g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
				"Invalid id: -1, should be >= 0 for call");
			close_fd_array(acon->parse.fds);
			return FALSE;
		}

		if (acon->parse.error->len > 0 || acon->parse.fds->len > 0) {
			g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
				"Wrong data in call");
			close_fd_array(acon->parse.fds);
			return FALSE;
		}
		acon->recv_call(acon, GSTR_LEN(acon->parse.mod), GSTR_LEN(acon->parse.action),
			id, acon->parse.data);
		break;
	case ANGEL_CALL_SEND_RESULT:
		g_mutex_lock(acon->mutex);
			if (!li_idlist_is_used(acon->call_id_list, id)) {
				g_mutex_unlock(acon->mutex);
				g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
					"Invalid id: %i", (gint) id);
				close_fd_array(acon->parse.fds);
				return FALSE;
			}
			li_idlist_put(acon->call_id_list, id);
			call = NULL;
			if ((guint) id < acon->call_table->len) {
				call = (liAngelCall*) g_ptr_array_index(acon->call_table, id);
				g_ptr_array_index(acon->call_table, id) = NULL;
			}
			if (NULL != call) {
				call->id = -1;

				call->result.error = acon->parse.error;
				call->result.data = acon->parse.data;
				call->result.fds = acon->parse.fds;
				acon->parse.error = g_string_sized_new(0);
				acon->parse.data = g_string_sized_new(0);
				acon->parse.fds = g_array_new(FALSE, FALSE, sizeof(int));
				li_event_async_send(&call->result_watcher);
			} else {
				/* timeout - call is gone */
				g_string_truncate(acon->parse.error, 0);
				g_string_truncate(acon->parse.data, 0);
				close_fd_array(acon->parse.fds);
			}
		g_mutex_unlock(acon->mutex);

		break;
	default:
		g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
			"Invalid type: %i", (gint) type);
		close_fd_array(acon->parse.fds);
		return FALSE;
	}

	return TRUE;
}
static GstFlowReturn
gst_audio_fx_base_fir_filter_transform (GstBaseTransform * base,
    GstBuffer * inbuf, GstBuffer * outbuf)
{
  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (base);
  GstClockTime timestamp, expected_timestamp;
  gint channels = GST_AUDIO_FILTER_CHANNELS (self);
  gint rate = GST_AUDIO_FILTER_RATE (self);
  gint bps = GST_AUDIO_FILTER_BPS (self);
  GstMapInfo inmap, outmap;
  guint input_samples;
  guint output_samples;
  guint generated_samples;
  guint64 output_offset;
  gint64 diff = 0;
  GstClockTime stream_time;

  timestamp = GST_BUFFER_TIMESTAMP (outbuf);

  if (!GST_CLOCK_TIME_IS_VALID (timestamp)
      && !GST_CLOCK_TIME_IS_VALID (self->start_ts)) {
    GST_ERROR_OBJECT (self, "Invalid timestamp");
    return GST_FLOW_ERROR;
  }

  g_mutex_lock (&self->lock);
  stream_time =
      gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);

  GST_DEBUG_OBJECT (self, "sync to %" GST_TIME_FORMAT,
      GST_TIME_ARGS (timestamp));

  if (GST_CLOCK_TIME_IS_VALID (stream_time))
    gst_object_sync_values (GST_OBJECT (self), stream_time);

  g_return_val_if_fail (self->kernel != NULL, GST_FLOW_ERROR);
  g_return_val_if_fail (channels != 0, GST_FLOW_ERROR);

  if (GST_CLOCK_TIME_IS_VALID (self->start_ts))
    expected_timestamp =
        self->start_ts + gst_util_uint64_scale_int (self->nsamples_in,
        GST_SECOND, rate);
  else
    expected_timestamp = GST_CLOCK_TIME_NONE;

  /* Reset the residue if already existing on discont buffers */
  if (GST_BUFFER_IS_DISCONT (inbuf)
      || (GST_CLOCK_TIME_IS_VALID (expected_timestamp)
          && (ABS (GST_CLOCK_DIFF (timestamp,
                      expected_timestamp) > 5 * GST_MSECOND)))) {
    GST_DEBUG_OBJECT (self, "Discontinuity detected - flushing");
    if (GST_CLOCK_TIME_IS_VALID (expected_timestamp))
      gst_audio_fx_base_fir_filter_push_residue (self);
    self->buffer_fill = 0;
    g_free (self->buffer);
    self->buffer = NULL;
    self->start_ts = timestamp;
    self->start_off = GST_BUFFER_OFFSET (inbuf);
    self->nsamples_out = 0;
    self->nsamples_in = 0;
  } else if (!GST_CLOCK_TIME_IS_VALID (self->start_ts)) {
    self->start_ts = timestamp;
    self->start_off = GST_BUFFER_OFFSET (inbuf);
  }

  gst_buffer_map (inbuf, &inmap, GST_MAP_READ);
  gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);

  input_samples = (inmap.size / bps) / channels;
  output_samples = (outmap.size / bps) / channels;

  self->nsamples_in += input_samples;

  generated_samples =
      self->process (self, inmap.data, outmap.data, input_samples);

  gst_buffer_unmap (inbuf, &inmap);
  gst_buffer_unmap (outbuf, &outmap);

  g_assert (generated_samples <= output_samples);
  self->nsamples_out += generated_samples;
  if (generated_samples == 0)
    goto no_samples;

  /* Calculate the number of samples we can push out now without outputting
   * latency zeros in the beginning */
  diff = ((gint64) self->nsamples_out) - ((gint64) self->latency);
  if (diff < 0)
    goto no_samples;

  if (diff < generated_samples) {
    gint64 tmp = diff;
    diff = generated_samples - diff;
    generated_samples = tmp;
  } else {
    diff = 0;
  }

  gst_buffer_resize (outbuf, diff * bps * channels,
      generated_samples * bps * channels);

  output_offset = self->nsamples_out - self->latency - generated_samples;
  GST_BUFFER_TIMESTAMP (outbuf) =
      self->start_ts + gst_util_uint64_scale_int (output_offset, GST_SECOND,
      rate);
  GST_BUFFER_DURATION (outbuf) =
      gst_util_uint64_scale_int (output_samples, GST_SECOND, rate);
  if (self->start_off != GST_BUFFER_OFFSET_NONE) {
    GST_BUFFER_OFFSET (outbuf) = self->start_off + output_offset;
    GST_BUFFER_OFFSET_END (outbuf) =
        GST_BUFFER_OFFSET (outbuf) + generated_samples;
  } else {
    GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET_NONE;
    GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_NONE;
  }
  g_mutex_unlock (&self->lock);

  GST_DEBUG_OBJECT (self,
      "Pushing buffer of size %" G_GSIZE_FORMAT " with timestamp: %"
      GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
      G_GUINT64_FORMAT ", offset_end: %" G_GUINT64_FORMAT ", nsamples_out: %d",
      gst_buffer_get_size (outbuf),
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
      GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
      GST_BUFFER_OFFSET_END (outbuf), generated_samples);

  return GST_FLOW_OK;

no_samples:
  {
    g_mutex_unlock (&self->lock);
    return GST_BASE_TRANSFORM_FLOW_DROPPED;
  }
}
static gboolean
gst_soup_http_client_sink_start (GstBaseSink * sink)
{
  GstSoupHttpClientSink *souphttpsink = GST_SOUP_HTTP_CLIENT_SINK (sink);

  if (souphttpsink->prop_session) {
    souphttpsink->session = souphttpsink->prop_session;
  } else {
    GSource *source;
    GError *error = NULL;

    souphttpsink->context = g_main_context_new ();

    /* set up idle source to signal when the main loop is running and
     * it's safe for ::stop() to call g_main_loop_quit() */
    source = g_idle_source_new ();
    g_source_set_callback (source, thread_ready_idle_cb, sink, NULL);
    g_source_attach (source, souphttpsink->context);
    g_source_unref (source);

    souphttpsink->loop = g_main_loop_new (souphttpsink->context, TRUE);

    g_mutex_lock (&souphttpsink->mutex);

    souphttpsink->thread = g_thread_try_new ("souphttpclientsink-thread",
        thread_func, souphttpsink, &error);

    if (error != NULL) {
      GST_DEBUG_OBJECT (souphttpsink, "failed to start thread, %s",
          error->message);
      g_error_free (error);
      g_mutex_unlock (&souphttpsink->mutex);
      return FALSE;
    }

    GST_LOG_OBJECT (souphttpsink, "waiting for main loop thread to start up");
    g_cond_wait (&souphttpsink->cond, &souphttpsink->mutex);
    g_mutex_unlock (&souphttpsink->mutex);
    GST_LOG_OBJECT (souphttpsink, "main loop thread running");

    if (souphttpsink->proxy == NULL) {
      souphttpsink->session =
          soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
          souphttpsink->context, SOUP_SESSION_USER_AGENT,
          souphttpsink->user_agent, SOUP_SESSION_TIMEOUT, souphttpsink->timeout,
          SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
          NULL);
    } else {
      souphttpsink->session =
          soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
          souphttpsink->context, SOUP_SESSION_USER_AGENT,
          souphttpsink->user_agent, SOUP_SESSION_TIMEOUT, souphttpsink->timeout,
          SOUP_SESSION_PROXY_URI, souphttpsink->proxy, NULL);
    }

    g_signal_connect (souphttpsink->session, "authenticate",
        G_CALLBACK (authenticate), souphttpsink);
  }

  /* Set up logging */
  gst_soup_util_log_setup (souphttpsink->session, souphttpsink->log_level,
      GST_ELEMENT (souphttpsink));

  return TRUE;
}
Beispiel #16
0
/**
 * gst_bus_timed_pop_filtered:
 * @bus: a #GstBus to pop from
 * @timeout: a timeout in nanoseconds, or GST_CLOCK_TIME_NONE to wait forever
 * @types: message types to take into account, GST_MESSAGE_ANY for any type
 *
 * Get a message from the bus whose type matches the message type mask @types,
 * waiting up to the specified timeout (and discarding any messages that do not
 * match the mask provided).
 *
 * If @timeout is 0, this function behaves like gst_bus_pop_filtered(). If
 * @timeout is #GST_CLOCK_TIME_NONE, this function will block forever until a
 * matching message was posted on the bus.
 *
 * Returns: (transfer full) (nullable): a #GstMessage matching the
 *     filter in @types, or %NULL if no matching message was found on
 *     the bus until the timeout expired. The message is taken from
 *     the bus and needs to be unreffed with gst_message_unref() after
 *     usage.
 *
 * MT safe.
 */
GstMessage *
gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
    GstMessageType types)
{
  GstMessage *message;
  GTimeVal now, then;
  gboolean first_round = TRUE;
  GstClockTime elapsed = 0;

  g_return_val_if_fail (GST_IS_BUS (bus), NULL);
  g_return_val_if_fail (types != 0, NULL);
  g_return_val_if_fail (timeout == 0 || bus->priv->poll != NULL, NULL);

  g_mutex_lock (&bus->priv->queue_lock);

  while (TRUE) {
    gint ret;

    GST_LOG_OBJECT (bus, "have %d messages",
        gst_atomic_queue_length (bus->priv->queue));

    while ((message = gst_atomic_queue_pop (bus->priv->queue))) {
      if (bus->priv->poll)
        gst_poll_read_control (bus->priv->poll);

      GST_DEBUG_OBJECT (bus, "got message %p, %s from %s, type mask is %u",
          message, GST_MESSAGE_TYPE_NAME (message),
          GST_MESSAGE_SRC_NAME (message), (guint) types);
      if ((GST_MESSAGE_TYPE (message) & types) != 0) {
        /* Extra check to ensure extended types don't get matched unless
         * asked for */
        if ((!GST_MESSAGE_TYPE_IS_EXTENDED (message))
            || (types & GST_MESSAGE_EXTENDED)) {
          /* exit the loop, we have a message */
          goto beach;
        }
      }

      GST_DEBUG_OBJECT (bus, "discarding message, does not match mask");
      gst_message_unref (message);
      message = NULL;
    }

    /* no need to wait, exit loop */
    if (timeout == 0)
      break;

    else if (timeout != GST_CLOCK_TIME_NONE) {
      if (first_round) {
        g_get_current_time (&then);
        first_round = FALSE;
      } else {
        g_get_current_time (&now);

        elapsed = GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (then);

        if (elapsed > timeout)
          break;
      }
    }

    /* only here in timeout case */
    g_assert (bus->priv->poll);
    g_mutex_unlock (&bus->priv->queue_lock);
    ret = gst_poll_wait (bus->priv->poll, timeout - elapsed);
    g_mutex_lock (&bus->priv->queue_lock);

    if (ret == 0) {
      GST_INFO_OBJECT (bus, "timed out, breaking loop");
      break;
    } else {
      GST_INFO_OBJECT (bus, "we got woken up, recheck for message");
    }
  }

beach:

  g_mutex_unlock (&bus->priv->queue_lock);

  return message;
}
static GstFlowReturn webkitMediaPlayReadyDecryptTransformInPlace(GstBaseTransform* base, GstBuffer* buffer)
{
    WebKitMediaPlayReadyDecrypt* self = WEBKIT_MEDIA_PLAYREADY_DECRYPT(base);
    GstFlowReturn result = GST_FLOW_OK;
    GstMapInfo map;
    const GValue* value;
    guint sampleIndex = 0;
    int errorCode;
    uint32_t trackID = 0;
    GstPad* pad;
    GstCaps* caps;
    GstMapInfo boxMap;
    GstBuffer* box = nullptr;
    GstProtectionMeta* protectionMeta = 0;
    gboolean boxMapped = FALSE;
    gboolean bufferMapped = FALSE;

    GST_TRACE_OBJECT(self, "Processing buffer");
    g_mutex_lock(&self->mutex);
    GST_TRACE_OBJECT(self, "Mutex acquired, stream received: %s", self->streamReceived ? "yes":"no");

    // The key might not have been received yet. Wait for it.
    if (!self->streamReceived)
        g_cond_wait(&self->condition, &self->mutex);

    if (!self->streamReceived) {
        GST_DEBUG_OBJECT(self, "Condition signaled from state change transition. Aborting.");
        result = GST_FLOW_NOT_SUPPORTED;
        goto beach;
    }

    GST_TRACE_OBJECT(self, "Proceeding with decryption");
    protectionMeta = reinterpret_cast<GstProtectionMeta*>(gst_buffer_get_protection_meta(buffer));
    if (!protectionMeta || !buffer) {
        if (!protectionMeta)
            GST_ERROR_OBJECT(self, "Failed to get GstProtection metadata from buffer %p", buffer);

        if (!buffer)
            GST_ERROR_OBJECT(self, "Failed to get writable buffer");

        result = GST_FLOW_NOT_SUPPORTED;
        goto beach;
    }

    bufferMapped = gst_buffer_map(buffer, &map, static_cast<GstMapFlags>(GST_MAP_READWRITE));
    if (!bufferMapped) {
        GST_ERROR_OBJECT(self, "Failed to map buffer");
        result = GST_FLOW_NOT_SUPPORTED;
        goto beach;
    }

    pad = gst_element_get_static_pad(GST_ELEMENT(self), "src");
    caps = gst_pad_get_current_caps(pad);
    if (g_str_has_prefix(gst_structure_get_name(gst_caps_get_structure(caps, 0)), "video/"))
        trackID = 1;
    else
        trackID = 2;
    gst_caps_unref(caps);
    gst_object_unref(pad);

    if (!gst_structure_get_uint(protectionMeta->info, "sample-index", &sampleIndex)) {
        GST_ERROR_OBJECT(self, "failed to get sample-index");
        result = GST_FLOW_NOT_SUPPORTED;
        goto beach;
    }

    value = gst_structure_get_value(protectionMeta->info, "box");
    if (!value) {
        GST_ERROR_OBJECT(self, "Failed to get encryption box for sample");
        result = GST_FLOW_NOT_SUPPORTED;
        goto beach;
    }

    box = gst_value_get_buffer(value);
    boxMapped = gst_buffer_map(box, &boxMap, GST_MAP_READ);
    if (!boxMapped) {
        GST_ERROR_OBJECT(self, "Failed to map encryption box");
        result = GST_FLOW_NOT_SUPPORTED;
        goto beach;
    }

    GST_TRACE_OBJECT(self, "decrypt sample %u", sampleIndex);
    if ((errorCode = self->sessionMetaData->decrypt(static_cast<void*>(map.data), static_cast<uint32_t>(map.size),
        static_cast<void*>(boxMap.data), static_cast<uint32_t>(boxMap.size), static_cast<uint32_t>(sampleIndex), trackID))) {
        GST_WARNING_OBJECT(self, "ERROR - packet decryption failed [%d]", errorCode);
        GST_MEMDUMP_OBJECT(self, "box", boxMap.data, boxMap.size);
        result = GST_FLOW_ERROR;
        goto beach;
    }

beach:
    if (boxMapped)
        gst_buffer_unmap(box, &boxMap);

    if (bufferMapped)
        gst_buffer_unmap(buffer, &map);

    if (protectionMeta)
        gst_buffer_remove_meta(buffer, reinterpret_cast<GstMeta*>(protectionMeta));

    GST_TRACE_OBJECT(self, "Unlocking mutex");
    g_mutex_unlock(&self->mutex);
    return result;
}
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;
}
Beispiel #19
0
static GstFlowReturn
gst_droidadec_handle_frame (GstAudioDecoder * decoder, GstBuffer * buffer)
{
  GstDroidADec *dec = GST_DROIDADEC (decoder);
  GstFlowReturn ret;
  DroidMediaCodecData data;
  DroidMediaBufferCallbacks cb;

  GST_DEBUG_OBJECT (dec, "handle frame");

  if (G_UNLIKELY (!buffer)) {
    return gst_droidadec_finish (decoder);
  }

  if (dec->downstream_flow_ret != GST_FLOW_OK) {
    GST_DEBUG_OBJECT (dec, "not handling frame in error state: %s",
        gst_flow_get_name (dec->downstream_flow_ret));
    ret = dec->downstream_flow_ret;
    goto error;
  }

  g_mutex_lock (&dec->eos_lock);
  if (dec->eos) {
    GST_WARNING_OBJECT (dec, "got frame in eos state");
    g_mutex_unlock (&dec->eos_lock);
    ret = GST_FLOW_EOS;
    goto error;
  }
  g_mutex_unlock (&dec->eos_lock);

  /* We must create the codec before we process any data. _create_codec will call
   * construct_decoder_codec_data which will store the nal prefix length for H264.
   * This is a bad situation. TODO: fix it
   */
  if (G_UNLIKELY (dec->dirty)) {
    if (dec->codec) {
      gst_droidadec_finish (decoder);
    }

    if (!gst_droidadec_create_codec (dec, buffer)) {
      ret = GST_FLOW_ERROR;
      goto error;
    }

    dec->dirty = FALSE;
  }

  if (!gst_droid_codec_process_decoder_data (dec->codec_type, buffer,
          &data.data)) {
    /* TODO: error */
    ret = GST_FLOW_ERROR;
    goto error;
  }

  cb.unref = g_free;
  cb.data = data.data.data;

  GST_DEBUG_OBJECT (dec, "decoding data of size %d (%d)",
      gst_buffer_get_size (buffer), data.data.size);

  /*
   * We are ignoring timestamping completely and relying
   * on the base class to do our bookkeeping ;-)
   */
  data.ts = 0;
  data.sync = false;

  /* This can deadlock if droidmedia/stagefright input buffer queue is full thus we
   * cannot write the input buffer. We end up waiting for the write operation
   * which does not happen because stagefright needs us to provide
   * output buffers to be filled (which can not happen because _loop() tries
   * to call get_oldest_frame() which acquires the stream lock the base class
   * is holding before calling us
   */
  GST_AUDIO_DECODER_STREAM_UNLOCK (decoder);
  droid_media_codec_queue (dec->codec, &data, &cb);
  GST_AUDIO_DECODER_STREAM_LOCK (decoder);

  /* from now on decoder owns a frame reference so we cannot use the out label otherwise
   * we will drop the needed reference
   */

  if (dec->downstream_flow_ret != GST_FLOW_OK) {
    GST_DEBUG_OBJECT (dec, "not handling frame in error state: %s",
        gst_flow_get_name (dec->downstream_flow_ret));
    ret = dec->downstream_flow_ret;
    goto out;
  }

  g_mutex_lock (&dec->eos_lock);
  if (dec->eos) {
    GST_WARNING_OBJECT (dec, "got frame in eos state");
    g_mutex_unlock (&dec->eos_lock);
    ret = GST_FLOW_EOS;
    goto out;
  }
  g_mutex_unlock (&dec->eos_lock);

  ret = GST_FLOW_OK;

out:
  return ret;

error:
  /* don't leak the frame */
  gst_audio_decoder_finish_frame (decoder, NULL, 1);

  return ret;
}
static int
gst_droidcamsrc_stream_window_dequeue_buffer (struct preview_stream_ops *w,
    buffer_handle_t ** buffer, int *stride)
{
  GstDroidCamSrcStreamWindow *win;
  GstBuffer *buff;
  GstFlowReturn ret;
  int trials;
  GstBufferPoolAcquireParams params;
  GstMemory *mem;
  struct ANativeWindowBuffer *native;
  int res;

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

  win = container_of (w, GstDroidCamSrcStreamWindow, window);

  g_mutex_lock (&win->lock);

retry:
  GST_DEBUG ("needs reconfigure? %d", win->needs_reconfigure);

  if (!win->pool || (win->pool && win->needs_reconfigure)) {
    /* create and re/configure the pool */
    gst_droidcamsrc_stream_window_reset_buffer_pool_locked (win);
  }

  if (!win->pool) {
    GST_ERROR ("failed to create buffer pool");
    res = -1;
    goto unlock_and_exit;
  }

  mem = NULL;
  trials = ACQUIRE_BUFFER_TRIALS;
  params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;

  while (trials > 0) {
    ret =
        gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (win->pool), &buff,
        &params);
    if (ret == GST_FLOW_OK) {
      /* we have our buffer */
      break;
    } else if (ret == GST_FLOW_ERROR || ret == GST_FLOW_FLUSHING) {
      /* no point in waiting */
      break;
    }

    /* we need to unlock here to allow buffers to be returned back */
    g_mutex_unlock (&win->lock);
    usleep (ACQUIRE_BUFFER_TIMEOUT);
    g_mutex_lock (&win->lock);
    if (win->needs_reconfigure) {
      /* out of here */
      goto retry;
    }

    --trials;
  }

  if (buff) {
    /* handover */
    mem = gst_buffer_peek_memory (buff, 0);
  } else if (ret == GST_FLOW_FLUSHING) {
    GST_INFO ("pool is flushing");
  } else {
    GST_WARNING ("failed to get a buffer");
  }

  if (!mem) {
    GST_ERROR ("no buffer memory found");

    res = -1;
    goto unlock_and_exit;
  }

  native = gst_memory_get_native_buffer (mem);
  if (!native) {
    GST_ERROR ("invalid buffer");
    gst_buffer_unref (buff);

    res = -1;
    goto unlock_and_exit;
  }

  *buffer = &native->handle;
  *stride = native->stride;

  GST_LOG ("dequeue buffer done %p", *buffer);

  res = 0;

unlock_and_exit:
  g_mutex_unlock (&win->lock);
  return res;
}
Beispiel #21
0
static void *
example_thread(void *data)
{
  NiceAgent *agent;
  NiceCandidate *local, *remote;
  GIOChannel* io_stdin;
  guint stream_id;
  gchar *line = NULL;
  int rval;

  io_stdin = g_io_channel_unix_new(fileno(stdin));
  g_io_channel_set_flags (io_stdin, G_IO_FLAG_NONBLOCK, NULL);

  // Create the nice agent
  agent = nice_agent_new(g_main_loop_get_context (gloop),
      NICE_COMPATIBILITY_RFC5245);
  if (agent == NULL)
    g_error("Failed to create agent");

  // Set the STUN settings and controlling mode
  if (stun_addr) {
    g_object_set(G_OBJECT(agent), "stun-server", stun_addr, NULL);
    g_object_set(G_OBJECT(agent), "stun-server-port", stun_port, NULL);
  }
  g_object_set(G_OBJECT(agent), "controlling-mode", controlling, NULL);

  // Connect to the signals
  g_signal_connect(G_OBJECT(agent), "candidate-gathering-done",
      G_CALLBACK(cb_candidate_gathering_done), NULL);
  g_signal_connect(G_OBJECT(agent), "new-selected-pair",
      G_CALLBACK(cb_new_selected_pair), NULL);
  g_signal_connect(G_OBJECT(agent), "component-state-changed",
      G_CALLBACK(cb_component_state_changed), NULL);

  // Create a new stream with one component
  stream_id = nice_agent_add_stream(agent, 1);
  if (stream_id == 0)
    g_error("Failed to add stream");

  // Attach to the component to receive the data
  // Without this call, candidates cannot be gathered
  nice_agent_attach_recv(agent, stream_id, 1,
      g_main_loop_get_context (gloop), cb_nice_recv, NULL);

  // Start gathering local candidates
  if (!nice_agent_gather_candidates(agent, stream_id))
    g_error("Failed to start candidate gathering");

  g_debug("waiting for candidate-gathering-done signal...");

  g_mutex_lock(&gather_mutex);
  while (!exit_thread && !candidate_gathering_done)
    g_cond_wait(&gather_cond, &gather_mutex);
  g_mutex_unlock(&gather_mutex);
  if (exit_thread)
    goto end;

  // Candidate gathering is done. Send our local candidates on stdout
  printf("Copy this line to remote client:\n");
  printf("\n  ");
  print_local_data(agent, stream_id, 1);
  printf("\n");

  // Listen on stdin for the remote candidate list
  printf("Enter remote data (single line, no wrapping):\n");
  printf("> ");
  fflush (stdout);
  while (!exit_thread) {
    GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL);
    if (s == G_IO_STATUS_NORMAL) {
      // Parse remote candidate list and set it on the agent
      rval = parse_remote_data(agent, stream_id, 1, line);
      if (rval == EXIT_SUCCESS) {
        g_free (line);
        break;
      } else {
        fprintf(stderr, "ERROR: failed to parse remote data\n");
        printf("Enter remote data (single line, no wrapping):\n");
        printf("> ");
        fflush (stdout);
      }
      g_free (line);
    } else if (s == G_IO_STATUS_AGAIN) {
      usleep (100000);
    }
  }

  g_debug("waiting for state READY or FAILED signal...");
  g_mutex_lock(&negotiate_mutex);
  while (!exit_thread && !negotiation_done)
    g_cond_wait(&negotiate_cond, &negotiate_mutex);
  g_mutex_unlock(&negotiate_mutex);
  if (exit_thread)
    goto end;

  // Get current selected candidate pair and print IP address used
  if (nice_agent_get_selected_pair (agent, stream_id, 1,
          &local, &remote)) {
    gchar ipaddr[INET6_ADDRSTRLEN];

    nice_address_to_string(&local->addr, ipaddr);
    printf("\nNegotiation complete: ([%s]:%d,",
        ipaddr, nice_address_get_port(&local->addr));
    nice_address_to_string(&remote->addr, ipaddr);
    printf(" [%s]:%d)\n", ipaddr, nice_address_get_port(&remote->addr));
  }

  // Listen to stdin and send data written to it
  printf("\nSend lines to remote (Ctrl-D to quit):\n");
  printf("> ");
  fflush (stdout);
  while (!exit_thread) {
    GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL);
    if (s == G_IO_STATUS_NORMAL) {
      nice_agent_send(agent, stream_id, 1, strlen(line), line);
      g_free (line);
      printf("> ");
      fflush (stdout);
    } else if (s == G_IO_STATUS_AGAIN) {
      usleep (100000);
    } else {
      // Ctrl-D was pressed.
      nice_agent_send(agent, stream_id, 1, 1, "\0");
      break;
    }
  }

end:
  g_io_channel_unref (io_stdin);
  g_object_unref(agent);
  g_main_loop_quit (gloop);

  return NULL;
}
Beispiel #22
0
GSList* action_database_lookup(ActionDatabase* database,char* name){
    g_mutex_lock(&(database->mutex));
    GSList* result = g_hash_table_lookup(database->hash_table,name);
    g_mutex_unlock(&(database->mutex));
    return result;
}
gboolean
eas_gdbus_call (struct eas_gdbus_client *client, const gchar *object,
		const gchar *interface, const gchar *method,
		EasProgressFn progress_fn, gpointer progress_data,
		const gchar *in_params, const gchar *out_params,
		GCancellable *cancellable, GError **error, ...)
{
	GDBusMessage *message;
	struct _eas_call_data call;
	GMainContext *ctxt;
	GVariant *v = NULL;
	va_list ap;
	gboolean success;
	guint cancel_handler_id;
	guint32 serial = 0;

	va_start (ap, error);

	message = g_dbus_message_new_method_call (EAS_SERVICE_NAME, object,
						  interface, method);

	v = g_variant_new_va (in_params, NULL, &ap);
	g_dbus_message_set_body (message, v);

	call.cancelled = FALSE;
	call.result = NULL;
	ctxt = g_main_context_new ();
	call.loop = g_main_loop_new (ctxt, FALSE);

	g_main_context_push_thread_default (ctxt);

	g_dbus_connection_send_message_with_reply (client->connection,
						   message,
						   G_DBUS_SEND_MESSAGE_FLAGS_NONE,
						   1000000,
						   &serial,
						   cancellable,
						   _call_done,
						   (gpointer) &call);
	g_object_unref (message);

	if (cancellable)
		cancel_handler_id = g_cancellable_connect (cancellable,
							  G_CALLBACK (_call_cancel),
							  (gpointer) &call, NULL);

	/* Ignore error; it's not the end of the world if progress info
	   is lost, and it should never happen anyway */
	if (progress_fn)
		eas_client_add_progress_info_to_table (client, serial, progress_fn,
						       progress_data, NULL);

	g_main_loop_run (call.loop);

	if (cancellable)
		g_cancellable_disconnect (cancellable, cancel_handler_id);

	success = eas_gdbus_call_finish (client, call.result, call.cancelled ? serial : 0,
					 out_params, &ap, error);

	if (serial && progress_fn) {
		EasProgressCallbackInfo *cbinfo;

		g_mutex_lock (client->progress_lock);
		cbinfo = g_hash_table_lookup (client->progress_fns_table,
					      GUINT_TO_POINTER (serial));
		if (cbinfo && cbinfo->calling) {
			g_debug ("Progress for call %u is running; wait for it to complete",
				 serial);
			g_hash_table_steal (client->progress_fns_table,
					    GUINT_TO_POINTER (serial));
			do {
				g_cond_wait (client->progress_cond, client->progress_lock);
			} while (cbinfo->calling);
			g_free (cbinfo);
		} else if (cbinfo) {
			g_hash_table_remove (client->progress_fns_table,
					     GUINT_TO_POINTER (serial));
		}
		g_mutex_unlock (client->progress_lock);
	}

	va_end (ap);

	g_main_context_pop_thread_default (ctxt);
	g_main_context_unref (ctxt);
	g_main_loop_unref (call.loop);
	g_object_unref (call.result);

	return success;
}
Beispiel #24
0
static void gst_shmdata_src_make_data_rendered(GstShmdataSrc *self){
  g_mutex_lock (&self->data_rendered_mutex);
  self->data_rendered = TRUE;
  g_cond_broadcast(&self->data_rendered_cond); 
  g_mutex_unlock (&self->data_rendered_mutex); 
}
Beispiel #25
0
static int
vips_sequential_generate( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsSequential *sequential = (VipsSequential *) b;
	VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( sequential );
        VipsRect *r = &or->valid;
	VipsRegion *ir = (VipsRegion *) seq;

	VIPS_DEBUG_MSG( "thread %p request for %d lines, start line %d\n", 
		g_thread_self(), r->height, r->top );

	if( sequential->trace )
		vips_diag( class->nickname, 
			"request for %d lines, starting at line %d", 
			r->height, r->top );

	g_mutex_lock( sequential->lock );

	VIPS_DEBUG_MSG( "thread %p has lock ...\n", g_thread_self() ); 

	/* If we've seen an error, everything must stop.
	 */
	if( sequential->error ) {
		g_mutex_unlock( sequential->lock );
		return( -1 );
	}

	if( r->top > sequential->y_pos && 
		sequential->y_pos > 0 ) {
		/* We have started reading (y_pos > 0) and this request is for 
		 * stuff beyond that, stall for a short while to give other
		 * threads time to catch up.
		 *
		 * The stall can be cancelled by a signal on @ready.
		 */
		VIPS_DEBUG_MSG( "thread %p stalling for up to %gs ...\n", 
			g_thread_self(), STALL_TIME ); 
		vips_g_cond_timed_wait( sequential->ready, 
			sequential->lock, STALL_TIME * 1000000 );
		VIPS_DEBUG_MSG( "thread %p awake again ...\n", 
			g_thread_self() ); 
	}

	/* This is a request for something some way down the image, and we've
	 * either not read anything yet or fallen through from the stall
	 * above. 
	 *
	 * Probably the operation is something like extract_area and we should 
	 * skip the initial part of the image. In fact, we read to cache,
	 * since it may be useful.
	 */
	if( r->top > sequential->y_pos ) {
		VipsRect area;

		VIPS_DEBUG_MSG( "thread %p skipping to line %d ...\n", 
			g_thread_self(),
			r->top );

		area.left = 0;
		area.top = sequential->y_pos;
		area.width = 1;
		area.height = r->top - sequential->y_pos;
		if( vips_region_prepare( ir, &area ) ) {
			VIPS_DEBUG_MSG( "thread %p error, unlocking ...\n", 
				g_thread_self() ); 
			sequential->error = -1;
			g_cond_broadcast( sequential->ready );
			g_mutex_unlock( sequential->lock );
			return( -1 );
		}

		sequential->y_pos = VIPS_RECT_BOTTOM( &area );
	}

	/* This is a request for old or present pixels -- serve from cache.
	 * This may trigger further, sequential reads.
	 */
	VIPS_DEBUG_MSG( "thread %p reading ...\n", g_thread_self() ); 
	if( vips_region_prepare( ir, r ) ||
		vips_region_region( or, ir, r, r->left, r->top ) ) {
		VIPS_DEBUG_MSG( "thread %p error, unlocking ...\n", 
			g_thread_self() ); 
		sequential->error = -1;
		g_cond_broadcast( sequential->ready );
		g_mutex_unlock( sequential->lock );
		return( -1 );
	}

	if( VIPS_RECT_BOTTOM( r ) > sequential->y_pos ) {
		/* This request has moved the read point. Update it, and wake 
		 * up all stalled threads for a retry.
		 */
		sequential->y_pos = VIPS_RECT_BOTTOM( r );

		VIPS_DEBUG_MSG( "thread %p updating y_pos to %d and "
			"waking stalled\n", 
			g_thread_self(),
			sequential->y_pos ); 

		g_cond_broadcast( sequential->ready );
	}

	VIPS_DEBUG_MSG( "thread %p unlocking ...\n", g_thread_self() ); 

	g_mutex_unlock( sequential->lock );

	return( 0 );
}
Beispiel #26
0
static GstFlowReturn
gst_shmdata_src_create (GstPushSrc *psrc, GstBuffer **outbuf)
{
  GstShmdataSrc *self = GST_SHMDATA_SRC (psrc);

  if (self->unlocked) {
    return GST_FLOW_FLUSHING;
  }

  g_mutex_lock (&self->on_data_mutex);
  while (!self->on_data && !self->unlocked)
    g_cond_wait_until (&self->on_data_cond,
                       &self->on_data_mutex,
                       g_get_monotonic_time () + 10 * G_TIME_SPAN_MILLISECOND);
  if (self->unlocked) {
    self->on_data = FALSE;
    g_mutex_unlock (&self->on_data_mutex);
    gst_shmdata_src_make_data_rendered(self);
    return GST_FLOW_FLUSHING;
  }
  self->on_data = FALSE;
  g_mutex_unlock (&self->on_data_mutex);

  if (self->is_first_read) {
    gst_shmdata_src_make_data_rendered(self);
    self->is_first_read = FALSE;
  }

  if (self->has_new_caps &&
      (GST_STATE_PAUSED == GST_STATE(self) || GST_STATE_PLAYING == GST_STATE(self))) {
    self->has_new_caps = FALSE;
    g_object_notify(G_OBJECT(self), "caps");
    GstPad *pad = gst_element_get_static_pad (GST_ELEMENT(self),"src");
    if(!gst_pad_set_caps (pad, self->caps)) {
      GST_ELEMENT_ERROR (GST_ELEMENT(self), CORE, NEGOTIATION, (NULL),
                         ("caps fix caps from shmdata type description"));
      return GST_FLOW_ERROR;
    }
    gst_object_unref(pad);
  }
  if(!self->copy_buffers){
    *outbuf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, 
                                           self->current_data,
                                           self->current_size,
                                           0,
                                           self->current_size,
                                           self,
                                           gst_shmdata_src_on_data_rendered);
  } else {
    GstBuffer *tmp = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, 
                                                  self->current_data,
                                                  self->current_size,
                                                  0,
                                                  self->current_size,
                                                  NULL,
                                                  NULL);
    *outbuf = gst_buffer_copy (tmp); 
    gst_shmdata_src_on_data_rendered(self);
    gst_buffer_unref(tmp);
  }
  
  return GST_FLOW_OK;
}
static void
gst_amc_audio_dec_loop (GstAmcAudioDec * self)
{
  GstFlowReturn flow_ret = GST_FLOW_OK;
  gboolean is_eos;
  GstAmcBufferInfo buffer_info;
  gint idx;

  GST_AUDIO_DECODER_STREAM_LOCK (self);

retry:
  /*if (self->input_caps_changed) {
     idx = INFO_OUTPUT_FORMAT_CHANGED;
     } else { */
  GST_DEBUG_OBJECT (self, "Waiting for available output buffer");
  GST_AUDIO_DECODER_STREAM_UNLOCK (self);
  /* Wait at most 100ms here, some codecs don't fail dequeueing if
   * the codec is flushing, causing deadlocks during shutdown */
  idx = gst_amc_codec_dequeue_output_buffer (self->codec, &buffer_info, 100000);
  GST_AUDIO_DECODER_STREAM_LOCK (self);
  /*} */

  if (idx < 0) {
    if (self->flushing)
      goto flushing;

    switch (idx) {
      case INFO_OUTPUT_BUFFERS_CHANGED:{
        GST_DEBUG_OBJECT (self, "Output buffers have changed");
        if (self->output_buffers)
          gst_amc_codec_free_buffers (self->output_buffers,
              self->n_output_buffers);
        self->output_buffers =
            gst_amc_codec_get_output_buffers (self->codec,
            &self->n_output_buffers);
        if (!self->output_buffers)
          goto get_output_buffers_error;
        break;
      }
      case INFO_OUTPUT_FORMAT_CHANGED:{
        GstAmcFormat *format;
        gchar *format_string;

        GST_DEBUG_OBJECT (self, "Output format has changed");

        format = gst_amc_codec_get_output_format (self->codec);
        if (!format)
          goto format_error;

        format_string = gst_amc_format_to_string (format);
        GST_DEBUG_OBJECT (self, "Got new output format: %s", format_string);
        g_free (format_string);

        if (!gst_amc_audio_dec_set_src_caps (self, format)) {
          gst_amc_format_free (format);
          goto format_error;
        }
        gst_amc_format_free (format);

        if (self->output_buffers)
          gst_amc_codec_free_buffers (self->output_buffers,
              self->n_output_buffers);
        self->output_buffers =
            gst_amc_codec_get_output_buffers (self->codec,
            &self->n_output_buffers);
        if (!self->output_buffers)
          goto get_output_buffers_error;

        goto retry;
        break;
      }
      case INFO_TRY_AGAIN_LATER:
        GST_DEBUG_OBJECT (self, "Dequeueing output buffer timed out");
        goto retry;
        break;
      case G_MININT:
        GST_ERROR_OBJECT (self, "Failure dequeueing output buffer");
        goto dequeue_error;
        break;
      default:
        g_assert_not_reached ();
        break;
    }

    goto retry;
  }

  GST_DEBUG_OBJECT (self,
      "Got output buffer at index %d: size %d time %" G_GINT64_FORMAT
      " flags 0x%08x", idx, buffer_info.size, buffer_info.presentation_time_us,
      buffer_info.flags);

  is_eos = ! !(buffer_info.flags & BUFFER_FLAG_END_OF_STREAM);
  self->n_buffers++;

  if (buffer_info.size > 0) {
    GstAmcAudioDecClass *klass = GST_AMC_AUDIO_DEC_GET_CLASS (self);
    GstBuffer *outbuf;
    GstAmcBuffer *buf;
    GstMapInfo minfo;

    /* This sometimes happens at EOS or if the input is not properly framed,
     * let's handle it gracefully by allocating a new buffer for the current
     * caps and filling it
     */
    if (idx >= self->n_output_buffers)
      goto invalid_buffer_index;

    if (strcmp (klass->codec_info->name, "OMX.google.mp3.decoder") == 0) {
      /* Google's MP3 decoder outputs garbage in the first output buffer
       * so we just drop it here */
      if (self->n_buffers == 1) {
        GST_DEBUG_OBJECT (self,
            "Skipping first buffer of Google MP3 decoder output");
        goto done;
      }
    }

    outbuf =
        gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (self),
        buffer_info.size);
    if (!outbuf)
      goto failed_allocate;

    gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
    buf = &self->output_buffers[idx];
    if (self->needs_reorder) {
      gint i, n_samples, c, n_channels;
      gint *reorder_map = self->reorder_map;
      gint16 *dest, *source;

      dest = (gint16 *) minfo.data;
      source = (gint16 *) (buf->data + buffer_info.offset);
      n_samples = buffer_info.size / self->info.bpf;
      n_channels = self->info.channels;

      for (i = 0; i < n_samples; i++) {
        for (c = 0; c < n_channels; c++) {
          dest[i * n_channels + reorder_map[c]] = source[i * n_channels + c];
        }
      }
    } else {
      orc_memcpy (minfo.data, buf->data + buffer_info.offset, buffer_info.size);
    }
    gst_buffer_unmap (outbuf, &minfo);

    /* FIXME: We should get one decoded input frame here for
     * every buffer. If this is not the case somewhere, we will
     * error out at some point and will need to add workarounds
     */
    flow_ret =
        gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf, 1);
  }

done:
  if (!gst_amc_codec_release_output_buffer (self->codec, idx, TRUE))
    goto failed_release;

  if (is_eos || flow_ret == GST_FLOW_EOS) {
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    g_mutex_lock (&self->drain_lock);
    if (self->draining) {
      GST_DEBUG_OBJECT (self, "Drained");
      self->draining = FALSE;
      g_cond_broadcast (&self->drain_cond);
    } else if (flow_ret == GST_FLOW_OK) {
      GST_DEBUG_OBJECT (self, "Component signalled EOS");
      flow_ret = GST_FLOW_EOS;
    }
    g_mutex_unlock (&self->drain_lock);
    GST_AUDIO_DECODER_STREAM_LOCK (self);
  } else {
    GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
  }

  self->downstream_flow_ret = flow_ret;

  if (flow_ret != GST_FLOW_OK)
    goto flow_error;

  GST_AUDIO_DECODER_STREAM_UNLOCK (self);

  return;

dequeue_error:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
        ("Failed to dequeue output buffer"));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_ERROR;
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }

get_output_buffers_error:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
        ("Failed to get output buffers"));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_ERROR;
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }

format_error:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
        ("Failed to handle format"));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_ERROR;
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }
failed_release:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
        ("Failed to release output buffer index %d", idx));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_ERROR;
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }
flushing:
  {
    GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_FLUSHING;
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }

flow_error:
  {
    if (flow_ret == GST_FLOW_EOS) {
      GST_DEBUG_OBJECT (self, "EOS");
      gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self),
          gst_event_new_eos ());
      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    } else if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_EOS) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED,
          ("Internal data stream error."), ("stream stopped, reason %s",
              gst_flow_get_name (flow_ret)));
      gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self),
          gst_event_new_eos ());
      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    }
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }

invalid_buffer_index:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
        ("Invalid input buffer index %d of %d", idx, self->n_input_buffers));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_ERROR;
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }

failed_allocate:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
        ("Failed to allocate output buffer"));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_ERROR;
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }
}
void
gst_soup_http_client_sink_set_property (GObject * object, guint property_id,
    const GValue * value, GParamSpec * pspec)
{
  GstSoupHttpClientSink *souphttpsink = GST_SOUP_HTTP_CLIENT_SINK (object);

  g_mutex_lock (&souphttpsink->mutex);
  switch (property_id) {
    case PROP_SESSION:
      if (souphttpsink->prop_session) {
        g_object_unref (souphttpsink->prop_session);
      }
      souphttpsink->prop_session = g_value_dup_object (value);
      break;
    case PROP_LOCATION:
      g_free (souphttpsink->location);
      souphttpsink->location = g_value_dup_string (value);
      souphttpsink->offset = 0;
      if ((souphttpsink->location == NULL)
          || !gst_uri_is_valid (souphttpsink->location)) {
        GST_WARNING_OBJECT (souphttpsink,
            "The location (\"%s\") set, is not a valid uri.",
            souphttpsink->location);
        g_free (souphttpsink->location);
        souphttpsink->location = NULL;
      }
      break;
    case PROP_USER_AGENT:
      g_free (souphttpsink->user_agent);
      souphttpsink->user_agent = g_value_dup_string (value);
      break;
    case PROP_AUTOMATIC_REDIRECT:
      souphttpsink->automatic_redirect = g_value_get_boolean (value);
      break;
    case PROP_USER_ID:
      g_free (souphttpsink->user_id);
      souphttpsink->user_id = g_value_dup_string (value);
      break;
    case PROP_USER_PW:
      g_free (souphttpsink->user_pw);
      souphttpsink->user_pw = g_value_dup_string (value);
      break;
    case PROP_PROXY_ID:
      g_free (souphttpsink->proxy_id);
      souphttpsink->proxy_id = g_value_dup_string (value);
      break;
    case PROP_PROXY_PW:
      g_free (souphttpsink->proxy_pw);
      souphttpsink->proxy_pw = g_value_dup_string (value);
      break;
    case PROP_PROXY:
    {
      const gchar *proxy;

      proxy = g_value_get_string (value);

      if (proxy == NULL) {
        GST_WARNING ("proxy property cannot be NULL");
        goto done;
      }
      if (!gst_soup_http_client_sink_set_proxy (souphttpsink, proxy)) {
        GST_WARNING ("badly formatted proxy URI");
        goto done;
      }
      break;
    }
    case PROP_COOKIES:
      g_strfreev (souphttpsink->cookies);
      souphttpsink->cookies = g_strdupv (g_value_get_boxed (value));
      break;
    case PROP_SOUP_LOG_LEVEL:
      souphttpsink->log_level = g_value_get_enum (value);
      break;
    case PROP_RETRY_DELAY:
      souphttpsink->retry_delay = g_value_get_int (value);
      break;
    case PROP_RETRIES:
      souphttpsink->retries = g_value_get_int (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
  }
done:
  g_mutex_unlock (&souphttpsink->mutex);
}
Beispiel #29
0
static CamelAuthenticationResult
ews_transport_authenticate_sync (CamelService *service,
				 const gchar *mechanism,
				 GCancellable *cancellable,
				 GError **error)
{
	CamelAuthenticationResult result;
	CamelEwsTransport *ews_transport;
	CamelSettings *settings;
	CamelEwsSettings *ews_settings;
	EEwsConnection *connection;
	const gchar *password;
	gchar *hosturl, *new_sync_state = NULL;
	GSList *folders_created = NULL;
	GSList *folders_updated = NULL;
	GSList *folders_deleted = NULL;
	gboolean includes_last_folder = FALSE;
	GError *local_error = NULL;

	ews_transport = CAMEL_EWS_TRANSPORT (service);

	password = camel_service_get_password (service);

	settings = camel_service_ref_settings (service);

	ews_settings = CAMEL_EWS_SETTINGS (settings);
	hosturl = camel_ews_settings_dup_hosturl (ews_settings);

	connection = e_ews_connection_new (hosturl, ews_settings);
	e_ews_connection_set_password (connection, password);

	g_free (hosturl);

	g_object_unref (settings);

	e_binding_bind_property (
		service, "proxy-resolver",
		connection, "proxy-resolver",
		G_BINDING_SYNC_CREATE);

	/* XXX We need to run some operation that requires authentication
	 *     but does not change any server-side state, so we can check
	 *     the error status and determine if our password is valid.
	 *     David suggested e_ews_connection_sync_folder_hierarchy(),
	 *     since we have to do that eventually anyway. */

	e_ews_connection_sync_folder_hierarchy_sync (connection, EWS_PRIORITY_MEDIUM, NULL,
		&new_sync_state, &includes_last_folder, &folders_created, &folders_updated, &folders_deleted,
		cancellable, &local_error);

	g_slist_free_full (folders_created, g_object_unref);
	g_slist_free_full (folders_updated, g_object_unref);
	g_slist_free_full (folders_deleted, g_free);
	g_free (new_sync_state);

	if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_UNAVAILABLE)) {
		local_error->domain = CAMEL_SERVICE_ERROR;
		local_error->code = CAMEL_SERVICE_ERROR_UNAVAILABLE;
	}

	if (!local_error) {
		g_mutex_lock (&ews_transport->priv->connection_lock);
		g_clear_object (&ews_transport->priv->connection);
		ews_transport->priv->connection = g_object_ref (connection);
		g_mutex_unlock (&ews_transport->priv->connection_lock);
	} else {
		g_mutex_lock (&ews_transport->priv->connection_lock);
		g_clear_object (&ews_transport->priv->connection);
		g_mutex_unlock (&ews_transport->priv->connection_lock);
	}

	if (!local_error) {
		result = CAMEL_AUTHENTICATION_ACCEPTED;
	} else if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED)) {
		g_clear_error (&local_error);
		result = CAMEL_AUTHENTICATION_REJECTED;
	} else {
		g_propagate_error (error, local_error);
		result = CAMEL_AUTHENTICATION_ERROR;
	}

	g_object_unref (connection);

	return result;
}
Beispiel #30
0
static void
pragha_scanner_update_handler(PraghaScanner *scanner, const gchar *dir_name)
{
	GDir *dir;
	const gchar *next_file = NULL;
	gchar *ab_file = NULL, *s_ab_file = NULL;
	GError *error = NULL;
	struct stat sbuf;
	PraghaMusicobject *mobj = NULL;

	if(g_cancellable_is_cancelled (scanner->cancellable))
		return;

	dir = g_dir_open(dir_name, 0, &error);
	if (!dir) {
		g_critical("Unable to open library : %s", dir_name);
		return;
	}

	next_file = g_dir_read_name(dir);
	while (next_file) {
		if(g_cancellable_is_cancelled (scanner->cancellable))
			return;

		ab_file = g_strconcat(dir_name, G_DIR_SEPARATOR_S, next_file, NULL);

		if (g_file_test(ab_file, G_FILE_TEST_IS_DIR)) {
			pragha_scanner_update_handler(scanner, ab_file);
		}
		else {
			mobj = g_hash_table_lookup(scanner->tracks_table,
			                           ab_file);
			if(!mobj) {
				mobj = new_musicobject_from_file(ab_file);
				if (G_LIKELY(mobj))
					 g_hash_table_insert(scanner->tracks_table,
					                     g_strdup(pragha_musicobject_get_file(mobj)),
					                     mobj);

			}
			else {
				if ((g_stat(ab_file, &sbuf) == 0) &&
				    (sbuf.st_mtime > scanner->last_update.tv_sec)) {
					mobj = new_musicobject_from_file(ab_file);
					if (G_LIKELY(mobj)) {
						g_hash_table_replace(scanner->tracks_table,
						                     g_strdup(pragha_musicobject_get_file(mobj)),
						                     mobj);
					}
				}
			}

			g_mutex_lock (&scanner->files_scanned_mutex);
			scanner->files_scanned++;
			g_mutex_unlock (&scanner->files_scanned_mutex);

			g_free(s_ab_file);
		}
		g_free(ab_file);
		next_file = g_dir_read_name(dir);
	}
	g_dir_close(dir);
}