mirror of
https://github.com/scorpion-26/gBar.git
synced 2024-11-24 12:12:09 +00:00
Process audio slider events asynchronously
This commit avoids piling up events if events are queued quicker, than gBar can handle, causing severe slowdowns. Instead, the requests are handled in a worker thread and excess events are discarded. Fixes: https://github.com/scorpion-26/gBar/issues/86
This commit is contained in:
parent
0f943405d3
commit
6dd1ee6783
2 changed files with 85 additions and 4 deletions
38
src/Bar.cpp
38
src/Bar.cpp
|
@ -288,14 +288,30 @@ namespace Bar
|
|||
Widget* micSlider;
|
||||
Button* audioIcon;
|
||||
Button* micIcon;
|
||||
|
||||
static AsyncAtomicContext<double> sinkAsyncContext;
|
||||
void OnChangeVolumeSink(Slider&, double value)
|
||||
{
|
||||
System::SetVolumeSink(value);
|
||||
// Process async and atomically, so the event handler isn't filled up
|
||||
ExecuteAsyncAtomically(
|
||||
sinkAsyncContext,
|
||||
[](double volume)
|
||||
{
|
||||
System::SetVolumeSink(volume);
|
||||
},
|
||||
value);
|
||||
}
|
||||
|
||||
static AsyncAtomicContext<double> sourceAsyncContext;
|
||||
void OnChangeVolumeSource(Slider&, double value)
|
||||
{
|
||||
System::SetVolumeSource(value);
|
||||
ExecuteAsyncAtomically(
|
||||
sourceAsyncContext,
|
||||
[](double volume)
|
||||
{
|
||||
System::SetVolumeSource(volume);
|
||||
},
|
||||
value);
|
||||
}
|
||||
|
||||
// For text
|
||||
|
@ -304,7 +320,14 @@ namespace Bar
|
|||
{
|
||||
audioVolume += delta;
|
||||
audioVolume = std::clamp(audioVolume, 0.0, 1.0);
|
||||
System::SetVolumeSink(audioVolume);
|
||||
// Process async and atomically, so the event handler isn't filled up
|
||||
ExecuteAsyncAtomically(
|
||||
sinkAsyncContext,
|
||||
[](double volume)
|
||||
{
|
||||
System::SetVolumeSink(volume);
|
||||
},
|
||||
audioVolume);
|
||||
}
|
||||
|
||||
double micVolume = 0;
|
||||
|
@ -312,7 +335,14 @@ namespace Bar
|
|||
{
|
||||
micVolume += delta;
|
||||
micVolume = std::clamp(micVolume, 0.0, 1.0);
|
||||
System::SetVolumeSource(micVolume);
|
||||
// Process async and atomically, so the event handler isn't filled up
|
||||
ExecuteAsyncAtomically(
|
||||
sourceAsyncContext,
|
||||
[](double volume)
|
||||
{
|
||||
System::SetVolumeSource(volume);
|
||||
},
|
||||
micVolume);
|
||||
}
|
||||
|
||||
void OnToggleSink(Button& button)
|
||||
|
|
51
src/Common.h
51
src/Common.h
|
@ -1,11 +1,15 @@
|
|||
#pragma once
|
||||
#include <atomic>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
|
@ -186,6 +190,53 @@ inline Process OpenProcess(const std::string& command)
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
struct AsyncAtomicContext
|
||||
{
|
||||
std::atomic<bool> running = false;
|
||||
std::mutex queueLock;
|
||||
std::optional<Data> queue;
|
||||
};
|
||||
|
||||
// Executes the callback function asynchronously, but only one at a time.
|
||||
// Multiple requests at once are stored in a FIFO of size 1.
|
||||
// The context should point to a static reference.
|
||||
template<typename Data, typename Callback>
|
||||
inline void ExecuteAsyncAtomically(AsyncAtomicContext<Data>& context, const Callback& callback, const Data& data)
|
||||
{
|
||||
// Update the queue
|
||||
context.queueLock.lock();
|
||||
context.queue = data;
|
||||
context.queueLock.unlock();
|
||||
|
||||
if (!context.running)
|
||||
{
|
||||
// Launch the thread
|
||||
context.running = true;
|
||||
std::thread(
|
||||
[&, callback]()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
context.queueLock.lock();
|
||||
if (!context.queue.has_value())
|
||||
{
|
||||
context.queueLock.unlock();
|
||||
break;
|
||||
}
|
||||
Data data = std::move(*context.queue);
|
||||
context.queue = {};
|
||||
context.queueLock.unlock();
|
||||
|
||||
// Execute
|
||||
callback(std::move(data));
|
||||
}
|
||||
context.running = false;
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
// Plugins
|
||||
#include "Window.h"
|
||||
#define DL_VERSION 1
|
||||
|
|
Loading…
Reference in a new issue