コード例 #1
0
static void
gst_opensles_src_init (GstOpenSLESSrc * src)
{
  /* Override some default values to fit on the AudioFlinger behaviour of
   * processing 20ms buffers as minimum buffer size. */
  GST_AUDIO_BASE_SRC (src)->buffer_time = 400000;
  GST_AUDIO_BASE_SRC (src)->latency_time = 20000;
}
コード例 #2
0
static guint
gst_dshowaudiosrc_read (GstAudioSrc * asrc, gpointer data, guint length, GstClockTime *timestamp)
{
  GstDshowAudioSrc *src = GST_DSHOWAUDIOSRC (asrc);
  guint ret = 0;

  if (!src->is_running)
    return -1;

  if (src->gbarray) {
  test:
    if (src->gbarray->len >= length) {
      g_mutex_lock (&src->gbarray_lock);
      memcpy (data, src->gbarray->data + (src->gbarray->len - length), length);
      g_byte_array_remove_range (src->gbarray, src->gbarray->len - length,
          length);
      ret = length;
      g_mutex_unlock (&src->gbarray_lock);
    } else {
      if (src->is_running) {
        Sleep (GST_AUDIO_BASE_SRC(src)->ringbuffer->spec.latency_time /
            GST_MSECOND / 10);
        goto test;
      }
    }
  }

  return ret;
}
コード例 #3
0
ファイル: gstalsasrc.c プロジェクト: rawoul/gst-plugins-base
static GstStateChangeReturn
gst_alsasrc_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
  GstAudioBaseSrc *src = GST_AUDIO_BASE_SRC (element);
  GstAlsaSrc *alsa = GST_ALSA_SRC (element);
  GstClock *clk;

  switch (transition) {
      /* show the compiler that we care */
    case GST_STATE_CHANGE_NULL_TO_READY:
    case GST_STATE_CHANGE_READY_TO_PAUSED:
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
    case GST_STATE_CHANGE_PAUSED_TO_READY:
    case GST_STATE_CHANGE_READY_TO_NULL:
      break;

    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      clk = src->clock;
      alsa->driver_timestamps = FALSE;
      if (GST_IS_SYSTEM_CLOCK (clk)) {
        gint clocktype;
        g_object_get (clk, "clock-type", &clocktype, NULL);
        if (clocktype == GST_CLOCK_TYPE_MONOTONIC) {
          GST_INFO ("Using driver timestamps !");
          alsa->driver_timestamps = TRUE;
        }
      }
      break;
  }
  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  return ret;
}
コード例 #4
0
ファイル: pulsesrc.c プロジェクト: PeterXu/gst-mobile
static void
gst_pulsesrc_init (GstPulseSrc * pulsesrc)
{
  pulsesrc->server = NULL;
  pulsesrc->device = NULL;
  pulsesrc->client_name = gst_pulse_client_name ();
  pulsesrc->device_description = NULL;

  pulsesrc->context = NULL;
  pulsesrc->stream = NULL;
  pulsesrc->stream_connected = FALSE;
  pulsesrc->source_output_idx = PA_INVALID_INDEX;

  pulsesrc->read_buffer = NULL;
  pulsesrc->read_buffer_length = 0;

  pa_sample_spec_init (&pulsesrc->sample_spec);

  pulsesrc->operation_success = FALSE;
  pulsesrc->paused = TRUE;
  pulsesrc->in_read = FALSE;

  pulsesrc->volume = DEFAULT_VOLUME;
  pulsesrc->volume_set = FALSE;

  pulsesrc->mute = DEFAULT_MUTE;
  pulsesrc->mute_set = FALSE;

  pulsesrc->notify = 0;

  pulsesrc->properties = NULL;
  pulsesrc->proplist = NULL;

  pulsesrc->probe = gst_pulseprobe_new (G_OBJECT (pulsesrc), G_OBJECT_GET_CLASS (pulsesrc), PROP_DEVICE, pulsesrc->server, FALSE, TRUE);        /* FALSE for sinks, TRUE for sources */

  /* this should be the default but it isn't yet */
  gst_audio_base_src_set_slave_method (GST_AUDIO_BASE_SRC (pulsesrc),
      GST_AUDIO_BASE_SRC_SLAVE_SKEW);

  /* override with a custom clock */
  if (GST_AUDIO_BASE_SRC (pulsesrc)->clock)
    gst_object_unref (GST_AUDIO_BASE_SRC (pulsesrc)->clock);

  GST_AUDIO_BASE_SRC (pulsesrc)->clock =
      gst_audio_clock_new ("GstPulseSrcClock",
      (GstAudioClockGetTimeFunc) gst_pulsesrc_get_time, pulsesrc, NULL);
}
コード例 #5
0
static gboolean
gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
{
  GstAlsaSrc *alsa;
  gint err;

  alsa = GST_ALSA_SRC (asrc);

  if (!alsasrc_parse_spec (alsa, spec))
    goto spec_parse;

  CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);

  CHECK (set_hwparams (alsa), hw_params_failed);
  CHECK (set_swparams (alsa), sw_params_failed);
  CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);

  alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info);
  spec->segsize = alsa->period_size * alsa->bpf;
  spec->segtotal = alsa->buffer_size / alsa->period_size;

  {
    snd_output_t *out_buf = NULL;
    char *msg = NULL;

    snd_output_buffer_open (&out_buf);
    snd_pcm_dump_hw_setup (alsa->handle, out_buf);
    snd_output_buffer_string (out_buf, &msg);
    GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
    snd_output_close (out_buf);
    snd_output_buffer_open (&out_buf);
    snd_pcm_dump_sw_setup (alsa->handle, out_buf);
    snd_output_buffer_string (out_buf, &msg);
    GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
    snd_output_close (out_buf);
  }

#ifdef SND_CHMAP_API_VERSION
  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9) {
    snd_pcm_chmap_t *chmap = snd_pcm_get_chmap (alsa->handle);
    if (chmap && chmap->channels == alsa->channels) {
      GstAudioChannelPosition pos[8];
      if (alsa_chmap_to_channel_positions (chmap, pos))
        gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
            (alsa)->ringbuffer, pos);
    }
    free (chmap);
  }
#endif /* SND_CHMAP_API_VERSION */

  return TRUE;

  /* ERRORS */
spec_parse:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Error parsing spec"));
    return FALSE;
  }
non_block:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Could not set device to blocking: %s", snd_strerror (err)));
    return FALSE;
  }
hw_params_failed:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Setting of hwparams failed: %s", snd_strerror (err)));
    return FALSE;
  }
sw_params_failed:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Setting of swparams failed: %s", snd_strerror (err)));
    return FALSE;
  }
prepare_failed:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Prepare failed: %s", snd_strerror (err)));
    return FALSE;
  }
}
コード例 #6
0
static gboolean
alsasrc_parse_spec (GstAlsaSrc * alsa, GstAudioRingBufferSpec * spec)
{
  switch (spec->type) {
    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW:
      switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
        case GST_AUDIO_FORMAT_U8:
          alsa->format = SND_PCM_FORMAT_U8;
          break;
        case GST_AUDIO_FORMAT_S8:
          alsa->format = SND_PCM_FORMAT_S8;
          break;
        case GST_AUDIO_FORMAT_S16LE:
          alsa->format = SND_PCM_FORMAT_S16_LE;
          break;
        case GST_AUDIO_FORMAT_S16BE:
          alsa->format = SND_PCM_FORMAT_S16_BE;
          break;
        case GST_AUDIO_FORMAT_U16LE:
          alsa->format = SND_PCM_FORMAT_U16_LE;
          break;
        case GST_AUDIO_FORMAT_U16BE:
          alsa->format = SND_PCM_FORMAT_U16_BE;
          break;
        case GST_AUDIO_FORMAT_S24_32LE:
          alsa->format = SND_PCM_FORMAT_S24_LE;
          break;
        case GST_AUDIO_FORMAT_S24_32BE:
          alsa->format = SND_PCM_FORMAT_S24_BE;
          break;
        case GST_AUDIO_FORMAT_U24_32LE:
          alsa->format = SND_PCM_FORMAT_U24_LE;
          break;
        case GST_AUDIO_FORMAT_U24_32BE:
          alsa->format = SND_PCM_FORMAT_U24_BE;
          break;
        case GST_AUDIO_FORMAT_S32LE:
          alsa->format = SND_PCM_FORMAT_S32_LE;
          break;
        case GST_AUDIO_FORMAT_S32BE:
          alsa->format = SND_PCM_FORMAT_S32_BE;
          break;
        case GST_AUDIO_FORMAT_U32LE:
          alsa->format = SND_PCM_FORMAT_U32_LE;
          break;
        case GST_AUDIO_FORMAT_U32BE:
          alsa->format = SND_PCM_FORMAT_U32_BE;
          break;
        case GST_AUDIO_FORMAT_S24LE:
          alsa->format = SND_PCM_FORMAT_S24_3LE;
          break;
        case GST_AUDIO_FORMAT_S24BE:
          alsa->format = SND_PCM_FORMAT_S24_3BE;
          break;
        case GST_AUDIO_FORMAT_U24LE:
          alsa->format = SND_PCM_FORMAT_U24_3LE;
          break;
        case GST_AUDIO_FORMAT_U24BE:
          alsa->format = SND_PCM_FORMAT_U24_3BE;
          break;
        case GST_AUDIO_FORMAT_S20LE:
          alsa->format = SND_PCM_FORMAT_S20_3LE;
          break;
        case GST_AUDIO_FORMAT_S20BE:
          alsa->format = SND_PCM_FORMAT_S20_3BE;
          break;
        case GST_AUDIO_FORMAT_U20LE:
          alsa->format = SND_PCM_FORMAT_U20_3LE;
          break;
        case GST_AUDIO_FORMAT_U20BE:
          alsa->format = SND_PCM_FORMAT_U20_3BE;
          break;
        case GST_AUDIO_FORMAT_S18LE:
          alsa->format = SND_PCM_FORMAT_S18_3LE;
          break;
        case GST_AUDIO_FORMAT_S18BE:
          alsa->format = SND_PCM_FORMAT_S18_3BE;
          break;
        case GST_AUDIO_FORMAT_U18LE:
          alsa->format = SND_PCM_FORMAT_U18_3LE;
          break;
        case GST_AUDIO_FORMAT_U18BE:
          alsa->format = SND_PCM_FORMAT_U18_3BE;
          break;
        case GST_AUDIO_FORMAT_F32LE:
          alsa->format = SND_PCM_FORMAT_FLOAT_LE;
          break;
        case GST_AUDIO_FORMAT_F32BE:
          alsa->format = SND_PCM_FORMAT_FLOAT_BE;
          break;
        case GST_AUDIO_FORMAT_F64LE:
          alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
          break;
        case GST_AUDIO_FORMAT_F64BE:
          alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
          break;
        default:
          goto error;
      }
      break;
    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW:
      alsa->format = SND_PCM_FORMAT_A_LAW;
      break;
    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW:
      alsa->format = SND_PCM_FORMAT_MU_LAW;
      break;
    default:
      goto error;

  }
  alsa->rate = GST_AUDIO_INFO_RATE (&spec->info);
  alsa->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
  alsa->buffer_time = spec->buffer_time;
  alsa->period_time = spec->latency_time;
  alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;

  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9)
    gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
        (alsa)->ringbuffer, alsa_position[alsa->channels - 1]);

  return TRUE;

  /* ERRORS */
error:
  {
    return FALSE;
  }
}
コード例 #7
0
ファイル: gstalsasrc.c プロジェクト: thaytan/gst-plugins-base
static gboolean
gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
{
  GstAlsaSrc *alsa;
  gint err;

  alsa = GST_ALSA_SRC (asrc);

  if (!alsasrc_parse_spec (alsa, spec))
    goto spec_parse;

  CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);

  CHECK (set_hwparams (alsa), hw_params_failed);
  CHECK (set_swparams (alsa), sw_params_failed);
  CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);

  alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info);
  spec->segsize = alsa->period_size * alsa->bpf;
  spec->segtotal = alsa->buffer_size / alsa->period_size;

  {
    snd_output_t *out_buf = NULL;
    char *msg = NULL;

    snd_output_buffer_open (&out_buf);
    snd_pcm_dump_hw_setup (alsa->handle, out_buf);
    snd_output_buffer_string (out_buf, &msg);
    GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
    snd_output_close (out_buf);
    snd_output_buffer_open (&out_buf);
    snd_pcm_dump_sw_setup (alsa->handle, out_buf);
    snd_output_buffer_string (out_buf, &msg);
    GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
    snd_output_close (out_buf);
  }

#ifdef SND_CHMAP_API_VERSION
  alsa_detect_channels_mapping (GST_OBJECT (alsa), alsa->handle, spec,
      alsa->channels, GST_AUDIO_BASE_SRC (alsa)->ringbuffer);
#endif /* SND_CHMAP_API_VERSION */

  return TRUE;

  /* ERRORS */
spec_parse:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Error parsing spec"));
    return FALSE;
  }
non_block:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Could not set device to blocking: %s", snd_strerror (err)));
    return FALSE;
  }
hw_params_failed:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Setting of hwparams failed: %s", snd_strerror (err)));
    return FALSE;
  }
sw_params_failed:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Setting of swparams failed: %s", snd_strerror (err)));
    return FALSE;
  }
prepare_failed:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Prepare failed: %s", snd_strerror (err)));
    return FALSE;
  }
}
コード例 #8
0
ファイル: pulsesrc.c プロジェクト: PeterXu/gst-mobile
static GstStateChangeReturn
gst_pulsesrc_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret;
  GstPulseSrc *this = GST_PULSESRC_CAST (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      if (!(this->mainloop = pa_threaded_mainloop_new ()))
        goto mainloop_failed;
      if (pa_threaded_mainloop_start (this->mainloop) < 0) {
        pa_threaded_mainloop_free (this->mainloop);
        this->mainloop = NULL;
        goto mainloop_start_failed;
      }
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      gst_element_post_message (element,
          gst_message_new_clock_provide (GST_OBJECT_CAST (element),
              GST_AUDIO_BASE_SRC (this)->clock, TRUE));
      break;
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      /* uncork and start recording */
      gst_pulsesrc_play (this);
      break;
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      /* stop recording ASAP by corking */
      pa_threaded_mainloop_lock (this->mainloop);
      GST_DEBUG_OBJECT (this, "corking");
      gst_pulsesrc_set_corked (this, TRUE, FALSE);
      pa_threaded_mainloop_unlock (this->mainloop);
      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      /* now make sure we get out of the _read method */
      gst_pulsesrc_pause (this);
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      if (this->mainloop)
        pa_threaded_mainloop_stop (this->mainloop);

      gst_pulsesrc_destroy_context (this);

      if (this->mainloop) {
        pa_threaded_mainloop_free (this->mainloop);
        this->mainloop = NULL;
      }
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      /* format_lost is reset in release() in baseaudiosink */
      gst_element_post_message (element,
          gst_message_new_clock_lost (GST_OBJECT_CAST (element),
              GST_AUDIO_BASE_SRC (this)->clock));
      break;
    default:
      break;
  }

  return ret;

  /* ERRORS */
mainloop_failed:
  {
    GST_ELEMENT_ERROR (this, RESOURCE, FAILED,
        ("pa_threaded_mainloop_new() failed"), (NULL));
    return GST_STATE_CHANGE_FAILURE;
  }
mainloop_start_failed:
  {
    GST_ELEMENT_ERROR (this, RESOURCE, FAILED,
        ("pa_threaded_mainloop_start() failed"), (NULL));
    return GST_STATE_CHANGE_FAILURE;
  }
}
コード例 #9
0
ファイル: pulsesrc.c プロジェクト: PeterXu/gst-mobile
static gboolean
gst_pulsesrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
{
  pa_buffer_attr wanted;
  const pa_buffer_attr *actual;
  GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
  pa_stream_flags_t flags;
  pa_operation *o;
  GstAudioClock *clock;

  pa_threaded_mainloop_lock (pulsesrc->mainloop);

  {
    GstAudioRingBufferSpec s = *spec;
    const pa_channel_map *m;

    m = pa_stream_get_channel_map (pulsesrc->stream);
    gst_pulse_channel_map_to_gst (m, &s);
    gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
        (pulsesrc)->ringbuffer, s.info.position);
  }

  /* enable event notifications */
  GST_LOG_OBJECT (pulsesrc, "subscribing to context events");
  if (!(o = pa_context_subscribe (pulsesrc->context,
              PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, NULL, NULL))) {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
        ("pa_context_subscribe() failed: %s",
            pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
    goto unlock_and_fail;
  }

  pa_operation_unref (o);

  wanted.maxlength = -1;
  wanted.tlength = -1;
  wanted.prebuf = 0;
  wanted.minreq = -1;
  wanted.fragsize = spec->segsize;

  GST_INFO_OBJECT (pulsesrc, "maxlength: %d", wanted.maxlength);
  GST_INFO_OBJECT (pulsesrc, "tlength:   %d", wanted.tlength);
  GST_INFO_OBJECT (pulsesrc, "prebuf:    %d", wanted.prebuf);
  GST_INFO_OBJECT (pulsesrc, "minreq:    %d", wanted.minreq);
  GST_INFO_OBJECT (pulsesrc, "fragsize:  %d", wanted.fragsize);

  flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE |
      PA_STREAM_NOT_MONOTONIC | PA_STREAM_ADJUST_LATENCY |
      PA_STREAM_START_CORKED;

  if (pulsesrc->mute_set && pulsesrc->mute)
    flags |= PA_STREAM_START_MUTED;

  if (pa_stream_connect_record (pulsesrc->stream, pulsesrc->device, &wanted,
          flags) < 0) {
    goto connect_failed;
  }

  /* our clock will now start from 0 again */
  clock = GST_AUDIO_CLOCK (GST_AUDIO_BASE_SRC (pulsesrc)->clock);
  gst_audio_clock_reset (clock, 0);

  pulsesrc->corked = TRUE;

  for (;;) {
    pa_stream_state_t state;

    state = pa_stream_get_state (pulsesrc->stream);

    if (!PA_STREAM_IS_GOOD (state))
      goto stream_is_bad;

    if (state == PA_STREAM_READY)
      break;

    /* Wait until the stream is ready */
    pa_threaded_mainloop_wait (pulsesrc->mainloop);
  }
  pulsesrc->stream_connected = TRUE;

  /* store the source output index so it can be accessed via a property */
  pulsesrc->source_output_idx = pa_stream_get_index (pulsesrc->stream);
  g_object_notify (G_OBJECT (pulsesrc), "source-output-index");

  if (pulsesrc->volume_set) {
    gst_pulsesrc_set_stream_volume (pulsesrc, pulsesrc->volume);
    pulsesrc->volume_set = FALSE;
  }

  /* get the actual buffering properties now */
  actual = pa_stream_get_buffer_attr (pulsesrc->stream);

  GST_INFO_OBJECT (pulsesrc, "maxlength: %d", actual->maxlength);
  GST_INFO_OBJECT (pulsesrc, "tlength:   %d (wanted: %d)",
      actual->tlength, wanted.tlength);
  GST_INFO_OBJECT (pulsesrc, "prebuf:    %d", actual->prebuf);
  GST_INFO_OBJECT (pulsesrc, "minreq:    %d (wanted %d)", actual->minreq,
      wanted.minreq);
  GST_INFO_OBJECT (pulsesrc, "fragsize:  %d (wanted %d)",
      actual->fragsize, wanted.fragsize);

  if (actual->fragsize >= wanted.fragsize) {
    spec->segsize = actual->fragsize;
  } else {
    spec->segsize = actual->fragsize * (wanted.fragsize / actual->fragsize);
  }
  spec->segtotal = actual->maxlength / spec->segsize;

  if (!pulsesrc->paused) {
    GST_DEBUG_OBJECT (pulsesrc, "uncorking because we are playing");
    gst_pulsesrc_set_corked (pulsesrc, FALSE, FALSE);
  }
  pa_threaded_mainloop_unlock (pulsesrc->mainloop);

  return TRUE;

  /* ERRORS */
connect_failed:
  {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
        ("Failed to connect stream: %s",
            pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
    goto unlock_and_fail;
  }
stream_is_bad:
  {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
        ("Failed to connect stream: %s",
            pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
    goto unlock_and_fail;
  }
unlock_and_fail:
  {
    gst_pulsesrc_destroy_stream (pulsesrc);

    pa_threaded_mainloop_unlock (pulsesrc->mainloop);
    return FALSE;
  }
}