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
content / browser / media / midi_host.h [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_MEDIA_MIDI_HOST_H_
#define CONTENT_BROWSER_MEDIA_MIDI_HOST_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "base/tuple.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "media/midi/midi_manager.h"
#include "media/midi/midi_service.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace midi {
class MidiService;
class MidiMessageQueue;
} // namespace midi
namespace content {
class CONTENT_EXPORT MidiHost : public midi::MidiManagerClient,
public midi::mojom::MidiSessionProvider,
public midi::mojom::MidiSession {
public:
MidiHost(const MidiHost&) = delete;
MidiHost& operator=(const MidiHost&) = delete;
~MidiHost() override;
// Creates an instance of MidiHost and binds |receiver| to the instance using
// a self owned receiver. Should be called on the IO thread.
static void BindReceiver(
int render_process_id,
midi::MidiService* midi_service,
mojo::PendingReceiver<midi::mojom::MidiSessionProvider> receiver);
// MidiManagerClient implementation. These methods can be called on any thread
// by platform specific implementations of MidiManager, so use locks
// appropriately.
void CompleteStartSession(midi::mojom::Result result) override;
void AddInputPort(const midi::mojom::PortInfo& info) override;
void AddOutputPort(const midi::mojom::PortInfo& info) override;
void SetInputPortState(uint32_t port, midi::mojom::PortState state) override;
void SetOutputPortState(uint32_t port, midi::mojom::PortState state) override;
void ReceiveMidiData(uint32_t port,
const uint8_t* data,
size_t length,
base::TimeTicks timestamp) override;
void AccumulateMidiBytesSent(size_t n) override;
void Detach() override;
// midi::mojom::MidiSessionProvider implementation.
void StartSession(
mojo::PendingReceiver<midi::mojom::MidiSession> session_receiver,
mojo::PendingRemote<midi::mojom::MidiSessionClient> client) override;
// midi::mojom::MidiSession implementation.
void SendData(uint32_t port,
const std::vector<uint8_t>& data,
base::TimeTicks timestamp) override;
protected:
MidiHost(int renderer_process_id, midi::MidiService* midi_service);
void SetHasMidiPermissionForTesting(bool value) {
has_midi_permission_ = value;
}
private:
// Use this to call methods on |midi_client_|. It makes sure that midi_client_
// is only accessed on the IO thread.
template <typename Method, typename... Params>
void CallClient(Method method, Params... params);
void EndSession();
const int renderer_process_id_;
// Represents if the renderer has a permission to send/receive MIDI messages.
bool has_midi_permission_;
// Represents if the renderer has a permission to send/receive MIDI SysEX
// messages.
bool has_midi_sysex_permission_;
// |midi_service_| manages a MidiManager instance that talks to
// platform-specific MIDI APIs. It can be nullptr after detached.
raw_ptr<midi::MidiService> midi_service_;
// Buffers where data sent from each MIDI input port is stored.
std::vector<std::unique_ptr<midi::MidiMessageQueue>> received_messages_queues_
GUARDED_BY(messages_queues_lock_);
// Protects access to |received_messages_queues_|;
base::Lock messages_queues_lock_;
// The number of bytes sent to the platform-specific MIDI sending
// system, but not yet completed.
size_t sent_bytes_in_flight_ GUARDED_BY(in_flight_lock_);
// The number of bytes successfully sent since the last time
// we've acknowledged back to the renderer.
size_t bytes_sent_since_last_acknowledgement_;
// Protects access to |sent_bytes_in_flight_|.
base::Lock in_flight_lock_;
// How many output port exists.
uint32_t output_port_count_ GUARDED_BY(output_port_count_lock_);
// Protects access to |output_port_count_|.
base::Lock output_port_count_lock_;
// Stores a session request sent from the renderer until CompleteStartSession
// is called.
mojo::PendingReceiver<midi::mojom::MidiSession> pending_session_receiver_;
// Bound on the IO thread if a session is successfully started by MidiService.
mojo::Receiver<midi::mojom::MidiSession> midi_session_{this};
// Bound on the IO thread and should only be called there. Use CallClient to
// call midi::mojom::MidiSessionClient methods.
mojo::Remote<midi::mojom::MidiSessionClient> midi_client_;
// WeakPtr factory for CallClient callbacks.
base::WeakPtrFactory<MidiHost> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_MEDIA_MIDI_HOST_H_