File: loopback_coordinator.h

package info (click to toggle)
chromium 145.0.7632.159-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,976,224 kB
  • sloc: cpp: 36,198,469; ansic: 7,634,080; javascript: 3,564,060; python: 1,649,622; xml: 838,470; asm: 717,087; pascal: 185,708; sh: 88,786; perl: 88,718; objc: 79,984; sql: 59,811; cs: 42,452; fortran: 24,101; makefile: 21,144; tcl: 15,277; php: 14,022; yacc: 9,066; ruby: 7,553; awk: 3,720; lisp: 3,233; lex: 1,328; ada: 727; jsp: 228; sed: 36
file content (159 lines) | stat: -rw-r--r-- 5,303 bytes parent folder | download | duplicates (6)
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_