Add the PrivacyNodeInfo object as pw_proxy data
parent
c60a8e9836
commit
49caa4bf31
|
@ -30,7 +30,7 @@ class PipewireBackend {
|
||||||
|
|
||||||
sigc::signal<void> privacy_nodes_changed_signal_event;
|
sigc::signal<void> privacy_nodes_changed_signal_event;
|
||||||
|
|
||||||
std::unordered_map<uint32_t, PrivacyNodeInfo> privacy_nodes;
|
std::unordered_map<uint32_t, PrivacyNodeInfo*> privacy_nodes;
|
||||||
|
|
||||||
static std::shared_ptr<PipewireBackend> getInstance();
|
static std::shared_ptr<PipewireBackend> getInstance();
|
||||||
|
|
||||||
|
|
|
@ -32,17 +32,8 @@ class PrivacyNodeInfo {
|
||||||
struct spa_hook object_listener;
|
struct spa_hook object_listener;
|
||||||
struct spa_hook proxy_listener;
|
struct spa_hook proxy_listener;
|
||||||
|
|
||||||
bool changed = false;
|
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
PrivacyNodeInfo(uint32_t id_, void *data_) : id(id_), data(data_) {}
|
|
||||||
|
|
||||||
~PrivacyNodeInfo() {
|
|
||||||
spa_hook_remove(&object_listener);
|
|
||||||
spa_hook_remove(&proxy_listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_name() {
|
std::string get_name() {
|
||||||
const std::vector<std::string *> names{&application_name, &node_name};
|
const std::vector<std::string *> names{&application_name, &node_name};
|
||||||
std::string name = "Unknown Application";
|
std::string name = "Unknown Application";
|
||||||
|
@ -59,7 +50,7 @@ class PrivacyNodeInfo {
|
||||||
std::string get_icon_name() {
|
std::string get_icon_name() {
|
||||||
const std::vector<std::string *> names{&application_icon_name, &pipewire_access_portal_app_id,
|
const std::vector<std::string *> names{&application_icon_name, &pipewire_access_portal_app_id,
|
||||||
&application_name, &node_name};
|
&application_name, &node_name};
|
||||||
std::string name = "application-x-executable-symbolic";
|
const std::string name = "application-x-executable-symbolic";
|
||||||
for (auto &name_ : names) {
|
for (auto &name_ : names) {
|
||||||
if (name_ != nullptr && name_->length() > 0 && DefaultGtkIconThemeWrapper::has_icon(*name_)) {
|
if (name_ != nullptr && name_->length() > 0 && DefaultGtkIconThemeWrapper::has_icon(*name_)) {
|
||||||
return *name_;
|
return *name_;
|
||||||
|
|
|
@ -78,17 +78,17 @@ void Privacy::onPrivacyNodesChanged() {
|
||||||
nodes_screenshare.clear();
|
nodes_screenshare.clear();
|
||||||
|
|
||||||
for (auto& node : backend->privacy_nodes) {
|
for (auto& node : backend->privacy_nodes) {
|
||||||
switch (node.second.state) {
|
switch (node.second->state) {
|
||||||
case PW_NODE_STATE_RUNNING:
|
case PW_NODE_STATE_RUNNING:
|
||||||
switch (node.second.type) {
|
switch (node.second->type) {
|
||||||
case PRIVACY_NODE_TYPE_VIDEO_INPUT:
|
case PRIVACY_NODE_TYPE_VIDEO_INPUT:
|
||||||
nodes_screenshare.push_back(&node.second);
|
nodes_screenshare.push_back(node.second);
|
||||||
break;
|
break;
|
||||||
case PRIVACY_NODE_TYPE_AUDIO_INPUT:
|
case PRIVACY_NODE_TYPE_AUDIO_INPUT:
|
||||||
nodes_audio_in.push_back(&node.second);
|
nodes_audio_in.push_back(node.second);
|
||||||
break;
|
break;
|
||||||
case PRIVACY_NODE_TYPE_AUDIO_OUTPUT:
|
case PRIVACY_NODE_TYPE_AUDIO_OUTPUT:
|
||||||
nodes_audio_out.push_back(&node.second);
|
nodes_audio_out.push_back(node.second);
|
||||||
break;
|
break;
|
||||||
case PRIVACY_NODE_TYPE_NONE:
|
case PRIVACY_NODE_TYPE_NONE:
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
namespace waybar::util::PipewireBackend {
|
namespace waybar::util::PipewireBackend {
|
||||||
|
|
||||||
// TODO: Refresh on suspend wake
|
|
||||||
static void get_node_info(void *data_, const struct pw_node_info *info) {
|
static void get_node_info(void *data_, const struct pw_node_info *info) {
|
||||||
PrivacyNodeInfo *p_node_info = static_cast<PrivacyNodeInfo *>(data_);
|
PrivacyNodeInfo *p_node_info = static_cast<PrivacyNodeInfo *>(data_);
|
||||||
PipewireBackend *backend = (PipewireBackend *)p_node_info->data;
|
PipewireBackend *backend = (PipewireBackend *)p_node_info->data;
|
||||||
|
@ -15,15 +14,6 @@ static void get_node_info(void *data_, const struct pw_node_info *info) {
|
||||||
spa_dict_for_each(item, info->props) {
|
spa_dict_for_each(item, info->props) {
|
||||||
if (strcmp(item->key, PW_KEY_CLIENT_ID) == 0) {
|
if (strcmp(item->key, PW_KEY_CLIENT_ID) == 0) {
|
||||||
p_node_info->client_id = strtoul(item->value, NULL, 10);
|
p_node_info->client_id = strtoul(item->value, NULL, 10);
|
||||||
} else if (strcmp(item->key, PW_KEY_MEDIA_CLASS) == 0) {
|
|
||||||
p_node_info->media_class = item->value;
|
|
||||||
if (strcmp(p_node_info->media_class.c_str(), "Stream/Input/Video") == 0) {
|
|
||||||
p_node_info->type = PRIVACY_NODE_TYPE_VIDEO_INPUT;
|
|
||||||
} else if (strcmp(p_node_info->media_class.c_str(), "Stream/Input/Audio") == 0) {
|
|
||||||
p_node_info->type = PRIVACY_NODE_TYPE_AUDIO_INPUT;
|
|
||||||
} else if (strcmp(p_node_info->media_class.c_str(), "Stream/Output/Audio") == 0) {
|
|
||||||
p_node_info->type = PRIVACY_NODE_TYPE_AUDIO_OUTPUT;
|
|
||||||
}
|
|
||||||
} else if (strcmp(item->key, PW_KEY_MEDIA_NAME) == 0) {
|
} else if (strcmp(item->key, PW_KEY_MEDIA_NAME) == 0) {
|
||||||
p_node_info->media_name = item->value;
|
p_node_info->media_name = item->value;
|
||||||
} else if (strcmp(item->key, PW_KEY_NODE_NAME) == 0) {
|
} else if (strcmp(item->key, PW_KEY_NODE_NAME) == 0) {
|
||||||
|
@ -37,22 +27,7 @@ static void get_node_info(void *data_, const struct pw_node_info *info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_node_info->type != PRIVACY_NODE_TYPE_NONE) {
|
|
||||||
backend->mutex_.lock();
|
|
||||||
p_node_info->changed = true;
|
|
||||||
backend->privacy_nodes.insert_or_assign(info->id, *p_node_info);
|
|
||||||
backend->mutex_.unlock();
|
|
||||||
|
|
||||||
backend->privacy_nodes_changed_signal_event.emit();
|
backend->privacy_nodes_changed_signal_event.emit();
|
||||||
} else {
|
|
||||||
if (p_node_info->changed) {
|
|
||||||
backend->mutex_.lock();
|
|
||||||
backend->privacy_nodes.erase(info->id);
|
|
||||||
backend->mutex_.unlock();
|
|
||||||
|
|
||||||
backend->privacy_nodes_changed_signal_event.emit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pw_node_events node_events = {
|
static const struct pw_node_events node_events = {
|
||||||
|
@ -76,27 +51,45 @@ static void registry_event_global(void *_data, uint32_t id, uint32_t permissions
|
||||||
uint32_t version, const struct spa_dict *props) {
|
uint32_t version, const struct spa_dict *props) {
|
||||||
if (!props || strcmp(type, PW_TYPE_INTERFACE_Node) != 0) return;
|
if (!props || strcmp(type, PW_TYPE_INTERFACE_Node) != 0) return;
|
||||||
|
|
||||||
PipewireBackend *backend = static_cast<PipewireBackend *>(_data);
|
const char *lookup_str = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS);
|
||||||
struct pw_proxy *proxy = (pw_proxy *)pw_registry_bind(backend->registry, id, type, version, 0);
|
if (!lookup_str) return;
|
||||||
if (proxy) {
|
std::string media_class = lookup_str;
|
||||||
PrivacyNodeInfo *p_node_info;
|
enum PrivacyNodeType media_type = PRIVACY_NODE_TYPE_NONE;
|
||||||
backend->mutex_.lock();
|
if (media_class == "Stream/Input/Video") {
|
||||||
if (backend->privacy_nodes.contains(id)) {
|
media_type = PRIVACY_NODE_TYPE_VIDEO_INPUT;
|
||||||
p_node_info = &backend->privacy_nodes.at(id);
|
} else if (media_class == "Stream/Input/Audio") {
|
||||||
|
media_type = PRIVACY_NODE_TYPE_AUDIO_INPUT;
|
||||||
|
} else if (media_class == "Stream/Output/Audio") {
|
||||||
|
media_type = PRIVACY_NODE_TYPE_AUDIO_OUTPUT;
|
||||||
} else {
|
} else {
|
||||||
p_node_info = new PrivacyNodeInfo(id, backend);
|
return;
|
||||||
}
|
}
|
||||||
backend->mutex_.unlock();
|
|
||||||
|
PipewireBackend *backend = static_cast<PipewireBackend *>(_data);
|
||||||
|
struct pw_proxy *proxy =
|
||||||
|
(pw_proxy *)pw_registry_bind(backend->registry, id, type, version, sizeof(PrivacyNodeInfo));
|
||||||
|
|
||||||
|
if (!proxy) return;
|
||||||
|
|
||||||
|
PrivacyNodeInfo *p_node_info = (PrivacyNodeInfo *)pw_proxy_get_user_data(proxy);
|
||||||
|
p_node_info->id = id;
|
||||||
|
p_node_info->data = backend;
|
||||||
|
p_node_info->type = media_type;
|
||||||
|
p_node_info->media_class = media_class;
|
||||||
|
|
||||||
pw_proxy_add_listener(proxy, &p_node_info->proxy_listener, &proxy_events, p_node_info);
|
pw_proxy_add_listener(proxy, &p_node_info->proxy_listener, &proxy_events, p_node_info);
|
||||||
|
|
||||||
pw_proxy_add_object_listener(proxy, &p_node_info->object_listener, &node_events, p_node_info);
|
pw_proxy_add_object_listener(proxy, &p_node_info->object_listener, &node_events, p_node_info);
|
||||||
}
|
|
||||||
|
backend->privacy_nodes.insert_or_assign(id, p_node_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registry_event_global_remove(void *_data, uint32_t id) {
|
static void registry_event_global_remove(void *_data, uint32_t id) {
|
||||||
auto backend = static_cast<PipewireBackend *>(_data);
|
auto backend = static_cast<PipewireBackend *>(_data);
|
||||||
|
|
||||||
backend->mutex_.lock();
|
backend->mutex_.lock();
|
||||||
if (backend->privacy_nodes.contains(id)) {
|
auto iter = backend->privacy_nodes.find(id);
|
||||||
|
if(iter != backend->privacy_nodes.end()) {
|
||||||
backend->privacy_nodes.erase(id);
|
backend->privacy_nodes.erase(id);
|
||||||
}
|
}
|
||||||
backend->mutex_.unlock();
|
backend->mutex_.unlock();
|
||||||
|
|
Loading…
Reference in New Issue