summaryrefslogtreecommitdiffstats
path: root/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h
blob: 24ab7da0b54a9ad530befb3e33f8b4c4a61889c6 (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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright (c) 2017 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_PEPPER_PEPPER_PLATFORM_AUDIO_OUTPUT_DEV_H_
#define CONTENT_RENDERER_PEPPER_PEPPER_PLATFORM_AUDIO_OUTPUT_DEV_H_

#include <memory>
#include <string>

#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "media/audio/audio_output_ipc.h"
#include "media/base/audio_parameters.h"
#include "media/base/output_device_info.h"

namespace base {
class OneShotTimer;
class SingleThreadTaskRunner;
}

namespace content {
class PepperAudioOutputHost;

// This class is used to support new PPAPI |PPB_AudioOutput_Dev|, while
// |PepperPlatformAudioOutput| is to support old PPAPI |PPB_Audio|.
class PepperPlatformAudioOutputDev
    : public media::AudioOutputIPCDelegate,
      public base::RefCountedThreadSafe<PepperPlatformAudioOutputDev> {
 public:
  // Factory function, returns NULL on failure. StreamCreated() will be called
  // when the stream is created.
  static PepperPlatformAudioOutputDev* Create(int render_frame_id,
                                              const std::string& device_id,
                                              const GURL& document_url,
                                              int sample_rate,
                                              int frames_per_buffer,
                                              PepperAudioOutputHost* client);

  // The following three methods are all called on main thread.

  // Request authorization to use the device.
  void RequestDeviceAuthorization();

  // Starts the playback. Returns false on error or if called before the
  // stream is created or after the stream is closed.
  bool StartPlayback();

  // Stops the playback. Returns false on error or if called before the stream
  // is created or after the stream is closed.
  bool StopPlayback();

  // Sets the volume. Returns false on error or if called before the stream
  // is created or after the stream is closed.
  bool SetVolume(double volume);

  // Closes the stream. Make sure to call this before the object is
  // destructed.
  void ShutDown();

  // media::AudioOutputIPCDelegate implementation.
  void OnError() override;
  void OnDeviceAuthorized(media::OutputDeviceStatus device_status,
                          const media::AudioParameters& output_params,
                          const std::string& matched_device_id) override;
  void OnStreamCreated(base::SharedMemoryHandle handle,
                       base::SyncSocket::Handle socket_handle) override;
  void OnIPCClosed() override;

 protected:
  ~PepperPlatformAudioOutputDev() override;

 private:
  enum State {
    IPC_CLOSED,       // No more IPCs can take place.
    IDLE,             // Not started.
    AUTHORIZING,      // Sent device authorization request, waiting for reply.
    AUTHORIZED,       // Successful device authorization received.
    CREATING_STREAM,  // Waiting for OnStreamCreated() to be called back.
    PAUSED,   // Paused.  OnStreamCreated() has been called.  Can Play()/Stop().
    PLAYING,  // Playing back.  Can Pause()/Stop().
  };

  friend class base::RefCountedThreadSafe<PepperPlatformAudioOutputDev>;

  PepperPlatformAudioOutputDev();
  PepperPlatformAudioOutputDev(int render_frame_id,
                               const std::string& device_id,
                               const GURL& document_url,
                               base::TimeDelta authorization_timeout);

  // Creates audio stream. Used for new Pepper audio output interface
  // |PPB_AudioOutput_Dev|.
  bool Initialize(int sample_rate,
                  int frames_per_buffer,
                  PepperAudioOutputHost* client);

  void RequestDeviceAuthorizationOnIOThread();
  void CreateStreamOnIOThread(const media::AudioParameters& params);
  void StartPlaybackOnIOThread();
  void StopPlaybackOnIOThread();
  void SetVolumeOnIOThread(double volume);
  void ShutDownOnIOThread();

  void NotifyStreamCreationFailed();

  PepperAudioOutputHost* client_;

  // Used to send/receive IPC. THIS MUST ONLY BE ACCESSED ON THE
  // I/O thread except to send messages and get the message loop.
  std::unique_ptr<media::AudioOutputIPC> ipc_;

  scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;

  // The frame containing the Pepper widget.
  int render_frame_id_;

  // Initialized on the main thread and accessed on the I/O thread afterwards.
  media::AudioParameters params_;

  // Current state (must only be accessed from the IO thread).
  State state_;

  // State of Start() calls before OnDeviceAuthorized() is called.
  bool start_on_authorized_;

  // State of StartPlayback() calls before OnStreamCreated() is called.
  bool play_on_start_;

  // The media session ID used to identify which output device to be started.
  int session_id_;

  // ID of hardware output device to be used (provided session_id_ is zero)
  const std::string device_id_;
  const url::Origin security_origin_;

  // If |device_id_| is empty and |session_id_| is not, |matched_device_id_| is
  // received in OnDeviceAuthorized().
  std::string matched_device_id_;

  base::WaitableEvent did_receive_auth_;
  media::AudioParameters output_params_;
  media::OutputDeviceStatus device_status_;

  const base::TimeDelta auth_timeout_;
  std::unique_ptr<base::OneShotTimer> auth_timeout_action_;

  DISALLOW_COPY_AND_ASSIGN(PepperPlatformAudioOutputDev);
};

}  // namespace content

#endif  // CONTENT_RENDERER_PEPPER_PEPPER_PLATFORM_AUDIO_OUTPUT_DEV_H_