aboutsummaryrefslogtreecommitdiffstats
path: root/alc/backends/pipewire.cpp
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2021-11-14 05:58:39 -0800
committerChris Robinson <[email protected]>2021-11-14 05:58:39 -0800
commitcf85ffd22fceeb4221a96b310f574f29a4b404ea (patch)
tree9ff564ed4872447d5afce2a0193241d862877a29 /alc/backends/pipewire.cpp
parent3b9c831c300e8191539eae69995caf023f8fff7a (diff)
Support "enum" choices for sample rates with PipeWire
Diffstat (limited to 'alc/backends/pipewire.cpp')
-rw-r--r--alc/backends/pipewire.cpp56
1 files changed, 48 insertions, 8 deletions
diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp
index 0e99fdc4..68e6f527 100644
--- a/alc/backends/pipewire.cpp
+++ b/alc/backends/pipewire.cpp
@@ -579,6 +579,23 @@ uint32_t get_param_range(const spa_pod *value, const al::span<Pod_t<T>,3> vals)
return 0;
}
+template<uint32_t T>
+std::vector<Pod_t<T>> get_param_enum(const spa_pod *value)
+{
+ std::vector<Pod_t<T>> vals;
+
+ uint32_t nvals{}, choice{};
+ value = spa_pod_get_values(value, &nvals, &choice);
+
+ if(get_pod_type(value) == T && nvals > 0 && choice == SPA_CHOICE_Enum)
+ {
+ vals.resize(nvals);
+ std::copy_n(get_pod_body<Pod_t<T>>(value), vals.size(), vals.begin());
+ }
+
+ return vals;
+}
+
template<uint32_t T, size_t N>
uint32_t get_param_array(const spa_pod *value, const al::span<Pod_t<T>,N> vals)
{
@@ -596,20 +613,43 @@ al::optional<Pod_t<T>> get_param(const spa_pod *value)
void parse_srate(DeviceNode *node, const spa_pod *value)
{
- /* TODO: Can this be anything else? An "enum" choice? Floats? Or will the
- * sample rate always be a range choice between ints?
+ /* TODO: Can this be anything else? Floats? Will the sample rate always be
+ * a range or enum choice of ints?
*/
if(get_pod_type(value) == SPA_TYPE_Choice)
{
int32_t srate[3]{};
- if(get_param_range<SPA_TYPE_Int>(value, al::span<int32_t,3>{srate}) < 1)
+ if(get_param_range<SPA_TYPE_Int>(value, al::span<int32_t,3>{srate}) > 0)
+ {
+ /* [0] is the default, [1] is the min, and [2] is the max. */
+ TRACE("Device ID %u sample rate: %d (range: %d -> %d)\n", node->mId, srate[0], srate[1],
+ srate[2]);
+ srate[0] = clampi(srate[0], MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
+ node->mSampleRate = static_cast<uint>(srate[0]);
return;
+ }
- /* [0] is the default, [1] is the min, and [2] is the max. */
- TRACE("Device ID %u sample rate: %d (range: %d -> %d)\n", node->mId, srate[0], srate[1],
- srate[2]);
- srate[0] = clampi(srate[0], MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
- node->mSampleRate = static_cast<uint>(srate[0]);
+ auto srates = get_param_enum<SPA_TYPE_Int>(value);
+ if(!srates.empty())
+ {
+ /* [0] is the default, [1...size()-1] are available selections. */
+ std::string others{(srates.size() > 1) ? std::to_string(srates[1]) : std::string{}};
+ for(size_t i{2};i < srates.size();++i)
+ {
+ others += ", ";
+ others += std::to_string(srates[i]);
+ }
+ TRACE("Device ID %u sample rate: %d (%s)\n", node->mId, srates[0], others.c_str());
+ for(const auto &rate : srates)
+ {
+ if(rate >= MIN_OUTPUT_RATE && rate <= MAX_OUTPUT_RATE)
+ {
+ node->mSampleRate = static_cast<uint>(rate);
+ break;
+ }
+ }
+ return;
+ }
}
}