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