1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#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 {
// Manages a collection of Member objects and notifies observers of changes.
// The class is not thread-safe and is expected to be used on a single sequence.
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;
}
// The following two friend functions enable transparent lookups in
// MemberSet using a LoopbackSource*, which is required by std::set with
// std::less<>.
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<>>;
// Interface for observing addition/removal of members.
class Observer {
public:
// Called after a member has been added.
virtual void OnMemberAdded(const Member& member) = 0;
// Called just before a member is removed.
virtual void OnMemberRemoved(const Member& member) = 0;
protected:
virtual ~Observer() = default;
};
LoopbackCoordinator();
LoopbackCoordinator(const LoopbackCoordinator&) = delete;
LoopbackCoordinator& operator=(const LoopbackCoordinator) = delete;
~LoopbackCoordinator();
// Adds a member to the coordinator and notifies observers.
void AddMember(const base::UnguessableToken& group_id,
LoopbackSource* loopback_source);
// Notifies observers and removes a member from the coordinator.
void RemoveMember(LoopbackSource* loopback_source);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Iterates over all members and runs the given `callback` for each one.
void ForEachMember(
base::RepeatingCallback<void(const Member&)> callback) const;
private:
// All added members.
MemberSet members_;
// Observers to be notified of membership changes. A set, to ensure uniquness
// and guarantee that we never send a notification twice to the same observer.
std::set<raw_ptr<Observer>> observers_;
SEQUENCE_CHECKER(sequence_checker_);
};
// An observer that filters sources based on a matcher.
class LoopbackGroupObserver : public LoopbackCoordinator::Observer {
public:
// Interface for receiving events about sources being added/removed from the
// group.
class Listener {
public:
virtual void OnSourceAdded(LoopbackSource* source) = 0;
virtual void OnSourceRemoved(LoopbackSource* source) = 0;
protected:
virtual ~Listener() = default;
};
// Base class for matching logic.
class Matcher {
public:
virtual ~Matcher() = default;
virtual bool Match(const LoopbackCoordinator::Member& member) const = 0;
};
using SourceCallback = base::RepeatingCallback<void(LoopbackSource*)>;
// Creates an observer that notifies its listener about sources belonging to
// a specific group.
static std::unique_ptr<LoopbackGroupObserver> CreateMatchingGroupObserver(
LoopbackCoordinator* coordinator,
const base::UnguessableToken& group_id);
// Creates an observer that notifies its listener about all sources EXCEPT
// those belonging to a specific group.
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;
// Registers this observer with the coordinator to start receiving events.
void StartObserving(Listener* listener);
// Unregisters this observer from the coordinator to stop receiving events.
void StopObserving();
// Iterates over the observed sources and runs the callback.
void ForEachSource(SourceCallback callback) const;
protected:
// LoopbackCoordinator::Observer implementation:
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;
};
} // namespace audio
#endif // SERVICES_AUDIO_LOOPBACK_COORDINATOR_H_
|