[WASAPI] set stream audio category
[xbmc.git] / xbmc / cores / AudioEngine / Sinks / pipewire / PipewireNode.cpp
blobbbb4cd9c31746398d23737088411419988672244
1 /*
2 * Copyright (C) 2010-2021 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "PipewireNode.h"
11 #include "PipewireContext.h"
12 #include "PipewireCore.h"
13 #include "PipewireRegistry.h"
14 #include "PipewireThreadLoop.h"
15 #include "utils/StringUtils.h"
16 #include "utils/log.h"
18 #include <spa/param/format.h>
19 #include <spa/pod/iter.h>
21 using namespace KODI;
22 using namespace PIPEWIRE;
24 CPipewireNode::CPipewireNode(CPipewireRegistry& registry, uint32_t id, const char* type)
25 : CPipewireProxy(registry, id, type, PW_VERSION_NODE), m_nodeEvents(CreateNodeEvents())
27 pw_proxy_add_object_listener(m_proxy.get(), &m_objectListener, &m_nodeEvents, this);
30 CPipewireNode::~CPipewireNode()
32 spa_hook_remove(&m_objectListener);
35 void CPipewireNode::EnumerateFormats()
37 if (!m_info)
38 return;
40 for (uint32_t param = 0; param < m_info->n_params; param++)
42 if (m_info->params[param].id == SPA_PARAM_EnumFormat)
43 pw_node_enum_params(m_proxy.get(), 0, m_info->params[param].id, 0, 0, NULL);
47 void CPipewireNode::Info(void* userdata, const struct pw_node_info* info)
49 auto& node = *reinterpret_cast<CPipewireNode*>(userdata);
51 if (node.m_info)
53 CLog::Log(LOGDEBUG, "CPipewireNode::{} - node {} changed", __FUNCTION__, info->id);
54 pw_node_info* m_info = node.m_info.get();
55 m_info = pw_node_info_update(m_info, info);
57 else
59 node.m_info.reset(pw_node_info_update(node.m_info.get(), info));
63 template<typename T>
64 static T Parse(uint32_t type, void* body, uint32_t size)
66 switch (type)
68 case SPA_TYPE_Id:
69 case SPA_TYPE_Int:
70 return *reinterpret_cast<T*>(body);
72 default:
73 throw std::runtime_error(StringUtils::Format("unhandled type: {}", type));
77 template<typename T>
78 static std::set<T> ParseArray(uint32_t type, void* body, uint32_t size)
80 switch (type)
82 case SPA_TYPE_Id:
83 case SPA_TYPE_Int:
85 std::set<T> values;
86 values.emplace(Parse<T>(type, body, size));
88 return values;
90 case SPA_TYPE_Array:
92 auto array = reinterpret_cast<spa_pod_array_body*>(body);
93 void* p;
94 std::set<T> values;
95 SPA_POD_ARRAY_BODY_FOREACH(array, size, p)
96 values.emplace(Parse<T>(array->child.type, p, array->child.size));
98 return values;
100 case SPA_TYPE_Choice:
102 auto choice = reinterpret_cast<spa_pod_choice_body*>(body);
103 void* p;
104 std::set<T> values;
105 SPA_POD_CHOICE_BODY_FOREACH(choice, size, p)
106 values.emplace(Parse<T>(choice->child.type, p, choice->child.size));
108 return values;
110 default:
111 throw std::runtime_error(StringUtils::Format("unhandled array: {}", type));
115 void CPipewireNode::Parse(uint32_t type, void* body, uint32_t size)
117 switch (type)
119 case SPA_TYPE_Object:
121 auto object = reinterpret_cast<spa_pod_object_body*>(body);
123 switch (object->type)
125 case SPA_TYPE_OBJECT_Format:
127 spa_pod_prop* prop;
128 SPA_POD_OBJECT_BODY_FOREACH(object, size, prop)
130 spa_format format = static_cast<spa_format>(prop->key);
132 switch (format)
134 case SPA_FORMAT_AUDIO_format:
136 m_formats = ParseArray<spa_audio_format>(
137 prop->value.type, SPA_POD_CONTENTS(spa_pod_prop, prop), prop->value.size);
138 break;
140 case SPA_FORMAT_AUDIO_rate:
142 m_rates = ParseArray<uint32_t>(
143 prop->value.type, SPA_POD_CONTENTS(spa_pod_prop, prop), prop->value.size);
144 break;
146 case SPA_FORMAT_AUDIO_position:
148 m_channels = ParseArray<spa_audio_channel>(
149 prop->value.type, SPA_POD_CONTENTS(spa_pod_prop, prop), prop->value.size);
150 break;
152 case SPA_FORMAT_AUDIO_iec958Codec:
154 m_iec958Codecs = ParseArray<spa_audio_iec958_codec>(
155 prop->value.type, SPA_POD_CONTENTS(spa_pod_prop, prop), prop->value.size);
156 break;
158 default:
159 break;
163 break;
165 default:
166 return;
169 break;
171 default:
172 return;
176 void CPipewireNode::Param(void* userdata,
177 int seq,
178 uint32_t id,
179 uint32_t index,
180 uint32_t next,
181 const struct spa_pod* param)
183 auto& node = *reinterpret_cast<CPipewireNode*>(userdata);
184 auto& loop = node.GetRegistry().GetCore().GetContext().GetThreadLoop();
186 node.Parse(SPA_POD_TYPE(param), SPA_POD_BODY(param), SPA_POD_BODY_SIZE(param));
188 loop.Signal(false);
191 pw_node_events CPipewireNode::CreateNodeEvents()
193 pw_node_events nodeEvents = {};
194 nodeEvents.version = PW_VERSION_NODE_EVENTS;
195 nodeEvents.info = Info;
196 nodeEvents.param = Param;
198 return nodeEvents;