mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 16:08:51 +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,
|
static GstDevice *gst_pulse_device_new (guint id,
|
||||||
const gchar * device_name, GstCaps * caps, const gchar * internal_name,
|
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,
|
G_DEFINE_TYPE (GstPulseDeviceProvider, gst_pulse_device_provider,
|
||||||
GST_TYPE_DEVICE_PROVIDER);
|
GST_TYPE_DEVICE_PROVIDER);
|
||||||
|
@ -65,6 +65,12 @@ enum
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GList *devices;
|
||||||
|
GstPulseDeviceProvider *self;
|
||||||
|
} ListDevicesData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_pulse_device_provider_class_init (GstPulseDeviceProviderClass * klass)
|
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->client_name);
|
||||||
g_free (self->server);
|
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);
|
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 *
|
static GstDevice *
|
||||||
new_source (const pa_source_info * info)
|
new_source (GstPulseDeviceProvider * self, const pa_source_info * info)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstStructure *props;
|
GstStructure *props;
|
||||||
|
@ -200,11 +208,12 @@ new_source (const pa_source_info * info)
|
||||||
props = gst_pulse_make_structure (info->proplist);
|
props = gst_pulse_make_structure (info->proplist);
|
||||||
|
|
||||||
return gst_pulse_device_new (info->index, info->description,
|
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 *
|
static GstDevice *
|
||||||
new_sink (const pa_sink_info * info)
|
new_sink (GstPulseDeviceProvider * self, const pa_sink_info * info)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstStructure *props;
|
GstStructure *props;
|
||||||
|
@ -218,7 +227,8 @@ new_sink (const pa_sink_info * info)
|
||||||
props = gst_pulse_make_structure (info->proplist);
|
props = gst_pulse_make_structure (info->proplist);
|
||||||
|
|
||||||
return gst_pulse_device_new (info->index, info->description,
|
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
|
static void
|
||||||
|
@ -233,12 +243,27 @@ get_source_info_cb (pa_context * context,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = new_source (info);
|
dev = new_source (self, info);
|
||||||
|
|
||||||
if (dev)
|
if (dev)
|
||||||
gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), 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
|
static void
|
||||||
get_sink_info_cb (pa_context * context,
|
get_sink_info_cb (pa_context * context,
|
||||||
const pa_sink_info * info, int eol, void *userdata)
|
const pa_sink_info * info, int eol, void *userdata)
|
||||||
|
@ -251,7 +276,7 @@ get_sink_info_cb (pa_context * context,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = new_sink (info);
|
dev = new_sink (self, info);
|
||||||
|
|
||||||
if (dev)
|
if (dev)
|
||||||
gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), 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 =
|
pa_subscription_event_type_t event_type =
|
||||||
type & PA_SUBSCRIPTION_EVENT_TYPE_MASK;
|
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 &&
|
if (facility != PA_SUBSCRIPTION_EVENT_SOURCE &&
|
||||||
facility != PA_SUBSCRIPTION_EVENT_SINK)
|
facility != PA_SUBSCRIPTION_EVENT_SINK)
|
||||||
return;
|
return;
|
||||||
|
@ -312,34 +344,38 @@ static void
|
||||||
get_source_info_list_cb (pa_context * context, const pa_source_info * info,
|
get_source_info_list_cb (pa_context * context, const pa_source_info * info,
|
||||||
int eol, void *userdata)
|
int eol, void *userdata)
|
||||||
{
|
{
|
||||||
GList **devices = userdata;
|
ListDevicesData *data = userdata;
|
||||||
|
|
||||||
if (eol)
|
if (eol)
|
||||||
return;
|
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
|
static void
|
||||||
get_sink_info_list_cb (pa_context * context, const pa_sink_info * info,
|
get_sink_info_list_cb (pa_context * context, const pa_sink_info * info,
|
||||||
int eol, void *userdata)
|
int eol, void *userdata)
|
||||||
{
|
{
|
||||||
GList **devices = userdata;
|
ListDevicesData *data = userdata;
|
||||||
|
|
||||||
if (eol)
|
if (eol)
|
||||||
return;
|
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 *
|
static GList *
|
||||||
gst_pulse_device_provider_probe (GstDeviceProvider * provider)
|
gst_pulse_device_provider_probe (GstDeviceProvider * provider)
|
||||||
{
|
{
|
||||||
GstPulseDeviceProvider *self = GST_PULSE_DEVICE_PROVIDER (provider);
|
GstPulseDeviceProvider *self = GST_PULSE_DEVICE_PROVIDER (provider);
|
||||||
GList *devices = NULL;
|
|
||||||
pa_mainloop *m = NULL;
|
pa_mainloop *m = NULL;
|
||||||
pa_context *c = NULL;
|
pa_context *c = NULL;
|
||||||
pa_operation *o;
|
pa_operation *o;
|
||||||
|
ListDevicesData data = { NULL, self };
|
||||||
|
|
||||||
if (!(m = pa_mainloop_new ()))
|
if (!(m = pa_mainloop_new ()))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -376,7 +412,7 @@ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
|
||||||
}
|
}
|
||||||
GST_DEBUG_OBJECT (self, "connected");
|
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 &&
|
while (pa_operation_get_state (o) == PA_OPERATION_RUNNING &&
|
||||||
pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
|
pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
|
||||||
if (pa_mainloop_iterate (m, TRUE, NULL) < 0)
|
if (pa_mainloop_iterate (m, TRUE, NULL) < 0)
|
||||||
|
@ -384,7 +420,7 @@ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
|
||||||
}
|
}
|
||||||
pa_operation_unref (o);
|
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 &&
|
while (pa_operation_get_state (o) == PA_OPERATION_RUNNING &&
|
||||||
pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
|
pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
|
||||||
if (pa_mainloop_iterate (m, TRUE, NULL) < 0)
|
if (pa_mainloop_iterate (m, TRUE, NULL) < 0)
|
||||||
|
@ -395,18 +431,38 @@ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
|
||||||
pa_context_disconnect (c);
|
pa_context_disconnect (c);
|
||||||
pa_mainloop_free (m);
|
pa_mainloop_free (m);
|
||||||
|
|
||||||
return devices;
|
return data.devices;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
|
|
||||||
return NULL;
|
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
|
static gboolean
|
||||||
gst_pulse_device_provider_start (GstDeviceProvider * provider)
|
gst_pulse_device_provider_start (GstDeviceProvider * provider)
|
||||||
{
|
{
|
||||||
GstPulseDeviceProvider *self = GST_PULSE_DEVICE_PROVIDER (provider);
|
GstPulseDeviceProvider *self = GST_PULSE_DEVICE_PROVIDER (provider);
|
||||||
pa_operation *initial_operation;
|
|
||||||
|
|
||||||
if (!(self->mainloop = pa_threaded_mainloop_new ())) {
|
if (!(self->mainloop = pa_threaded_mainloop_new ())) {
|
||||||
GST_ERROR_OBJECT (self, "Could not create pulseaudio mainloop");
|
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");
|
GST_DEBUG_OBJECT (self, "connected");
|
||||||
|
|
||||||
pa_context_subscribe (self->context,
|
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,
|
if (!run_pulse_operation (self, pa_context_get_server_info (self->context,
|
||||||
get_source_info_cb, self);
|
get_server_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)
|
|
||||||
goto unlock_and_fail;
|
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);
|
if (!run_pulse_operation (self,
|
||||||
}
|
pa_context_get_source_info_list (self->context, get_source_info_cb,
|
||||||
pa_operation_unref (initial_operation);
|
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);
|
pa_threaded_mainloop_unlock (self->mainloop);
|
||||||
|
|
||||||
|
@ -495,11 +543,6 @@ unlock_and_fail:
|
||||||
|
|
||||||
mainloop_failed:
|
mainloop_failed:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
cancel_and_fail:
|
|
||||||
pa_operation_cancel (initial_operation);
|
|
||||||
pa_operation_unref (initial_operation);
|
|
||||||
goto unlock_and_fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -611,7 +654,7 @@ gst_pulse_device_reconfigure_element (GstDevice * device, GstElement * element)
|
||||||
static GstDevice *
|
static GstDevice *
|
||||||
gst_pulse_device_new (guint device_index, const gchar * device_name,
|
gst_pulse_device_new (guint device_index, const gchar * device_name,
|
||||||
GstCaps * caps, const gchar * internal_name, GstPulseDeviceType type,
|
GstCaps * caps, const gchar * internal_name, GstPulseDeviceType type,
|
||||||
GstStructure * props)
|
GstStructure * props, gboolean is_default)
|
||||||
{
|
{
|
||||||
GstPulseDevice *gstdev;
|
GstPulseDevice *gstdev;
|
||||||
const gchar *element = NULL;
|
const gchar *element = NULL;
|
||||||
|
@ -636,7 +679,7 @@ gst_pulse_device_new (guint device_index, const gchar * device_name,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_structure_set (props, "is-default", G_TYPE_BOOLEAN, is_default, NULL);
|
||||||
gstdev = g_object_new (GST_TYPE_PULSE_DEVICE,
|
gstdev = g_object_new (GST_TYPE_PULSE_DEVICE,
|
||||||
"display-name", device_name, "caps", caps, "device-class", klass,
|
"display-name", device_name, "caps", caps, "device-class", klass,
|
||||||
"internal-name", internal_name, "properties", props, NULL);
|
"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->type = type;
|
||||||
gstdev->device_index = device_index;
|
gstdev->device_index = device_index;
|
||||||
gstdev->element = element;
|
gstdev->element = element;
|
||||||
|
gstdev->is_default = is_default;
|
||||||
|
|
||||||
gst_structure_free (props);
|
gst_structure_free (props);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
|
|
@ -50,6 +50,8 @@ struct _GstPulseDeviceProvider {
|
||||||
|
|
||||||
gchar *server;
|
gchar *server;
|
||||||
gchar *client_name;
|
gchar *client_name;
|
||||||
|
gchar *default_source_name;
|
||||||
|
gchar *default_sink_name;
|
||||||
|
|
||||||
pa_threaded_mainloop *mainloop;
|
pa_threaded_mainloop *mainloop;
|
||||||
pa_context *context;
|
pa_context *context;
|
||||||
|
@ -84,6 +86,7 @@ struct _GstPulseDevice {
|
||||||
GstPulseDeviceType type;
|
GstPulseDeviceType type;
|
||||||
guint device_index;
|
guint device_index;
|
||||||
gchar *internal_name;
|
gchar *internal_name;
|
||||||
|
gboolean is_default;
|
||||||
const gchar *element;
|
const gchar *element;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue