mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
pulse: Mark default devices as "default"
This commit is contained in:
parent
6db7bb1539
commit
7bc5e28d85
2 changed files with 90 additions and 43 deletions
|
@ -40,7 +40,7 @@ GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
|
|||
|
||||
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);
|
||||
|
@ -65,6 +65,12 @@ enum
|
|||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GList *devices;
|
||||
GstPulseDeviceProvider *self;
|
||||
} ListDevicesData;
|
||||
|
||||
static void
|
||||
gst_pulse_device_provider_class_init (GstPulseDeviceProviderClass * klass)
|
||||
{
|
||||
|
@ -114,6 +120,8 @@ gst_pulse_device_provider_finalize (GObject * object)
|
|||
|
||||
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);
|
||||
}
|
||||
|
@ -186,7 +194,7 @@ context_state_cb (pa_context * c, void *userdata)
|
|||
}
|
||||
|
||||
static GstDevice *
|
||||
new_source (const pa_source_info * info)
|
||||
new_source (GstPulseDeviceProvider * self, const pa_source_info * info)
|
||||
{
|
||||
GstCaps *caps;
|
||||
GstStructure *props;
|
||||
|
@ -200,11 +208,12 @@ new_source (const pa_source_info * info)
|
|||
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;
|
||||
|
@ -218,7 +227,8 @@ new_sink (const pa_sink_info * info)
|
|||
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
|
||||
|
@ -233,12 +243,27 @@ get_source_info_cb (pa_context * context,
|
|||
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)
|
||||
|
@ -251,7 +276,7 @@ get_sink_info_cb (pa_context * context,
|
|||
return;
|
||||
}
|
||||
|
||||
dev = new_sink (info);
|
||||
dev = new_sink (self, info);
|
||||
|
||||
if (dev)
|
||||
gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), dev);
|
||||
|
@ -268,6 +293,13 @@ context_subscribe_cb (pa_context * context, pa_subscription_event_type_t type,
|
|||
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;
|
||||
|
@ -312,34 +344,38 @@ static void
|
|||
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;
|
||||
|
@ -376,7 +412,7 @@ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
|
|||
}
|
||||
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)
|
||||
|
@ -384,7 +420,7 @@ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
|
|||
}
|
||||
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)
|
||||
|
@ -395,18 +431,38 @@ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
|
|||
pa_context_disconnect (c);
|
||||
pa_mainloop_free (m);
|
||||
|
||||
return devices;
|
||||
return data.devices;
|
||||
|
||||
failed:
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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");
|
||||
|
@ -460,29 +516,21 @@ gst_pulse_device_provider_start (GstDeviceProvider * provider)
|
|||
GST_DEBUG_OBJECT (self, "connected");
|
||||
|
||||
pa_context_subscribe (self->context,
|
||||
PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SINK, NULL, NULL);
|
||||
PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SINK |
|
||||
PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, 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_threaded_mainloop_wait (self->mainloop);
|
||||
}
|
||||
pa_operation_unref (initial_operation);
|
||||
|
||||
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_server_info (self->context,
|
||||
get_server_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_source_info_list (self->context, get_source_info_cb,
|
||||
self)))
|
||||
goto unlock_and_fail;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -495,11 +543,6 @@ unlock_and_fail:
|
|||
|
||||
mainloop_failed:
|
||||
return FALSE;
|
||||
|
||||
cancel_and_fail:
|
||||
pa_operation_cancel (initial_operation);
|
||||
pa_operation_unref (initial_operation);
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -611,7 +654,7 @@ gst_pulse_device_reconfigure_element (GstDevice * device, GstElement * element)
|
|||
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;
|
||||
|
@ -636,7 +679,7 @@ gst_pulse_device_new (guint device_index, const gchar * device_name,
|
|||
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);
|
||||
|
@ -644,6 +687,7 @@ gst_pulse_device_new (guint device_index, const gchar * device_name,
|
|||
gstdev->type = type;
|
||||
gstdev->device_index = device_index;
|
||||
gstdev->element = element;
|
||||
gstdev->is_default = is_default;
|
||||
|
||||
gst_structure_free (props);
|
||||
gst_caps_unref (caps);
|
||||
|
|
|
@ -50,6 +50,8 @@ struct _GstPulseDeviceProvider {
|
|||
|
||||
gchar *server;
|
||||
gchar *client_name;
|
||||
gchar *default_source_name;
|
||||
gchar *default_sink_name;
|
||||
|
||||
pa_threaded_mainloop *mainloop;
|
||||
pa_context *context;
|
||||
|
@ -84,6 +86,7 @@ struct _GstPulseDevice {
|
|||
GstPulseDeviceType type;
|
||||
guint device_index;
|
||||
gchar *internal_name;
|
||||
gboolean is_default;
|
||||
const gchar *element;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue