blob: 8ca62b731255d3a9ebb5c06499d36f90dd065962 [file] [log] [blame]
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +00001// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
dnicoara@chromium.org9f2a6f02014-01-03 21:25:00 +00005#ifndef MEDIA_MIDI_MIDI_MANAGER_ALSA_H_
6#define MEDIA_MIDI_MIDI_MANAGER_ALSA_H_
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +00007
agoode@chromium.org25227512014-06-08 05:12:05 +00008#include <alsa/asoundlib.h>
avi793390d2015-12-22 22:22:36 -08009#include <stdint.h>
danakj75afea02016-04-25 20:36:04 -070010
limasdfe59d0392015-11-19 20:28:57 -080011#include <map>
danakj75afea02016-04-25 20:36:04 -070012#include <memory>
Takuto Ikutafd795cb2019-01-05 00:32:48 +000013#include <unordered_map>
dchengc2aeece2015-12-27 00:54:00 -080014#include <utility>
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +000015#include <vector>
16
agoode55a8b522015-03-08 12:40:17 -070017#include "base/gtest_prod_util.h"
avieea95e82015-12-18 20:27:08 -080018#include "base/macros.h"
agoode@chromium.org25227512014-06-08 05:12:05 +000019#include "base/synchronization/lock.h"
Takashi Toyoshimae8240ab2018-10-03 09:30:11 +000020#include "base/thread_annotations.h"
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +000021#include "base/threading/thread.h"
agoodef212b2a2015-03-19 12:53:23 -070022#include "base/values.h"
agoode7de413f2015-04-24 00:13:39 -070023#include "device/udev_linux/scoped_udev.h"
brettw49ff0172015-05-05 12:43:04 -070024#include "media/midi/midi_export.h"
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +000025#include "media/midi/midi_manager.h"
26
toyoshime147c5e2015-05-07 21:58:31 -070027namespace midi {
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +000028
brettw49ff0172015-05-05 12:43:04 -070029class MIDI_EXPORT MidiManagerAlsa final : public MidiManager {
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +000030 public:
toyoshimf4d61522017-02-10 02:03:32 -080031 explicit MidiManagerAlsa(MidiService* service);
Peter Boström53634032021-09-22 20:24:34 +000032
33 MidiManagerAlsa(const MidiManagerAlsa&) = delete;
34 MidiManagerAlsa& operator=(const MidiManagerAlsa&) = delete;
35
dcheng9e8524d2014-10-27 15:18:50 -070036 ~MidiManagerAlsa() override;
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +000037
toyoshim@chromium.orgc82e66e2014-02-04 07:05:47 +000038 // MidiManager implementation.
dcheng9e8524d2014-10-27 15:18:50 -070039 void StartInitialization() override;
40 void DispatchSendMidiData(MidiManagerClient* client,
Avi Drissman3528fd02015-12-18 20:11:31 -050041 uint32_t port_index,
42 const std::vector<uint8_t>& data,
tzik925e2c62018-02-02 07:39:45 +000043 base::TimeTicks timestamp) override;
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +000044
45 private:
agoode99d63292015-04-13 08:39:25 -070046 friend class MidiManagerAlsaTest;
agoode55a8b522015-03-08 12:40:17 -070047 FRIEND_TEST_ALL_PREFIXES(MidiManagerAlsaTest, ExtractManufacturer);
agoode99d63292015-04-13 08:39:25 -070048 FRIEND_TEST_ALL_PREFIXES(MidiManagerAlsaTest, ToMidiPortState);
agoode55a8b522015-03-08 12:40:17 -070049
agoodeb09423b2015-05-11 11:39:57 -070050 class AlsaCard;
danakj75afea02016-04-25 20:36:04 -070051 using AlsaCardMap = std::map<int, std::unique_ptr<AlsaCard>>;
agoodeb09423b2015-05-11 11:39:57 -070052
agoode99d63292015-04-13 08:39:25 -070053 class MidiPort {
agoodef212b2a2015-03-19 12:53:23 -070054 public:
55 enum class Type { kInput, kOutput };
56
agooded87fc0f2015-05-21 08:29:31 -070057 // The Id class is used to keep the multiple strings separate
58 // but compare them all together for equality purposes.
59 // The individual strings that make up the Id can theoretically contain
60 // arbitrary characters, so unfortunately there is no simple way to
61 // concatenate them into a single string.
62 class Id final {
63 public:
64 Id();
65 Id(const std::string& bus,
66 const std::string& vendor_id,
67 const std::string& model_id,
68 const std::string& usb_interface_num,
69 const std::string& serial);
70 Id(const Id&);
71 ~Id();
72 bool operator==(const Id&) const;
73 bool empty() const;
74
75 std::string bus() const { return bus_; }
76 std::string vendor_id() const { return vendor_id_; }
77 std::string model_id() const { return model_id_; }
78 std::string usb_interface_num() const { return usb_interface_num_; }
79 std::string serial() const { return serial_; }
80
81 private:
82 std::string bus_;
83 std::string vendor_id_;
84 std::string model_id_;
85 std::string usb_interface_num_;
86 std::string serial_;
87 };
88
agoode99d63292015-04-13 08:39:25 -070089 MidiPort(const std::string& path,
agooded87fc0f2015-05-21 08:29:31 -070090 const Id& id,
agoode99d63292015-04-13 08:39:25 -070091 int client_id,
92 int port_id,
93 int midi_device,
94 const std::string& client_name,
95 const std::string& port_name,
96 const std::string& manufacturer,
97 const std::string& version,
98 Type type);
Peter Boström5e5c4fa2021-10-15 21:43:24 +000099
100 MidiPort(const MidiPort&) = delete;
101 MidiPort& operator=(const MidiPort&) = delete;
102
agoode99d63292015-04-13 08:39:25 -0700103 ~MidiPort();
agoodef212b2a2015-03-19 12:53:23 -0700104
105 // Gets a Value representation of this object, suitable for serialization.
danakj75afea02016-04-25 20:36:04 -0700106 std::unique_ptr<base::Value> Value() const;
agoodef212b2a2015-03-19 12:53:23 -0700107
108 // Gets a string version of Value in JSON format.
109 std::string JSONValue() const;
110
111 // Gets an opaque identifier for this object, suitable for using as the id
112 // field in MidiPort.id on the web. Note that this string does not store
113 // the full state.
114 std::string OpaqueKey() const;
115
agoode99d63292015-04-13 08:39:25 -0700116 // Checks for equality for connected ports.
117 bool MatchConnected(const MidiPort& query) const;
118 // Checks for equality for kernel cards with id, pass 1.
119 bool MatchCardPass1(const MidiPort& query) const;
120 // Checks for equality for kernel cards with id, pass 2.
121 bool MatchCardPass2(const MidiPort& query) const;
122 // Checks for equality for non-card clients, pass 1.
123 bool MatchNoCardPass1(const MidiPort& query) const;
124 // Checks for equality for non-card clients, pass 2.
125 bool MatchNoCardPass2(const MidiPort& query) const;
agoodef212b2a2015-03-19 12:53:23 -0700126
agoode99d63292015-04-13 08:39:25 -0700127 // accessors
128 std::string path() const { return path_; }
agooded87fc0f2015-05-21 08:29:31 -0700129 Id id() const { return id_; }
agoode99d63292015-04-13 08:39:25 -0700130 std::string client_name() const { return client_name_; }
131 std::string port_name() const { return port_name_; }
132 std::string manufacturer() const { return manufacturer_; }
133 std::string version() const { return version_; }
134 int client_id() const { return client_id_; }
135 int port_id() const { return port_id_; }
136 int midi_device() const { return midi_device_; }
137 Type type() const { return type_; }
Avi Drissman3528fd02015-12-18 20:11:31 -0500138 uint32_t web_port_index() const { return web_port_index_; }
agoode99d63292015-04-13 08:39:25 -0700139 bool connected() const { return connected_; }
140
141 // mutators
Avi Drissman3528fd02015-12-18 20:11:31 -0500142 void set_web_port_index(uint32_t web_port_index) {
agoode99d63292015-04-13 08:39:25 -0700143 web_port_index_ = web_port_index;
144 }
145 void set_connected(bool connected) { connected_ = connected; }
146 void Update(const std::string& path,
147 int client_id,
148 int port_id,
149 const std::string& client_name,
150 const std::string& port_name,
151 const std::string& manufacturer,
152 const std::string& version) {
153 path_ = path;
154 client_id_ = client_id;
155 port_id_ = port_id;
156 client_name_ = client_name;
157 port_name_ = port_name;
158 manufacturer_ = manufacturer;
159 version_ = version;
160 }
161
162 private:
163 // Immutable properties.
agooded87fc0f2015-05-21 08:29:31 -0700164 const Id id_;
agoode99d63292015-04-13 08:39:25 -0700165 const int midi_device_;
166
agoodef212b2a2015-03-19 12:53:23 -0700167 const Type type_;
168
agoode99d63292015-04-13 08:39:25 -0700169 // Mutable properties. These will get updated as ports move around or
170 // drivers change.
171 std::string path_;
172 int client_id_;
173 int port_id_;
174 std::string client_name_;
175 std::string port_name_;
176 std::string manufacturer_;
177 std::string version_;
178
179 // Index for MidiManager.
Avi Drissman3528fd02015-12-18 20:11:31 -0500180 uint32_t web_port_index_ = 0;
agoode99d63292015-04-13 08:39:25 -0700181
182 // Port is present in the ALSA system.
agoode5a1aa112015-06-21 20:51:00 -0700183 bool connected_ = true;
agoode55a8b522015-03-08 12:40:17 -0700184 };
185
agoode99d63292015-04-13 08:39:25 -0700186 class MidiPortStateBase {
187 public:
danakj75afea02016-04-25 20:36:04 -0700188 typedef std::vector<std::unique_ptr<MidiPort>>::iterator iterator;
agoodebd4be9b2015-03-16 19:17:25 -0700189
Peter Boström53634032021-09-22 20:24:34 +0000190 MidiPortStateBase(const MidiPortStateBase&) = delete;
191 MidiPortStateBase& operator=(const MidiPortStateBase&) = delete;
192
agoode99d63292015-04-13 08:39:25 -0700193 virtual ~MidiPortStateBase();
194
195 // Given a port, finds a port in the internal store.
196 iterator Find(const MidiPort& port);
197
198 // Given a port, finds a connected port, using exact matching.
199 iterator FindConnected(const MidiPort& port);
200
201 // Given a port, finds a disconnected port, using heuristic matching.
202 iterator FindDisconnected(const MidiPort& port);
203
204 iterator begin() { return ports_.begin(); }
205 iterator end() { return ports_.end(); }
206
207 protected:
208 MidiPortStateBase();
agoode5ebc4932015-12-01 08:25:12 -0800209 iterator erase(iterator position) { return ports_.erase(position); }
danakj75afea02016-04-25 20:36:04 -0700210 void push_back(std::unique_ptr<MidiPort> port) {
dchengc2aeece2015-12-27 00:54:00 -0800211 ports_.push_back(std::move(port));
212 }
agoode99d63292015-04-13 08:39:25 -0700213
214 private:
danakj75afea02016-04-25 20:36:04 -0700215 std::vector<std::unique_ptr<MidiPort>> ports_;
agoode99d63292015-04-13 08:39:25 -0700216 };
217
218 class TemporaryMidiPortState final : public MidiPortStateBase {
219 public:
agoode5ebc4932015-12-01 08:25:12 -0800220 iterator erase(iterator position) {
221 return MidiPortStateBase::erase(position);
Nico Webera0faaf72019-02-07 19:07:54 +0000222 }
danakj75afea02016-04-25 20:36:04 -0700223 void push_back(std::unique_ptr<MidiPort> port) {
dchengc2aeece2015-12-27 00:54:00 -0800224 MidiPortStateBase::push_back(std::move(port));
agoode5ebc4932015-12-01 08:25:12 -0800225 }
agoode99d63292015-04-13 08:39:25 -0700226 };
227
228 class MidiPortState final : public MidiPortStateBase {
229 public:
230 MidiPortState();
231
agoode5ebc4932015-12-01 08:25:12 -0800232 // Inserts a port at the end. Returns web_port_index.
danakj75afea02016-04-25 20:36:04 -0700233 uint32_t push_back(std::unique_ptr<MidiPort> port);
agoode99d63292015-04-13 08:39:25 -0700234
235 private:
Avi Drissman3528fd02015-12-18 20:11:31 -0500236 uint32_t num_input_ports_ = 0;
237 uint32_t num_output_ports_ = 0;
agoode99d63292015-04-13 08:39:25 -0700238 };
239
240 class AlsaSeqState {
241 public:
242 enum class PortDirection { kInput, kOutput, kDuplex };
243
244 AlsaSeqState();
Peter Boström53634032021-09-22 20:24:34 +0000245
246 AlsaSeqState(const AlsaSeqState&) = delete;
247 AlsaSeqState& operator=(const AlsaSeqState&) = delete;
248
agoode99d63292015-04-13 08:39:25 -0700249 ~AlsaSeqState();
250
251 void ClientStart(int client_id,
252 const std::string& client_name,
253 snd_seq_client_type_t type);
254 bool ClientStarted(int client_id);
255 void ClientExit(int client_id);
256 void PortStart(int client_id,
257 int port_id,
258 const std::string& port_name,
259 PortDirection direction,
260 bool midi);
261 void PortExit(int client_id, int port_id);
262 snd_seq_client_type_t ClientType(int client_id) const;
danakj75afea02016-04-25 20:36:04 -0700263 std::unique_ptr<TemporaryMidiPortState> ToMidiPortState(
agoodeb09423b2015-05-11 11:39:57 -0700264 const AlsaCardMap& alsa_cards);
265
266 int card_client_count() { return card_client_count_; }
agoode99d63292015-04-13 08:39:25 -0700267
268 private:
269 class Port {
270 public:
271 Port(const std::string& name, PortDirection direction, bool midi);
Peter Boström53634032021-09-22 20:24:34 +0000272
273 Port(const Port&) = delete;
274 Port& operator=(const Port&) = delete;
275
agoode99d63292015-04-13 08:39:25 -0700276 ~Port();
277
agoodeb0582872015-05-20 05:22:24 -0700278 std::string name() const { return name_; }
279 PortDirection direction() const { return direction_; }
agoode99d63292015-04-13 08:39:25 -0700280 // True if this port is a MIDI port, instead of another kind of ALSA port.
agoodeb0582872015-05-20 05:22:24 -0700281 bool midi() const { return midi_; }
agoode99d63292015-04-13 08:39:25 -0700282
283 private:
284 const std::string name_;
285 const PortDirection direction_;
286 const bool midi_;
agoode99d63292015-04-13 08:39:25 -0700287 };
288
289 class Client {
290 public:
danakj75afea02016-04-25 20:36:04 -0700291 using PortMap = std::map<int, std::unique_ptr<Port>>;
agoode99d63292015-04-13 08:39:25 -0700292
293 Client(const std::string& name, snd_seq_client_type_t type);
Peter Boström53634032021-09-22 20:24:34 +0000294
295 Client(const Client&) = delete;
296 Client& operator=(const Client&) = delete;
297
agoode99d63292015-04-13 08:39:25 -0700298 ~Client();
299
agoodeb0582872015-05-20 05:22:24 -0700300 std::string name() const { return name_; }
301 snd_seq_client_type_t type() const { return type_; }
danakj75afea02016-04-25 20:36:04 -0700302 void AddPort(int addr, std::unique_ptr<Port> port);
agoode99d63292015-04-13 08:39:25 -0700303 void RemovePort(int addr);
304 PortMap::const_iterator begin() const;
305 PortMap::const_iterator end() const;
306
307 private:
308 const std::string name_;
309 const snd_seq_client_type_t type_;
310 PortMap ports_;
agoode99d63292015-04-13 08:39:25 -0700311 };
312
danakj75afea02016-04-25 20:36:04 -0700313 std::map<int, std::unique_ptr<Client>> clients_;
agoode99d63292015-04-13 08:39:25 -0700314
agoodeb09423b2015-05-11 11:39:57 -0700315 // This is the current number of clients we know about that have
316 // cards. When this number matches alsa_card_midi_count_, we know
317 // we are in sync between ALSA and udev. Until then, we cannot generate
318 // MIDIConnectionEvents to web clients.
agoodedf1b9ff2015-06-25 18:14:50 -0700319 int card_client_count_ = 0;
agoode99d63292015-04-13 08:39:25 -0700320 };
321
agoodeb09423b2015-05-11 11:39:57 -0700322 class AlsaCard {
323 public:
324 AlsaCard(udev_device* dev,
agooded87fc0f2015-05-21 08:29:31 -0700325 const std::string& name,
326 const std::string& longname,
327 const std::string& driver,
agoodeb09423b2015-05-11 11:39:57 -0700328 int midi_device_count);
Peter Boström53634032021-09-22 20:24:34 +0000329
330 AlsaCard(const AlsaCard&) = delete;
331 AlsaCard& operator=(const AlsaCard&) = delete;
332
agoodeb09423b2015-05-11 11:39:57 -0700333 ~AlsaCard();
agooded87fc0f2015-05-21 08:29:31 -0700334 std::string name() const { return name_; }
335 std::string longname() const { return longname_; }
336 std::string driver() const { return driver_; }
337 std::string path() const { return path_; }
338 std::string bus() const { return bus_; }
339 std::string vendor_id() const { return vendor_id_; }
340 std::string model_id() const { return model_id_; }
341 std::string usb_interface_num() const { return usb_interface_num_; }
342 std::string serial() const { return serial_; }
agoodeb09423b2015-05-11 11:39:57 -0700343 int midi_device_count() const { return midi_device_count_; }
agooded87fc0f2015-05-21 08:29:31 -0700344 std::string manufacturer() const { return manufacturer_; }
agoodeb09423b2015-05-11 11:39:57 -0700345
346 private:
347 FRIEND_TEST_ALL_PREFIXES(MidiManagerAlsaTest, ExtractManufacturer);
348
349 // Extracts the manufacturer using heuristics and a variety of sources.
350 static std::string ExtractManufacturerString(
351 const std::string& udev_id_vendor,
352 const std::string& udev_id_vendor_id,
353 const std::string& udev_id_vendor_from_database,
agooded87fc0f2015-05-21 08:29:31 -0700354 const std::string& name,
355 const std::string& longname);
agoodeb09423b2015-05-11 11:39:57 -0700356
agooded87fc0f2015-05-21 08:29:31 -0700357 const std::string name_;
358 const std::string longname_;
359 const std::string driver_;
360 const std::string path_;
361 const std::string bus_;
362 const std::string vendor_id_;
363 const std::string model_id_;
364 const std::string usb_interface_num_;
365 const std::string serial_;
366 const int midi_device_count_;
367 const std::string manufacturer_;
agoodeb09423b2015-05-11 11:39:57 -0700368 };
369
agoode5a1aa112015-06-21 20:51:00 -0700370 struct SndSeqDeleter {
371 void operator()(snd_seq_t* seq) const { snd_seq_close(seq); }
372 };
373
374 struct SndMidiEventDeleter {
375 void operator()(snd_midi_event_t* coder) const {
376 snd_midi_event_free(coder);
Nico Webera0faaf72019-02-07 19:07:54 +0000377 }
agoode5a1aa112015-06-21 20:51:00 -0700378 };
379
Takuto Ikutafd795cb2019-01-05 00:32:48 +0000380 using SourceMap = std::unordered_map<int, uint32_t>;
381 using OutPortMap = std::unordered_map<uint32_t, int>;
danakj75afea02016-04-25 20:36:04 -0700382 using ScopedSndSeqPtr = std::unique_ptr<snd_seq_t, SndSeqDeleter>;
agoodeb2ead822016-03-11 12:14:35 -0800383 using ScopedSndMidiEventPtr =
danakj75afea02016-04-25 20:36:04 -0700384 std::unique_ptr<snd_midi_event_t, SndMidiEventDeleter>;
agoode99d63292015-04-13 08:39:25 -0700385
agoode@chromium.org25227512014-06-08 05:12:05 +0000386 // An internal callback that runs on MidiSendThread.
toyoshimefcee5e2017-06-14 07:14:39 -0700387 void SendMidiData(MidiManagerClient* client,
toyoshimf4d61522017-02-10 02:03:32 -0800388 uint32_t port_index,
389 const std::vector<uint8_t>& data);
agoode@chromium.org25227512014-06-08 05:12:05 +0000390
toyoshimefcee5e2017-06-14 07:14:39 -0700391 void EventLoop();
tzik925e2c62018-02-02 07:39:45 +0000392 void ProcessSingleEvent(snd_seq_event_t* event, base::TimeTicks timestamp);
agoode99d63292015-04-13 08:39:25 -0700393 void ProcessClientStartEvent(int client_id);
394 void ProcessPortStartEvent(const snd_seq_addr_t& addr);
395 void ProcessClientExitEvent(const snd_seq_addr_t& addr);
396 void ProcessPortExitEvent(const snd_seq_addr_t& addr);
agoode975043d2015-05-11 00:46:17 -0700397 void ProcessUdevEvent(udev_device* dev);
agoodeb09423b2015-05-11 11:39:57 -0700398 void AddCard(udev_device* dev);
399 void RemoveCard(int number);
agoode99d63292015-04-13 08:39:25 -0700400
401 // Updates port_state_ and Web MIDI state from alsa_seq_state_.
402 void UpdatePortStateAndGenerateEvents();
403
404 // Enumerates ports. Call once after subscribing to the announce port.
405 void EnumerateAlsaPorts();
agoode975043d2015-05-11 00:46:17 -0700406 // Enumerates udev cards. Call once after initializing the udev monitor.
407 bool EnumerateUdevCards();
agoode99d63292015-04-13 08:39:25 -0700408 // Returns true if successful.
Avi Drissman3528fd02015-12-18 20:11:31 -0500409 bool CreateAlsaOutputPort(uint32_t port_index, int client_id, int port_id);
410 void DeleteAlsaOutputPort(uint32_t port_index);
agoode99d63292015-04-13 08:39:25 -0700411 // Returns true if successful.
Avi Drissman3528fd02015-12-18 20:11:31 -0500412 bool Subscribe(uint32_t port_index, int client_id, int port_id);
agoode99d63292015-04-13 08:39:25 -0700413
Takashi Toyoshima0ae49702017-09-01 04:59:51 +0000414 // Allocates new snd_midi_event_t instance and wraps it to return as
415 // ScopedSndMidiEventPtr.
416 ScopedSndMidiEventPtr CreateScopedSndMidiEventPtr(size_t size);
417
agoodeb2ead822016-03-11 12:14:35 -0800418 // Members initialized in the constructor are below.
419 // Our copies of the internal state of the ports of seq and udev.
agoode99d63292015-04-13 08:39:25 -0700420 AlsaSeqState alsa_seq_state_;
421 MidiPortState port_state_;
toyoshim@chromium.org4a8657c2014-02-06 11:23:09 +0000422
agoode@chromium.org25227512014-06-08 05:12:05 +0000423 // One input port, many output ports.
Takashi Toyoshimae8240ab2018-10-03 09:30:11 +0000424 base::Lock out_ports_lock_;
425 OutPortMap out_ports_ GUARDED_BY(out_ports_lock_);
agoode@chromium.org25227512014-06-08 05:12:05 +0000426
agoodebd4be9b2015-03-16 19:17:25 -0700427 // Mapping from ALSA client:port to our index.
agoode@chromium.org25227512014-06-08 05:12:05 +0000428 SourceMap source_map_;
429
agoodeb09423b2015-05-11 11:39:57 -0700430 // Mapping from card to devices.
431 AlsaCardMap alsa_cards_;
agoodeb09423b2015-05-11 11:39:57 -0700432
433 // This is the current count of midi devices across all cards we know
434 // about. When this number matches card_client_count_ in AlsaSeqState,
435 // we are safe to generate MIDIConnectionEvents. Otherwise we need to
436 // wait for our information from ALSA and udev to get back in sync.
agoode5a1aa112015-06-21 20:51:00 -0700437 int alsa_card_midi_count_ = 0;
agoodeb09423b2015-05-11 11:39:57 -0700438
agoodeb2ead822016-03-11 12:14:35 -0800439 // ALSA seq handles and ids.
440 ScopedSndSeqPtr in_client_;
441 int in_client_id_;
Takashi Toyoshimae8240ab2018-10-03 09:30:11 +0000442 ScopedSndSeqPtr out_client_ GUARDED_BY(out_client_lock_);
443 base::Lock out_client_lock_;
agoodeb2ead822016-03-11 12:14:35 -0800444 int out_client_id_;
445 int in_port_id_;
446
agoode99d63292015-04-13 08:39:25 -0700447 // ALSA event -> MIDI coder.
agoodeb2ead822016-03-11 12:14:35 -0800448 ScopedSndMidiEventPtr decoder_;
agoode@chromium.org25227512014-06-08 05:12:05 +0000449
agoode7de413f2015-04-24 00:13:39 -0700450 // udev, for querying hardware devices.
451 device::ScopedUdevPtr udev_;
agoode975043d2015-05-11 00:46:17 -0700452 device::ScopedUdevMonitorPtr udev_monitor_;
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +0000453};
454
toyoshime147c5e2015-05-07 21:58:31 -0700455} // namespace midi
toyoshim@chromium.orga97eebf2014-01-03 07:52:39 +0000456
dnicoara@chromium.org9f2a6f02014-01-03 21:25:00 +0000457#endif // MEDIA_MIDI_MIDI_MANAGER_ALSA_H_