static GstDevice *gst_pulse_device_new (guint id,
const gchar * device_name, GstCaps * caps, const gchar * internal_name,
- GstPulseDeviceType type, GstStructure * properties);
+ GstPulseDeviceType type, GstStructure * properties, gboolean is_default);
G_DEFINE_TYPE (GstPulseDeviceProvider, gst_pulse_device_provider,
GST_TYPE_DEVICE_PROVIDER);
};
+typedef struct
+{
+ GList *devices;
+ GstPulseDeviceProvider *self;
+} ListDevicesData;
+
static void
gst_pulse_device_provider_class_init (GstPulseDeviceProviderClass * klass)
{
g_free (self->client_name);
g_free (self->server);
+ g_free (self->default_sink_name);
+ g_free (self->default_source_name);
G_OBJECT_CLASS (gst_pulse_device_provider_parent_class)->finalize (object);
}
}
static GstDevice *
-new_source (const pa_source_info * info)
+new_source (GstPulseDeviceProvider * self, const pa_source_info * info)
{
GstCaps *caps;
GstStructure *props;
props = gst_pulse_make_structure (info->proplist);
return gst_pulse_device_new (info->index, info->description,
- caps, info->name, GST_PULSE_DEVICE_TYPE_SOURCE, props);
+ caps, info->name, GST_PULSE_DEVICE_TYPE_SOURCE, props,
+ !g_strcmp0 (info->name, self->default_source_name));
}
static GstDevice *
-new_sink (const pa_sink_info * info)
+new_sink (GstPulseDeviceProvider * self, const pa_sink_info * info)
{
GstCaps *caps;
GstStructure *props;
props = gst_pulse_make_structure (info->proplist);
return gst_pulse_device_new (info->index, info->description,
- caps, info->name, GST_PULSE_DEVICE_TYPE_SINK, props);
+ caps, info->name, GST_PULSE_DEVICE_TYPE_SINK, props,
+ !g_strcmp0 (info->name, self->default_sink_name));
}
static void
return;
}
- dev = new_source (info);
+ dev = new_source (self, info);
if (dev)
gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), dev);
}
static void
+get_server_info_cb (pa_context * context, const pa_server_info * info,
+ void *userdata)
+{
+ GstPulseDeviceProvider *self = userdata;
+
+ g_free (self->default_sink_name);
+ g_free (self->default_source_name);
+ self->default_sink_name = g_strdup (info->default_sink_name);
+ self->default_source_name = g_strdup (info->default_source_name);
+ GST_DEBUG_OBJECT (self, "Default sink name: %s", self->default_sink_name);
+
+ pa_threaded_mainloop_signal (self->mainloop, 0);
+}
+
+static void
get_sink_info_cb (pa_context * context,
const pa_sink_info * info, int eol, void *userdata)
{
return;
}
- dev = new_sink (info);
+ dev = new_sink (self, info);
if (dev)
gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), dev);
pa_subscription_event_type_t event_type =
type & PA_SUBSCRIPTION_EVENT_TYPE_MASK;
+ if (facility == PA_SUBSCRIPTION_EVENT_SERVER ||
+ facility != PA_SUBSCRIPTION_EVENT_CHANGE) {
+ pa_context_get_server_info (self->context, get_server_info_cb, self);
+
+ return;
+ }
+
if (facility != PA_SUBSCRIPTION_EVENT_SOURCE &&
facility != PA_SUBSCRIPTION_EVENT_SINK)
return;
get_source_info_list_cb (pa_context * context, const pa_source_info * info,
int eol, void *userdata)
{
- GList **devices = userdata;
+ ListDevicesData *data = userdata;
if (eol)
return;
- *devices = g_list_prepend (*devices, gst_object_ref_sink (new_source (info)));
+ data->devices =
+ g_list_prepend (data->devices,
+ gst_object_ref_sink (new_source (data->self, info)));
}
static void
get_sink_info_list_cb (pa_context * context, const pa_sink_info * info,
int eol, void *userdata)
{
- GList **devices = userdata;
+ ListDevicesData *data = userdata;
if (eol)
return;
- *devices = g_list_prepend (*devices, gst_object_ref_sink (new_sink (info)));
+ data->devices =
+ g_list_prepend (data->devices, gst_object_ref_sink (new_sink (data->self,
+ info)));
}
static GList *
gst_pulse_device_provider_probe (GstDeviceProvider * provider)
{
GstPulseDeviceProvider *self = GST_PULSE_DEVICE_PROVIDER (provider);
- GList *devices = NULL;
pa_mainloop *m = NULL;
pa_context *c = NULL;
pa_operation *o;
+ ListDevicesData data = { NULL, self };
if (!(m = pa_mainloop_new ()))
return NULL;
}
GST_DEBUG_OBJECT (self, "connected");
- o = pa_context_get_sink_info_list (c, get_sink_info_list_cb, &devices);
+ o = pa_context_get_sink_info_list (c, get_sink_info_list_cb, &data);
while (pa_operation_get_state (o) == PA_OPERATION_RUNNING &&
pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
if (pa_mainloop_iterate (m, TRUE, NULL) < 0)
}
pa_operation_unref (o);
- o = pa_context_get_source_info_list (c, get_source_info_list_cb, &devices);
+ o = pa_context_get_source_info_list (c, get_source_info_list_cb, &data);
while (pa_operation_get_state (o) == PA_OPERATION_RUNNING &&
pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
if (pa_mainloop_iterate (m, TRUE, NULL) < 0)
pa_context_disconnect (c);
pa_mainloop_free (m);
- return devices;
+ return data.devices;
failed:
}
static gboolean
+run_pulse_operation (GstPulseDeviceProvider * self, pa_operation * operation)
+{
+ if (!operation)
+ return FALSE;
+
+ while (pa_operation_get_state (operation) == PA_OPERATION_RUNNING) {
+ if (!PA_CONTEXT_IS_GOOD (pa_context_get_state ((self->context)))) {
+ pa_operation_cancel (operation);
+ pa_operation_unref (operation);
+ return FALSE;
+ }
+
+ pa_threaded_mainloop_wait (self->mainloop);
+ }
+
+ pa_operation_unref (operation);
+
+ return TRUE;
+}
+
+static gboolean
gst_pulse_device_provider_start (GstDeviceProvider * provider)
{
GstPulseDeviceProvider *self = GST_PULSE_DEVICE_PROVIDER (provider);
- pa_operation *initial_operation;
if (!(self->mainloop = pa_threaded_mainloop_new ())) {
GST_ERROR_OBJECT (self, "Could not create pulseaudio mainloop");
GST_DEBUG_OBJECT (self, "connected");
pa_context_subscribe (self->context,
- PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SINK, NULL, NULL);
-
- initial_operation = pa_context_get_source_info_list (self->context,
- get_source_info_cb, self);
- while (pa_operation_get_state (initial_operation) == PA_OPERATION_RUNNING) {
- if (!PA_CONTEXT_IS_GOOD (pa_context_get_state ((self->context))))
- goto cancel_and_fail;
+ PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SINK |
+ PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, NULL, NULL);
- pa_threaded_mainloop_wait (self->mainloop);
- }
- pa_operation_unref (initial_operation);
+ if (!run_pulse_operation (self, pa_context_get_server_info (self->context,
+ get_server_info_cb, self)))
+ goto unlock_and_fail;
- initial_operation = pa_context_get_sink_info_list (self->context,
- get_sink_info_cb, self);
- if (!initial_operation)
+ if (!run_pulse_operation (self,
+ pa_context_get_source_info_list (self->context, get_source_info_cb,
+ self)))
goto unlock_and_fail;
- while (pa_operation_get_state (initial_operation) == PA_OPERATION_RUNNING) {
- if (!PA_CONTEXT_IS_GOOD (pa_context_get_state ((self->context))))
- goto cancel_and_fail;
- pa_threaded_mainloop_wait (self->mainloop);
- }
- pa_operation_unref (initial_operation);
+ if (!run_pulse_operation (self, pa_context_get_sink_info_list (self->context,
+ get_sink_info_cb, self)))
+ goto unlock_and_fail;
pa_threaded_mainloop_unlock (self->mainloop);
mainloop_failed:
return FALSE;
-
-cancel_and_fail:
- pa_operation_cancel (initial_operation);
- pa_operation_unref (initial_operation);
- goto unlock_and_fail;
}
static void
static GstDevice *
gst_pulse_device_new (guint device_index, const gchar * device_name,
GstCaps * caps, const gchar * internal_name, GstPulseDeviceType type,
- GstStructure * props)
+ GstStructure * props, gboolean is_default)
{
GstPulseDevice *gstdev;
const gchar *element = NULL;
break;
}
-
+ gst_structure_set (props, "is-default", G_TYPE_BOOLEAN, is_default, NULL);
gstdev = g_object_new (GST_TYPE_PULSE_DEVICE,
"display-name", device_name, "caps", caps, "device-class", klass,
"internal-name", internal_name, "properties", props, NULL);
gstdev->type = type;
gstdev->device_index = device_index;
gstdev->element = element;
+ gstdev->is_default = is_default;
gst_structure_free (props);
gst_caps_unref (caps);