summaryrefslogtreecommitdiff
path: root/chromium/content/renderer/media/midi_message_filter.h
blob: f7e1a8474a49172d1ab6a8a9a1c481449c9ebc3f (plain)
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
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_
#define CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_

#include <set>
#include <vector>

#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "ipc/message_filter.h"
#include "media/midi/midi_port_info.h"
#include "media/midi/midi_result.h"
#include "third_party/WebKit/public/platform/WebMIDIAccessorClient.h"

namespace base {
class MessageLoopProxy;
}

namespace content {

// MessageFilter that handles MIDI messages.
class CONTENT_EXPORT MidiMessageFilter : public IPC::MessageFilter {
 public:
  explicit MidiMessageFilter(
      const scoped_refptr<base::MessageLoopProxy>& io_message_loop);

  // Each client registers for MIDI access here.
  // If permission is granted, then the client's
  void AddClient(blink::WebMIDIAccessorClient* client);
  void RemoveClient(blink::WebMIDIAccessorClient* client);

  // A client will only be able to call this method if it has a suitable
  // output port (from addOutputPort()).
  void SendMidiData(uint32 port,
                    const uint8* data,
                    size_t length,
                    double timestamp);

  // IO message loop associated with this message filter.
  scoped_refptr<base::MessageLoopProxy> io_message_loop() const {
    return io_message_loop_;
  }

 protected:
  ~MidiMessageFilter() override;

 private:
  void StartSessionOnIOThread();

  void SendMidiDataOnIOThread(uint32 port,
                              const std::vector<uint8>& data,
                              double timestamp);

  void EndSessionOnIOThread();

  // Sends an IPC message using |sender_|.
  void Send(IPC::Message* message);

  // IPC::MessageFilter override. Called on |io_message_loop|.
  bool OnMessageReceived(const IPC::Message& message) override;
  void OnFilterAdded(IPC::Sender* sender) override;
  void OnFilterRemoved() override;
  void OnChannelClosing() override;

  // Called when the browser process has approved (or denied) access to
  // MIDI hardware.
  void OnSessionStarted(media::MidiResult result);

  // These functions are called in 2 cases:
  //  (1) Just before calling |OnSessionStarted|, to notify the recipient about
  //      existing ports.
  //  (2) To notify the recipient that a new device was connected and that new
  //      ports have been created.
  void OnAddInputPort(media::MidiPortInfo info);
  void OnAddOutputPort(media::MidiPortInfo info);

  // Called when the browser process has sent MIDI data containing one or
  // more messages.
  void OnDataReceived(uint32 port,
                      const std::vector<uint8>& data,
                      double timestamp);

  // From time-to-time, the browser incrementally informs us of how many bytes
  // it has successfully sent. This is part of our throttling process to avoid
  // sending too much data before knowing how much has already been sent.
  void OnAcknowledgeSentData(size_t bytes_sent);

  // Following methods, Handle*, run on |main_message_loop_|.
  void HandleClientAdded(media::MidiResult result);

  void HandleAddInputPort(media::MidiPortInfo info);
  void HandleAddOutputPort(media::MidiPortInfo info);

  void HandleDataReceived(uint32 port,
                          const std::vector<uint8>& data,
                          double timestamp);

  void HandleAckknowledgeSentData(size_t bytes_sent);

  // IPC sender for Send(); must only be accessed on |io_message_loop_|.
  IPC::Sender* sender_;

  // Message loop on which IPC calls are driven.
  const scoped_refptr<base::MessageLoopProxy> io_message_loop_;

  // Main thread's message loop.
  scoped_refptr<base::MessageLoopProxy> main_message_loop_;

  /*
   * Notice: Following members are designed to be accessed only on
   * |main_message_loop_|.
   */
  // Keeps track of all MIDI clients.
  typedef std::set<blink::WebMIDIAccessorClient*> ClientsSet;
  ClientsSet clients_;

  // Represents clients that are waiting for a session being open.
  typedef std::vector<blink::WebMIDIAccessorClient*> ClientsQueue;
  ClientsQueue clients_waiting_session_queue_;

  // Represents a result on starting a session. Can be accessed only on
  media::MidiResult session_result_;

  // Holds MidiPortInfoList for input ports and output ports.
  media::MidiPortInfoList inputs_;
  media::MidiPortInfoList outputs_;

  size_t unacknowledged_bytes_sent_;

  DISALLOW_COPY_AND_ASSIGN(MidiMessageFilter);
};

}  // namespace content

#endif  // CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_