#ifndef SERVICES_AUDIO_LOOPBACK_COORDINATOR_H_
#define SERVICES_AUDIO_LOOPBACK_COORDINATOR_H_
#include <memory>
#include <set>
#include <vector>
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/unguessable_token.h"
#include "services/audio/loopback_source.h"
namespace audio {
class LoopbackCoordinator {
public:
struct Member {
public:
Member(base::UnguessableToken group_id, LoopbackSource* loopback_source)
: group_id(group_id), loopback_source(loopback_source) {}
bool operator<(const Member& other) const {
return loopback_source < other.loopback_source;
}
friend bool operator<(const Member& lhs, const LoopbackSource* rhs_source) {
return lhs.loopback_source < rhs_source;
}
friend bool operator<(const LoopbackSource* lhs_source, const Member& rhs) {
return lhs_source < rhs.loopback_source;
}
const base::UnguessableToken group_id;
const raw_ptr<LoopbackSource> loopback_source;
};
using MemberSet = std::set<Member, std::less<>>;
class Observer {
public:
virtual void OnMemberAdded(const Member& member) = 0;
virtual void OnMemberRemoved(const Member& member) = 0;
protected:
virtual ~Observer() = default;
};
LoopbackCoordinator();
LoopbackCoordinator(const LoopbackCoordinator&) = delete;
LoopbackCoordinator& operator=(const LoopbackCoordinator) = delete;
~LoopbackCoordinator();
void AddMember(const base::UnguessableToken& group_id,
LoopbackSource* loopback_source);
void RemoveMember(LoopbackSource* loopback_source);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
void ForEachMember(
base::RepeatingCallback<void(const Member&)> callback) const;
private:
MemberSet members_;
std::set<raw_ptr<Observer>> observers_;
SEQUENCE_CHECKER(sequence_checker_);
};
class LoopbackGroupObserver : public LoopbackCoordinator::Observer {
public:
class Listener {
public:
virtual void OnSourceAdded(LoopbackSource* source) = 0;
virtual void OnSourceRemoved(LoopbackSource* source) = 0;
protected:
virtual ~Listener() = default;
};
class Matcher {
public:
virtual ~Matcher() = default;
virtual bool Match(const LoopbackCoordinator::Member& member) const = 0;
};
using SourceCallback = base::RepeatingCallback<void(LoopbackSource*)>;
static std::unique_ptr<LoopbackGroupObserver> CreateMatchingGroupObserver(
LoopbackCoordinator* coordinator,
const base::UnguessableToken& group_id);
static std::unique_ptr<LoopbackGroupObserver> CreateExcludingGroupObserver(
LoopbackCoordinator* coordinator,
const base::UnguessableToken& group_id);
LoopbackGroupObserver(LoopbackCoordinator* coordinator,
std::unique_ptr<Matcher> matcher);
~LoopbackGroupObserver() override;
LoopbackGroupObserver(const LoopbackGroupObserver&) = delete;
LoopbackGroupObserver& operator=(const LoopbackGroupObserver&) = delete;
void StartObserving(Listener* listener);
void StopObserving();
void ForEachSource(SourceCallback callback) const;
protected:
void OnMemberAdded(const LoopbackCoordinator::Member& member) override;
void OnMemberRemoved(const LoopbackCoordinator::Member& member) override;
private:
const raw_ptr<LoopbackCoordinator> coordinator_;
std::unique_ptr<Matcher> matcher_;
raw_ptr<Listener> listener_ = nullptr;
};
}
#endif