1// Copyright (c) 2012 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
5#ifndef REMOTING_HOST_LINUX_AUDIO_PIPE_READER_H_
6#define REMOTING_HOST_LINUX_AUDIO_PIPE_READER_H_
7
8#include "base/files/file.h"
9#include "base/files/file_path.h"
10#include "base/files/file_path_watcher.h"
11#include "base/memory/ref_counted.h"
12#include "base/memory/ref_counted_memory.h"
13#include "base/message_loop/message_loop.h"
14#include "base/observer_list_threadsafe.h"
15#include "base/time/time.h"
16#include "base/timer/timer.h"
17#include "remoting/proto/audio.pb.h"
18
19namespace remoting {
20
21struct AudioPipeReaderTraits;
22
23// AudioPipeReader class reads from a named pipe to which an audio server (e.g.
24// pulseaudio) writes the sound that's being played back and then sends data to
25// all registered observers.
26class AudioPipeReader
27    : public base::RefCountedThreadSafe<AudioPipeReader, AudioPipeReaderTraits>,
28      public base::MessageLoopForIO::Watcher {
29 public:
30  // PulseAudio's module-pipe-sink must be configured to use the following
31  // parameters for the sink we read from.
32  static const AudioPacket_SamplingRate kSamplingRate =
33      AudioPacket::SAMPLING_RATE_48000;
34  static const AudioPacket_BytesPerSample kBytesPerSample =
35      AudioPacket::BYTES_PER_SAMPLE_2;
36  static const AudioPacket_Channels kChannels = AudioPacket::CHANNELS_STEREO;
37
38  class StreamObserver {
39   public:
40    virtual void OnDataRead(scoped_refptr<base::RefCountedString> data) = 0;
41  };
42
43  // |task_runner| specifies the IO thread to use to read data from the pipe.
44  static scoped_refptr<AudioPipeReader> Create(
45      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
46      const base::FilePath& pipe_path);
47
48  // Register or unregister an observer. Each observer receives data on the
49  // thread on which it was registered and guaranteed not to be called after
50  // RemoveObserver().
51  void AddObserver(StreamObserver* observer);
52  void RemoveObserver(StreamObserver* observer);
53
54  // MessageLoopForIO::Watcher interface.
55  virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
56  virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
57
58 private:
59  friend class base::DeleteHelper<AudioPipeReader>;
60  friend class base::RefCountedThreadSafe<AudioPipeReader>;
61  friend struct AudioPipeReaderTraits;
62
63  AudioPipeReader(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
64                  const base::FilePath& pipe_path);
65  virtual ~AudioPipeReader();
66
67  void StartOnAudioThread();
68  void OnDirectoryChanged(const base::FilePath& path, bool error);
69  void TryOpenPipe();
70  void StartTimer();
71  void DoCapture();
72  void WaitForPipeReadable();
73
74  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
75  base::FilePath pipe_path_;
76
77  // Watcher for the directory that contains audio pipe we are reading from, to
78  // monitor when pulseaudio creates or deletes it.
79  base::FilePathWatcher file_watcher_;
80
81  base::File pipe_;
82  base::RepeatingTimer<AudioPipeReader> timer_;
83  scoped_refptr<ObserverListThreadSafe<StreamObserver> > observers_;
84
85  // Time when capturing was started.
86  base::TimeTicks started_time_;
87
88  // Stream position of the last capture in bytes with zero position
89  // corresponding to |started_time_|. Must always be a multiple of the sample
90  // size.
91  int64 last_capture_position_;
92
93  // Bytes left from the previous read.
94  std::string left_over_bytes_;
95
96  base::MessageLoopForIO::FileDescriptorWatcher file_descriptor_watcher_;
97
98  DISALLOW_COPY_AND_ASSIGN(AudioPipeReader);
99};
100
101// Destroys |audio_pipe_reader| on the audio thread.
102struct AudioPipeReaderTraits {
103  static void Destruct(const AudioPipeReader* audio_pipe_reader);
104};
105
106}  // namespace remoting
107
108#endif  // REMOTING_HOST_LINUX_AUDIO_PIPE_READER_H_
109