Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pipewire/wireplumber
  • julian/wireplumber
  • gkiagia/wireplumber
  • hadess/wireplumber
  • NorwayFun/wireplumber
  • mkoch-aditg/wireplumber
  • fvogt/wireplumber
  • raghu447/wireplumber
  • dvzrv/wireplumber
  • a-wai/wireplumber
  • jarkko/wireplumber
  • Be/wireplumber
  • hemish/wireplumber
  • dreamcat4/wireplumber
  • fdanis/wireplumber
  • igrekster/wireplumber
  • wtaymans/wireplumber
  • arun/wireplumber
  • darix/wireplumber
  • dsseng/wireplumber
  • pinkflames/wireplumber
  • whot/wireplumber
  • marv/wireplumber
  • SanchayanMaity/wireplumber
  • jakobrs/wireplumber
  • pvir/wireplumber
  • bdaase/wireplumber
  • thesamesam/wireplumber
  • ashoks/wireplumber
  • N4RR4D0R/wireplumber
  • freddy1984govoni/wireplumber
  • saivert/wireplumber
  • hritchie4510/wireplumber
  • Zaiken64/wireplumber
  • iczero/wireplumber
  • tamborim/wireplumber
  • pobrn/wireplumber
  • sevz/wireplumber
  • tintou/wireplumber
  • jij/wireplumber
  • mazunki/wireplumber
  • antlarr/wireplumber
  • daissi/wireplumber
  • etircopyh/wireplumber
  • gobonja/wireplumber
  • PureTryOut/wireplumber
  • ROGUE/wireplumber
  • alosarjos/wireplumber
  • Joker234/wireplumber
  • msizanoen1/wireplumber
  • kkovaacs/wireplumber
  • Kritzefitz/wireplumber
  • brandsimon/wireplumber
  • hltack/wireplumber
  • piotrdrag/wireplumber
  • mol/wireplumber
  • EncryptedCicada/wireplumber
  • danialbehzadi/wireplumber
  • ajonsson/wireplumber
  • TestingPlant/wireplumber
  • dv1/wireplumber
  • jordimas/wireplumber
  • urbalazs/wireplumber
  • antonio.ilersich/wireplumber
  • ryuukyu/wireplumber
  • prescott66/wireplumber
  • Supreeeme/wireplumber
  • rmader/wireplumber
  • tsabsch/wireplumber
  • yurchor/wireplumber
  • openglfreak/wireplumber
  • vic/wireplumber
  • matoro1/wireplumber
  • david.turner/wireplumber
  • Duncaen/wireplumber
  • stefanu21/wireplumber
  • brocellous/wireplumber
  • sergio-costas/wireplumber
  • mhoran/wireplumber
  • alshopov/wireplumber
  • chadmed/wireplumber
  • yaron/wireplumber
  • yrlf/wireplumber
  • StacyHarper/wireplumber
  • robberos/wireplumber
  • souravdas142/wireplumber
  • stefanu/wireplumber
  • staindk/wireplumber
  • WhyNotHugo/wireplumber
  • tomhughes/wireplumber
  • tytan652/wireplumber
  • rafaelff/wireplumber
  • flywater/wireplumber
  • andika/wireplumber
  • quenty_occitania/wireplumber
  • PJungkamp/wireplumber
  • andrew-sayers/wireplumber
97 results
Show changes
Commits on Source (3)
......@@ -10,16 +10,25 @@
#include <pipewire/keys.h>
#include "module-default-nodes/common.h"
typedef struct _WpDefaultNode WpDefaultNode;
struct _WpDefaultNode
{
gchar *value;
gchar *config_value;
};
struct _WpDefaultNodesApi
{
WpPlugin parent;
gchar *defaults[N_DEFAULT_NODES];
WpDefaultNode defaults[N_DEFAULT_NODES];
WpObjectManager *om;
};
enum {
ACTION_GET_DEFAULT_NODE,
ACTION_GET_DEFAULT_CONFIGURED_NODE_NAME,
ACTION_SET_DEFAULT_CONFIGURED_NODE_NAME,
SIGNAL_CHANGED,
N_SIGNALS
};
......@@ -63,30 +72,32 @@ on_metadata_changed (WpMetadata *m, guint32 subject,
const gchar *key, const gchar *type, const gchar *value, gpointer d)
{
WpDefaultNodesApi * self = WP_DEFAULT_NODES_API (d);
gint node_t = -1;
gchar name[1024];
if (subject == 0) {
for (gint i = 0; i < N_DEFAULT_NODES; i++) {
if (!g_strcmp0 (key, DEFAULT_KEY[i])) {
node_t = i;
break;
}
}
}
if (subject != 0)
return;
if (node_t != -1) {
g_clear_pointer (&self->defaults[node_t], g_free);
for (gint i = 0; i < N_DEFAULT_NODES; i++) {
gchar name[1024];
if (!g_strcmp0 (key, DEFAULT_KEY[i])) {
g_clear_pointer (&self->defaults[i].value, g_free);
if (value && !g_strcmp0 (type, "Spa:String:JSON") &&
json_object_find (value, "name", name, sizeof(name)) == 0)
self->defaults[i].value = g_strdup (name);
if (value && !g_strcmp0 (type, "Spa:String:JSON") &&
json_object_find (value, "name", name, sizeof(name)) == 0)
{
self->defaults[node_t] = g_strdup (name);
}
wp_debug_object (m, "changed '%s' -> '%s'", key,
self->defaults[i].value);
wp_debug_object (m, "changed '%s' -> '%s'", key, self->defaults[node_t]);
schedule_changed_notification (self);
break;
} else if (!g_strcmp0 (key, DEFAULT_CONFIG_KEY[i])) {
g_clear_pointer (&self->defaults[i].config_value, g_free);
if (value && !g_strcmp0 (type, "Spa:String:JSON") &&
json_object_find (value, "name", name, sizeof(name)) == 0)
self->defaults[i].config_value = g_strdup (name);
schedule_changed_notification (self);
wp_debug_object (m, "changed '%s' -> '%s'", key,
self->defaults[i].config_value);
}
}
}
......@@ -144,8 +155,10 @@ wp_default_nodes_api_disable (WpPlugin * plugin)
{
WpDefaultNodesApi * self = WP_DEFAULT_NODES_API (plugin);
for (guint i = 0; i < N_DEFAULT_NODES; i++)
g_clear_pointer (&self->defaults[i], g_free);
for (guint i = 0; i < N_DEFAULT_NODES; i++) {
g_clear_pointer (&self->defaults[i].value, g_free);
g_clear_pointer (&self->defaults[i].config_value, g_free);
}
g_clear_object (&self->om);
}
......@@ -161,13 +174,13 @@ wp_default_nodes_api_get_default_node (WpDefaultNodesApi * self,
}
}
if (node_t != -1 && self->defaults[node_t]) {
if (node_t != -1 && self->defaults[node_t].value) {
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) val = G_VALUE_INIT;
it = wp_object_manager_new_filtered_iterator (self->om,
WP_TYPE_NODE,
WP_CONSTRAINT_TYPE_PW_PROPERTY,
PW_KEY_NODE_NAME, "=s", self->defaults[node_t],
PW_KEY_NODE_NAME, "=s", self->defaults[node_t].value,
NULL);
for (; wp_iterator_next (it, &val); g_value_unset (&val)) {
WpNode *node = g_value_get_object (&val);
......@@ -180,6 +193,42 @@ wp_default_nodes_api_get_default_node (WpDefaultNodesApi * self,
return SPA_ID_INVALID;
}
static gchar *
wp_default_nodes_api_get_default_configured_node_name (WpDefaultNodesApi * self,
const gchar * media_class)
{
for (gint i = 0; i < N_DEFAULT_NODES; i++)
if (!g_strcmp0 (media_class, NODE_TYPE_STR[i]) &&
self->defaults[i].config_value)
return g_strdup (self->defaults[i].config_value);
return NULL;
}
static gboolean
wp_default_nodes_api_set_default_configured_node_name (WpDefaultNodesApi * self,
const gchar * media_class, const gchar * name)
{
g_autoptr (WpMetadata) m = wp_object_manager_lookup (self->om,
WP_TYPE_METADATA, NULL);
if (!m)
return FALSE;
for (gint i = 0; i < N_DEFAULT_NODES; i++) {
if (!g_strcmp0 (media_class, NODE_TYPE_STR[i])) {
if (name) {
g_autofree gchar *v = g_strdup_printf ("{ \"name\": \"%s\" }", name);
wp_metadata_set (m, 0, DEFAULT_CONFIG_KEY[i], "Spa:String:JSON", v);
} else {
wp_metadata_set (m, 0, DEFAULT_CONFIG_KEY[i], NULL, NULL);
}
return TRUE;
}
}
return FALSE;
}
static void
wp_default_nodes_api_class_init (WpDefaultNodesApiClass * klass)
{
......@@ -195,6 +244,20 @@ wp_default_nodes_api_class_init (WpDefaultNodesApiClass * klass)
NULL, NULL, NULL,
G_TYPE_UINT, 1, G_TYPE_STRING);
signals[ACTION_GET_DEFAULT_CONFIGURED_NODE_NAME] = g_signal_new_class_handler (
"get-default-configured-node-name", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
(GCallback) wp_default_nodes_api_get_default_configured_node_name,
NULL, NULL, NULL,
G_TYPE_STRING, 1, G_TYPE_STRING);
signals[ACTION_SET_DEFAULT_CONFIGURED_NODE_NAME] = g_signal_new_class_handler (
"set-default-configured-node-name", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
(GCallback) wp_default_nodes_api_set_default_configured_node_name,
NULL, NULL, NULL,
G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_STRING);
signals[SIGNAL_CHANGED] = g_signal_new (
"changed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
......
......@@ -11,7 +11,6 @@
#include <pipewire/pipewire.h>
#include <pipewire/keys.h>
#define COMPILING_MODULE_DEFAULT_NODES 1
#include "module-default-nodes/common.h"
#define NAME "default-nodes"
......@@ -522,6 +521,17 @@ on_metadata_changed (WpMetadata *m, guint32 subject,
}
}
static void
on_object_added (WpObjectManager *om, WpPipewireObject *proxy, gpointer d)
{
WpDefaultNodes * self = WP_DEFAULT_NODES (d);
if (WP_IS_DEVICE (proxy)) {
g_signal_connect_object (proxy, "params-changed",
G_CALLBACK (schedule_rescan), self, G_CONNECT_SWAPPED);
}
}
static void
on_metadata_added (WpObjectManager *om, WpMetadata *metadata, gpointer d)
{
......@@ -556,6 +566,8 @@ on_metadata_added (WpObjectManager *om, WpMetadata *metadata, gpointer d)
WP_OBJECT_FEATURES_ALL);
g_signal_connect_object (self->rescan_om, "objects-changed",
G_CALLBACK (schedule_rescan), self, G_CONNECT_SWAPPED);
g_signal_connect_object (self->rescan_om, "object-added",
G_CALLBACK (on_object_added), self, 0);
wp_core_install_object_manager (core, self->rescan_om);
}
......
......@@ -29,16 +29,12 @@ static const gchar * NODE_TYPE_STR[N_DEFAULT_NODES] = {
[VIDEO_SOURCE] = "Video/Source",
};
#if COMPILING_MODULE_DEFAULT_NODES
static const gchar * DEFAULT_CONFIG_KEY[N_DEFAULT_NODES] = {
[AUDIO_SINK] = "default.configured.audio.sink",
[AUDIO_SOURCE] = "default.configured.audio.source",
[VIDEO_SOURCE] = "default.configured.video.source",
};
#endif
static int
json_object_find (const char *obj, const char *key, char *value, size_t len)
{
......
......@@ -8,9 +8,16 @@
#include <wp/wp.h>
#include <stdio.h>
#include <spa/utils/defs.h>
#include <pipewire/keys.h>
#include <pipewire/extensions/session-manager/keys.h>
static const gchar *DEFAULT_NODE_MEDIA_CLASSES[] = {
"Audio/Sink",
"Audio/Source",
"Video/Source",
};
typedef struct _WpCtl WpCtl;
struct _WpCtl
{
......@@ -47,6 +54,10 @@ static struct {
guint32 id;
gint index;
} set_profile;
struct {
guint32 id;
} clear_default;
};
} cmdline;
......@@ -343,6 +354,21 @@ status_run (WpCtl * self)
printf ("\n");
}
/* Settings */
printf ("Settings\n");
if (def_nodes_api) {
printf (TREE_INDENT_END "Default Configured Node Names:\n");
for (guint i = 0; i < G_N_ELEMENTS (DEFAULT_NODE_MEDIA_CLASSES); i++) {
const gchar *name = NULL;
g_signal_emit_by_name (def_nodes_api, "get-default-configured-node-name",
DEFAULT_NODE_MEDIA_CLASSES[i], &name);
if (name)
printf (TREE_INDENT_EMPTY " %4u. %-12s %s\n", i,
DEFAULT_NODE_MEDIA_CLASSES[i], name);
}
}
g_clear_object (&context.mixer_api);
g_main_loop_quit (self->loop);
}
......@@ -578,10 +604,6 @@ set_default_parse_positional (gint argc, gchar ** argv, GError **error)
static gboolean
set_default_prepare (WpCtl * self, GError ** error)
{
wp_object_manager_add_interest (self->om, WP_TYPE_METADATA,
WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY,
"metadata.name", "=s", "default",
NULL);
wp_object_manager_add_interest (self->om, WP_TYPE_NODE,
WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY,
"object.id", "=u", cmdline.set_default.id,
......@@ -596,17 +618,14 @@ set_default_prepare (WpCtl * self, GError ** error)
static void
set_default_run (WpCtl * self)
{
g_autoptr (WpMetadata) metadata = NULL;
g_autoptr (WpPlugin) def_nodes_api = NULL;
g_autoptr (WpProxy) proxy = NULL;
guint32 id = cmdline.set_default.id;
const gchar *media_class;
const gchar *key;
const gchar *name;
gchar buf[1024];
metadata = wp_object_manager_lookup (self->om, WP_TYPE_METADATA, NULL);
if (!metadata) {
printf ("No metadata found\n");
def_nodes_api = wp_plugin_find (self->core, "default-nodes-api");
if (!def_nodes_api) {
printf ("Default nodes API not loaded\n");
goto out;
}
......@@ -618,30 +637,30 @@ set_default_run (WpCtl * self)
media_class = wp_pipewire_object_get_property (WP_PIPEWIRE_OBJECT (proxy),
PW_KEY_MEDIA_CLASS);
if (!g_strcmp0 (media_class, "Audio/Sink"))
key = "default.configured.audio.sink";
else if (!g_strcmp0 (media_class, "Audio/Source"))
key = "default.configured.audio.source";
else if (!g_strcmp0 (media_class, "Video/Source"))
key = "default.configured.video.source";
else {
printf ("%u is not a device node (media.class = %s)\n",
id, media_class);
goto out;
}
for (guint i = 0; i < G_N_ELEMENTS (DEFAULT_NODE_MEDIA_CLASSES); i++) {
if (!g_strcmp0 (media_class, DEFAULT_NODE_MEDIA_CLASSES[i])) {
gboolean res = FALSE;
const gchar *name = wp_pipewire_object_get_property (
WP_PIPEWIRE_OBJECT (proxy), PW_KEY_NODE_NAME);
if (!name) {
printf ("node %u does not have a valid node.name\n", id);
goto out;
}
name = wp_pipewire_object_get_property (WP_PIPEWIRE_OBJECT (proxy),
PW_KEY_NODE_NAME);
if (!name) {
printf ("node %u does not have a valid node.name\n", id);
goto out;
g_signal_emit_by_name (def_nodes_api, "set-default-configured-node-name",
DEFAULT_NODE_MEDIA_CLASSES[i], name, &res);
if (!res) {
printf ("failed to set default node %u (media.class = %s)\n", id,
media_class);
goto out;
}
wp_core_sync (self->core, NULL, (GAsyncReadyCallback) async_quit, self);
return;
}
}
g_snprintf (buf, sizeof(buf), "{ \"name\": \"%s\" }", name);
wp_metadata_set (metadata, 0, key, "Spa:String:JSON", buf);
wp_core_sync (self->core, NULL, (GAsyncReadyCallback) async_quit, self);
return;
printf ("%u is not a device node (media.class = %s)\n", id, media_class);
out:
self->exit_code = 3;
......@@ -897,6 +916,80 @@ out:
g_main_loop_quit (self->loop);
}
/* clear-default */
static gboolean
clear_default_parse_positional (gint argc, gchar ** argv, GError **error)
{
cmdline.clear_default.id = SPA_ID_INVALID;
if (argc >= 3) {
long id = strtol (argv[2], NULL, 10);
if (id < 0) {
g_set_error (error, wpctl_error_domain_quark(), 0,
"'%s' is not a valid number", argv[2]);
return FALSE;
}
cmdline.clear_default.id = id;
}
return TRUE;
}
static gboolean
clear_default_prepare (WpCtl * self, GError ** error)
{
return TRUE;
}
static void
clear_default_run (WpCtl * self)
{
g_autoptr (WpPlugin) def_nodes_api = NULL;
guint32 id = cmdline.clear_default.id;
gboolean res = FALSE;
def_nodes_api = wp_plugin_find (self->core, "default-nodes-api");
if (!def_nodes_api) {
printf ("Default nodes API not loaded\n");
goto out;
}
/* clear all defaults if id was not given */
if (id == SPA_ID_INVALID) {
for (guint i = 0; i < G_N_ELEMENTS (DEFAULT_NODE_MEDIA_CLASSES); i++) {
g_signal_emit_by_name (def_nodes_api, "set-default-configured-node-name",
DEFAULT_NODE_MEDIA_CLASSES[i], NULL, &res);
if (!res) {
printf ("failed to clear default configured node (%s)\n",
DEFAULT_NODE_MEDIA_CLASSES[i]);
goto out;
}
}
} else {
if (id < G_N_ELEMENTS (DEFAULT_NODE_MEDIA_CLASSES)) {
g_signal_emit_by_name (def_nodes_api, "set-default-configured-node-name",
DEFAULT_NODE_MEDIA_CLASSES[id], NULL, &res);
if (!res) {
printf ("failed to clear default configured node (%s)\n",
DEFAULT_NODE_MEDIA_CLASSES[id]);
goto out;
}
} else {
printf ("Id %d is not a valid default node Id\n", id);
goto out;
}
}
wp_core_sync (self->core, NULL, (GAsyncReadyCallback) async_quit, self);
return;
out:
self->exit_code = 3;
g_main_loop_quit (self->loop);
}
#define N_ENTRIES 3
static const struct subcommand {
......@@ -984,6 +1077,16 @@ static const struct subcommand {
.parse_positional = set_profile_parse_positional,
.prepare = set_profile_prepare,
.run = set_profile_run,
},
{
.name = "clear-default",
.positional_args = "[ID]",
.summary = "Clears the default configured node (no ID means 'all')",
.description = NULL,
.entries = { { NULL } },
.parse_positional = clear_default_parse_positional,
.prepare = clear_default_prepare,
.run = clear_default_run,
}
};
......