GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_WASAPI2_STATIC_CAPS));
+/**
+ * GstWasapi2SrcLoopbackMode:
+ *
+ * Loopback capture mode
+ *
+ * Since: 1.22
+ */
+typedef enum
+{
+ /**
+ * GstWasapi2SrcLoopbackMode::default:
+ *
+ * Default loopback mode
+ *
+ * Since: 1.22
+ */
+ GST_WASAPI2_SRC_LOOPBACK_DEFAULT,
+
+ /**
+ * GstWasapi2SrcLoopbackMode::include-process-tree:
+ *
+ * Captures only specified process and its child process
+ *
+ * Since: 1.22
+ */
+ GST_WASAPI2_SRC_LOOPBACK_INCLUDE_PROCESS_TREE,
+
+ /**
+ * GstWasapi2SrcLoopbackMode::exclude-process-tree:
+ *
+ * Excludes specified process and its child process
+ *
+ * Since: 1.22
+ */
+ GST_WASAPI2_SRC_LOOPBACK_EXCLUDE_PROCESS_TREE,
+} GstWasapi2SrcLoopbackMode;
+
+#define GST_TYPE_WASAPI2_SRC_LOOPBACK_MODE (gst_wasapi2_src_loopback_mode_get_type ())
+static GType
+gst_wasapi2_src_loopback_mode_get_type (void)
+{
+ static GType loopback_type = 0;
+ static const GEnumValue types[] = {
+ {GST_WASAPI2_SRC_LOOPBACK_DEFAULT, "Default", "default"},
+ {GST_WASAPI2_SRC_LOOPBACK_INCLUDE_PROCESS_TREE,
+ "Include process and its child processes",
+ "include-process-tree"},
+ {GST_WASAPI2_SRC_LOOPBACK_EXCLUDE_PROCESS_TREE,
+ "Exclude process and its child processes",
+ "exclude-process-tree"},
+ {0, NULL, NULL}
+ };
+
+ if (g_once_init_enter (&loopback_type)) {
+ GType gtype = g_enum_register_static ("GstWasapi2SrcLoopbackMode", types);
+ g_once_init_leave (&loopback_type, gtype);
+ }
+
+ return loopback_type;
+}
+
#define DEFAULT_LOW_LATENCY FALSE
#define DEFAULT_MUTE FALSE
#define DEFAULT_VOLUME 1.0
#define DEFAULT_LOOPBACK FALSE
+#define DEFAULT_LOOPBACK_MODE GST_WASAPI2_SRC_LOOPBACK_DEFAULT
enum
{
PROP_VOLUME,
PROP_DISPATCHER,
PROP_LOOPBACK,
+ PROP_LOOPBACK_MODE,
+ PROP_LOOPBACK_TARGET_PID,
};
struct _GstWasapi2Src
gdouble volume;
gpointer dispatcher;
gboolean loopback;
+ GstWasapi2SrcLoopbackMode loopback_mode;
+ guint loopback_pid;
gboolean mute_changed;
gboolean volume_changed;
GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+ if (gst_wasapi2_can_process_loopback ()) {
+ /**
+ * GstWasapi2Src:loopback-mode:
+ *
+ * Loopback mode. "target-process-id" must be specified in case of
+ * process loopback modes.
+ *
+ * This feature requires "Windows 10 build 20348"
+ *
+ * Since: 1.22
+ */
+ g_object_class_install_property (gobject_class, PROP_LOOPBACK_MODE,
+ g_param_spec_enum ("loopback-mode", "Loopback Mode",
+ "Loopback mode to use", GST_TYPE_WASAPI2_SRC_LOOPBACK_MODE,
+ DEFAULT_LOOPBACK_MODE,
+ GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_READY |
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GstWasapi2Src:loopback-target-pid:
+ *
+ * Target process id to be recorded or excluded depending on loopback mode
+ *
+ * This feature requires "Windows 10 build 20348"
+ *
+ * Since: 1.22
+ */
+ g_object_class_install_property (gobject_class, PROP_LOOPBACK_TARGET_PID,
+ g_param_spec_uint ("loopback-target-pid", "Loopback Target PID",
+ "Process ID to be recorded or excluded for process loopback mode",
+ 0, G_MAXUINT32, 0,
+ GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_READY |
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ }
+
gst_element_class_add_static_pad_template (element_class, &src_template);
gst_element_class_set_static_metadata (element_class, "Wasapi2Src",
"Source/Audio/Hardware",
GST_DEBUG_CATEGORY_INIT (gst_wasapi2_src_debug, "wasapi2src",
0, "Windows audio session API source");
+
+ if (gst_wasapi2_can_process_loopback ())
+ gst_type_mark_as_plugin_api (GST_TYPE_WASAPI2_SRC_LOOPBACK_MODE, 0);
}
static void
case PROP_LOOPBACK:
self->loopback = g_value_get_boolean (value);
break;
+ case PROP_LOOPBACK_MODE:
+ self->loopback_mode = g_value_get_enum (value);
+ break;
+ case PROP_LOOPBACK_TARGET_PID:
+ self->loopback_pid = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_LOOPBACK:
g_value_set_boolean (value, self->loopback);
break;
+ case PROP_LOOPBACK_MODE:
+ g_value_set_enum (value, self->loopback_mode);
+ break;
+ case PROP_LOOPBACK_TARGET_PID:
+ g_value_set_uint (value, self->loopback_pid);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
GstWasapi2ClientDeviceClass device_class =
GST_WASAPI2_CLIENT_DEVICE_CLASS_CAPTURE;
- if (self->loopback)
+ if (self->loopback_pid) {
+ if (self->loopback_mode == GST_WASAPI2_SRC_LOOPBACK_INCLUDE_PROCESS_TREE) {
+ device_class =
+ GST_WASAPI2_CLIENT_DEVICE_CLASS_INCLUDE_PROCESS_LOOPBACK_CAPTURE;
+ } else if (self->loopback_mode ==
+ GST_WASAPI2_SRC_LOOPBACK_EXCLUDE_PROCESS_TREE) {
+ device_class =
+ GST_WASAPI2_CLIENT_DEVICE_CLASS_EXCLUDE_PROCESS_LOOPBACK_CAPTURE;
+ }
+ } else if (self->loopback) {
device_class = GST_WASAPI2_CLIENT_DEVICE_CLASS_LOOPBACK_CAPTURE;
+ }
+
+ GST_DEBUG_OBJECT (self, "Device class %d", device_class);
name = g_strdup_printf ("%s-ringbuffer", GST_OBJECT_NAME (src));
ringbuffer =
gst_wasapi2_ring_buffer_new (device_class,
- self->low_latency, self->device_id, self->dispatcher, name);
+ self->low_latency, self->device_id, self->dispatcher, name,
+ self->loopback_pid);
g_free (name);
return ringbuffer;