Exemplo n.º 1
0
static void
gst_pulsesrc_set_property (GObject * object,
    guint prop_id, const GValue * value, GParamSpec * pspec)
{

  GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (object);

  switch (prop_id) {
    case PROP_SERVER:
      g_free (pulsesrc->server);
      pulsesrc->server = g_value_dup_string (value);
      if (pulsesrc->probe)
        gst_pulseprobe_set_server (pulsesrc->probe, pulsesrc->server);
      break;
    case PROP_DEVICE:
      g_free (pulsesrc->device);
      pulsesrc->device = g_value_dup_string (value);
      break;
    case PROP_CLIENT_NAME:
      g_free (pulsesrc->client_name);
      if (!g_value_get_string (value)) {
        GST_WARNING_OBJECT (pulsesrc,
            "Empty PulseAudio client name not allowed. Resetting to default value");
        pulsesrc->client_name = gst_pulse_client_name ();
      } else
        pulsesrc->client_name = g_value_dup_string (value);
      break;
    case PROP_STREAM_PROPERTIES:
      if (pulsesrc->properties)
        gst_structure_free (pulsesrc->properties);
      pulsesrc->properties =
          gst_structure_copy (gst_value_get_structure (value));
      if (pulsesrc->proplist)
        pa_proplist_free (pulsesrc->proplist);
      pulsesrc->proplist = gst_pulse_make_proplist (pulsesrc->properties);
      break;
    case PROP_VOLUME:
      gst_pulsesrc_set_stream_volume (pulsesrc, g_value_get_double (value));
      break;
    case PROP_MUTE:
      gst_pulsesrc_set_stream_mute (pulsesrc, g_value_get_boolean (value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
static void
gst_pulsesrc_init (GstPulseSrc * pulsesrc, GstPulseSrcClass * klass)
{
  pulsesrc->server = NULL;
  pulsesrc->device = NULL;
  pulsesrc->client_name = gst_pulse_client_name ();
  pulsesrc->device_description = NULL;

  pulsesrc->context = NULL;
  pulsesrc->stream = NULL;

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

#ifdef HAVE_PULSE_0_9_13
  pa_sample_spec_init (&pulsesrc->sample_spec);
#else
  pulsesrc->sample_spec.format = PA_SAMPLE_INVALID;
  pulsesrc->sample_spec.rate = 0;
  pulsesrc->sample_spec.channels = 0;
#endif

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

  pulsesrc->mixer = NULL;

  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_base_audio_src_set_slave_method (GST_BASE_AUDIO_SRC (pulsesrc),
      GST_BASE_AUDIO_SRC_SLAVE_SKEW);
}
Exemplo n.º 4
0
static gboolean
gst_pulsesrc_open (GstAudioSrc * asrc)
{
  GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
  gchar *name = gst_pulse_client_name ();

  pa_threaded_mainloop_lock (pulsesrc->mainloop);

  g_assert (!pulsesrc->context);
  g_assert (!pulsesrc->stream);

  GST_DEBUG_OBJECT (pulsesrc, "opening device");

  if (!(pulsesrc->context =
          pa_context_new (pa_threaded_mainloop_get_api (pulsesrc->mainloop),
              name))) {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to create context"),
        (NULL));
    goto unlock_and_fail;
  }

  pa_context_set_state_callback (pulsesrc->context,
      gst_pulsesrc_context_state_cb, pulsesrc);

  GST_DEBUG_OBJECT (pulsesrc, "connect to server %s",
      GST_STR_NULL (pulsesrc->server));

  if (pa_context_connect (pulsesrc->context, pulsesrc->server, 0, NULL) < 0) {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
            pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
    goto unlock_and_fail;
  }

  for (;;) {
    pa_context_state_t state;

    state = pa_context_get_state (pulsesrc->context);

    if (!PA_CONTEXT_IS_GOOD (state)) {
      GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
              pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
      goto unlock_and_fail;
    }

    if (state == PA_CONTEXT_READY)
      break;

    /* Wait until the context is ready */
    pa_threaded_mainloop_wait (pulsesrc->mainloop);
  }
  GST_DEBUG_OBJECT (pulsesrc, "connected");

  pa_threaded_mainloop_unlock (pulsesrc->mainloop);

  g_free (name);
  return TRUE;

  /* ERRORS */
unlock_and_fail:
  {
    gst_pulsesrc_destroy_context (pulsesrc);

    pa_threaded_mainloop_unlock (pulsesrc->mainloop);

    g_free (name);
    return FALSE;
  }
}
Exemplo n.º 5
0
static gboolean
gst_pulsemixer_ctrl_open (GstPulseMixerCtrl * c)
{
  int e;
  gchar *name = gst_pulse_client_name ();
  pa_operation *o = NULL;

  g_assert (c);

  c->mainloop = pa_threaded_mainloop_new ();
  g_assert (c->mainloop);

  e = pa_threaded_mainloop_start (c->mainloop);
  g_assert (e == 0);

  pa_threaded_mainloop_lock (c->mainloop);

  if (!(c->context =
          pa_context_new (pa_threaded_mainloop_get_api (c->mainloop), name))) {
    GST_WARNING_OBJECT (c->object, "Failed to create context");
    goto unlock_and_fail;
  }

  pa_context_set_state_callback (c->context,
      gst_pulsemixer_ctrl_context_state_cb, c);
  pa_context_set_subscribe_callback (c->context,
      gst_pulsemixer_ctrl_subscribe_cb, c);

  if (pa_context_connect (c->context, c->server, 0, NULL) < 0) {
    GST_WARNING_OBJECT (c->object, "Failed to connect context: %s",
        pa_strerror (pa_context_errno (c->context)));
    goto unlock_and_fail;
  }

  /* Wait until the context is ready */
  pa_threaded_mainloop_wait (c->mainloop);

  if (pa_context_get_state (c->context) != PA_CONTEXT_READY) {
    GST_WARNING_OBJECT (c->object, "Failed to connect context: %s",
        pa_strerror (pa_context_errno (c->context)));
    goto unlock_and_fail;
  }

  /* Subscribe to events */

  if (!(o =
          pa_context_subscribe (c->context,
              PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE,
              gst_pulsemixer_ctrl_success_cb, c))) {
    GST_WARNING_OBJECT (c->object, "Failed to subscribe to events: %s",
        pa_strerror (pa_context_errno (c->context)));
    goto unlock_and_fail;
  }

  c->operation_success = 0;
  while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
    pa_threaded_mainloop_wait (c->mainloop);
    CHECK_DEAD_GOTO (c, unlock_and_fail);
  }

  if (!c->operation_success) {
    GST_WARNING_OBJECT (c->object, "Failed to subscribe to events: %s",
        pa_strerror (pa_context_errno (c->context)));
    goto unlock_and_fail;
  }
  pa_operation_unref (o);
  o = NULL;

  /* Get sink info */

  if (c->type == GST_PULSEMIXER_UNKNOWN || c->type == GST_PULSEMIXER_SINK) {
    if (!(o =
            pa_context_get_sink_info_by_name (c->context, c->device,
                gst_pulsemixer_ctrl_sink_info_cb, c))) {
      GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s",
          pa_strerror (pa_context_errno (c->context)));
      goto unlock_and_fail;
    }

    c->operation_success = 0;
    while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
      pa_threaded_mainloop_wait (c->mainloop);
      CHECK_DEAD_GOTO (c, unlock_and_fail);
    }

    pa_operation_unref (o);
    o = NULL;

    if (!c->operation_success && (c->type == GST_PULSEMIXER_SINK
            || pa_context_errno (c->context) != PA_ERR_NOENTITY)) {
      GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s",
          pa_strerror (pa_context_errno (c->context)));
      goto unlock_and_fail;
    }
  }

  if (c->type == GST_PULSEMIXER_UNKNOWN || c->type == GST_PULSEMIXER_SOURCE) {
    if (!(o =
            pa_context_get_source_info_by_name (c->context, c->device,
                gst_pulsemixer_ctrl_source_info_cb, c))) {
      GST_WARNING_OBJECT (c->object, "Failed to get source info: %s",
          pa_strerror (pa_context_errno (c->context)));
      goto unlock_and_fail;
    }

    c->operation_success = 0;
    while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
      pa_threaded_mainloop_wait (c->mainloop);
      CHECK_DEAD_GOTO (c, unlock_and_fail);
    }

    pa_operation_unref (o);
    o = NULL;

    if (!c->operation_success) {
      GST_WARNING_OBJECT (c->object, "Failed to get source info: %s",
          pa_strerror (pa_context_errno (c->context)));
      goto unlock_and_fail;
    }
  }

  g_assert (c->type != GST_PULSEMIXER_UNKNOWN);

  c->track = gst_pulsemixer_track_new (c);
  c->tracklist = g_list_append (c->tracklist, c->track);

  pa_threaded_mainloop_unlock (c->mainloop);
  g_free (name);

  return TRUE;

unlock_and_fail:

  if (o)
    pa_operation_unref (o);

  if (c->mainloop)
    pa_threaded_mainloop_unlock (c->mainloop);

  g_free (name);

  return FALSE;
}
Exemplo n.º 6
0
static void
gst_pulsesrc_class_init (GstPulseSrcClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS (klass);
  GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
  gchar *clientname;

  gobject_class->finalize = gst_pulsesrc_finalize;
  gobject_class->set_property = gst_pulsesrc_set_property;
  gobject_class->get_property = gst_pulsesrc_get_property;

  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_pulsesrc_change_state);

  gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_pulsesrc_negotiate);

  gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_pulsesrc_open);
  gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_pulsesrc_close);
  gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_prepare);
  gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_unprepare);
  gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_pulsesrc_read);
  gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_pulsesrc_delay);
  gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_pulsesrc_reset);

  /* Overwrite GObject fields */
  g_object_class_install_property (gobject_class,
      PROP_SERVER,
      g_param_spec_string ("server", "Server",
          "The PulseAudio server to connect to", DEFAULT_SERVER,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class, PROP_DEVICE,
      g_param_spec_string ("device", "Device",
          "The PulseAudio source device to connect to", DEFAULT_DEVICE,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class,
      PROP_DEVICE_NAME,
      g_param_spec_string ("device-name", "Device name",
          "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));

  clientname = gst_pulse_client_name ();
  /**
   * GstPulseSrc:client-name
   *
   * The PulseAudio client name to use.
   */
  g_object_class_install_property (gobject_class,
      PROP_CLIENT_NAME,
      g_param_spec_string ("client-name", "Client Name",
          "The PulseAudio client_name_to_use", clientname,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
          GST_PARAM_MUTABLE_READY));
  g_free (clientname);

  /**
   * GstPulseSrc:stream-properties
   *
   * List of pulseaudio stream properties. A list of defined properties can be
   * found in the <ulink href="http://0pointer.de/lennart/projects/pulseaudio/doxygen/proplist_8h.html">pulseaudio api docs</ulink>.
   *
   * Below is an example for registering as a music application to pulseaudio.
   * |[
   * GstStructure *props;
   *
   * props = gst_structure_from_string ("props,media.role=music", NULL);
   * g_object_set (pulse, "stream-properties", props, NULL);
   * gst_structure_free (props);
   * ]|
   *
   * Since: 0.10.26
   */
  g_object_class_install_property (gobject_class,
      PROP_STREAM_PROPERTIES,
      g_param_spec_boxed ("stream-properties", "stream properties",
          "list of pulseaudio stream properties",
          GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  /**
   * GstPulseSrc:source-output-index
   *
   * The index of the PulseAudio source output corresponding to this element.
   *
   * Since: 0.10.31
   */
  g_object_class_install_property (gobject_class,
      PROP_SOURCE_OUTPUT_INDEX,
      g_param_spec_uint ("source-output-index", "source output index",
          "The index of the PulseAudio source output corresponding to this "
          "record stream", 0, G_MAXUINT, PA_INVALID_INDEX,
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));

  gst_element_class_set_static_metadata (gstelement_class,
      "PulseAudio Audio Source",
      "Source/Audio",
      "Captures audio from a PulseAudio server", "Lennart Poettering");
  gst_element_class_add_pad_template (gstelement_class,
      gst_static_pad_template_get (&pad_template));

  /**
   * GstPulseSrc:volume
   *
   * The volume of the record stream.
   */
  g_object_class_install_property (gobject_class,
      PROP_VOLUME, g_param_spec_double ("volume", "Volume",
          "Linear volume of this stream, 1.0=100%",
          0.0, MAX_VOLUME, DEFAULT_VOLUME,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  /**
   * GstPulseSrc:mute
   *
   * Whether the stream is muted or not.
   */
  g_object_class_install_property (gobject_class,
      PROP_MUTE, g_param_spec_boolean ("mute", "Mute",
          "Mute state of this stream",
          DEFAULT_MUTE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
Exemplo n.º 7
0
static void
gst_pulsesrc_class_init (GstPulseSrcClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS (klass);
  GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);

  gobject_class->finalize = gst_pulsesrc_finalize;
  gobject_class->set_property = gst_pulsesrc_set_property;
  gobject_class->get_property = gst_pulsesrc_get_property;

  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_pulsesrc_change_state);

  gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_pulsesrc_negotiate);

  gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_pulsesrc_open);
  gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_pulsesrc_close);
  gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_prepare);
  gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_unprepare);
  gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_pulsesrc_read);
  gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_pulsesrc_delay);
  gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_pulsesrc_reset);

  /* Overwrite GObject fields */
  g_object_class_install_property (gobject_class,
      PROP_SERVER,
      g_param_spec_string ("server", "Server",
          "The PulseAudio server to connect to", DEFAULT_SERVER,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class, PROP_DEVICE,
      g_param_spec_string ("device", "Device",
          "The PulseAudio source device to connect to", DEFAULT_DEVICE,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class,
      PROP_DEVICE_NAME,
      g_param_spec_string ("device-name", "Device name",
          "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));

  /**
   * GstPulseSink:client
   *
   * The PulseAudio client name to use.
   *
   * Since: 0.10.27
   */
  g_object_class_install_property (gobject_class,
      PROP_CLIENT,
      g_param_spec_string ("client", "Client",
          "The PulseAudio client_name_to_use", gst_pulse_client_name (),
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
          GST_PARAM_MUTABLE_READY));

  /**
   * GstPulseSrc:stream-properties
   *
   * List of pulseaudio stream properties. A list of defined properties can be
   * found in the <ulink href="http://0pointer.de/lennart/projects/pulseaudio/doxygen/proplist_8h.html">pulseaudio api docs</ulink>.
   *
   * Below is an example for registering as a music application to pulseaudio.
   * |[
   * GstStructure *props;
   *
   * props = gst_structure_from_string ("props,media.role=music", NULL);
   * g_object_set (pulse, "stream-properties", props, NULL);
   * gst_structure_free (props);
   * ]|
   *
   * Since: 0.10.26
   */
  g_object_class_install_property (gobject_class,
      PROP_STREAM_PROPERTIES,
      g_param_spec_boxed ("stream-properties", "stream properties",
          "list of pulseaudio stream properties",
          GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}