15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/linux/audio_pipe_reader.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const int kSampleBytesPerSecond = AudioPipeReader::kSamplingRate *
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                  AudioPipeReader::kChannels *
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                  AudioPipeReader::kBytesPerSample;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Read data from the pipe every 40ms.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCapturingPeriodMs = 40;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Size of the pipe buffer in milliseconds.
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kPipeBufferSizeMs = kCapturingPeriodMs * 2;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Size of the pipe buffer in bytes.
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kPipeBufferSizeBytes = kPipeBufferSizeMs * kSampleBytesPerSecond /
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Time::kMillisecondsPerSecond;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(F_SETPIPE_SZ)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// F_SETPIPE_SZ is supported only starting linux 2.6.35, but we want to be able
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to compile this code on machines with older kernel.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define F_SETPIPE_SZ 1031
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(F_SETPIPE_SZ)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<AudioPipeReader> AudioPipeReader::Create(
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const base::FilePath& pipe_path) {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a reference to the new AudioPipeReader before posting the
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // StartOnAudioThread task, otherwise it may be deleted on the audio
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // thread before we return.
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<AudioPipeReader> pipe_reader =
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      new AudioPipeReader(task_runner, pipe_path);
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  task_runner->PostTask(
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      FROM_HERE, base::Bind(&AudioPipeReader::StartOnAudioThread, pipe_reader));
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return pipe_reader;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioPipeReader::AudioPipeReader(
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const base::FilePath& pipe_path)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : task_runner_(task_runner),
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pipe_path_(pipe_path),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      observers_(new ObserverListThreadSafe<StreamObserver>()) {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)AudioPipeReader::~AudioPipeReader() {}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPipeReader::AddObserver(StreamObserver* observer) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_->AddObserver(observer);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPipeReader::RemoveObserver(StreamObserver* observer) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_->RemoveObserver(observer);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPipeReader::OnFileCanReadWithoutBlocking(int fd) {
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK_EQ(fd, pipe_.GetPlatformFile());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartTimer();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPipeReader::OnFileCanWriteWithoutBlocking(int fd) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void AudioPipeReader::StartOnAudioThread() {
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(task_runner_->BelongsToCurrentThread());
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!file_watcher_.Watch(pipe_path_.DirName(), true,
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                           base::Bind(&AudioPipeReader::OnDirectoryChanged,
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      base::Unretained(this)))) {
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR) << "Failed to watch pulseaudio directory "
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)               << pipe_path_.DirName().value();
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TryOpenPipe();
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void AudioPipeReader::OnDirectoryChanged(const base::FilePath& path,
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         bool error) {
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(task_runner_->BelongsToCurrentThread());
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (error) {
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR) << "File watcher returned an error.";
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TryOpenPipe();
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void AudioPipeReader::TryOpenPipe() {
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(task_runner_->BelongsToCurrentThread());
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::File new_pipe;
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  new_pipe.Initialize(
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pipe_path_,
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC);
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If both |pipe_| and |new_pipe| are valid then compare inodes for the two
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // file descriptors. Don't need to do anything if inode hasn't changed.
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (new_pipe.IsValid() && pipe_.IsValid()) {
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    struct stat old_stat;
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    struct stat new_stat;
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (fstat(pipe_.GetPlatformFile(), &old_stat) == 0 &&
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        fstat(new_pipe.GetPlatformFile(), &new_stat) == 0 &&
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        old_stat.st_ino == new_stat.st_ino) {
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return;
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  file_descriptor_watcher_.StopWatchingFileDescriptor();
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  timer_.Stop();
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pipe_ = new_pipe.Pass();
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (pipe_.IsValid()) {
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Set O_NONBLOCK flag.
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (HANDLE_EINTR(fcntl(pipe_.GetPlatformFile(), F_SETFL, O_NONBLOCK)) < 0) {
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      PLOG(ERROR) << "fcntl";
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pipe_.Close();
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return;
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Set buffer size for the pipe.
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (HANDLE_EINTR(fcntl(
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            pipe_.GetPlatformFile(), F_SETPIPE_SZ, kPipeBufferSizeBytes)) < 0) {
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      PLOG(ERROR) << "fcntl";
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    WaitForPipeReadable();
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPipeReader::StartTimer() {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(task_runner_->BelongsToCurrentThread());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  started_time_ = base::TimeTicks::Now();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_capture_position_ = 0;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCapturingPeriodMs),
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               this, &AudioPipeReader::DoCapture);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPipeReader::DoCapture() {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(task_runner_->BelongsToCurrentThread());
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(pipe_.IsValid());
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calculate how much we need read from the pipe. Pulseaudio doesn't control
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // how much data it writes to the pipe, so we need to pace the stream.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta stream_position = base::TimeTicks::Now() - started_time_;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 stream_position_bytes = stream_position.InMilliseconds() *
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kSampleBytesPerSecond / base::Time::kMillisecondsPerSecond;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 bytes_to_read = stream_position_bytes - last_capture_position_;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data = left_over_bytes_;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t pos = data.size();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_over_bytes_.clear();
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.resize(pos + bytes_to_read);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (pos < data.size()) {
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int read_result =
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        pipe_.ReadAtCurrentPos(string_as_array(&data) + pos, data.size() - pos);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (read_result > 0) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pos += read_result;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (read_result < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PLOG(ERROR) << "read";
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Stop reading from the pipe if PulseAudio isn't writing anything.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pos == 0) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitForPipeReadable();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save any incomplete samples we've read for later. Each packet should
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // contain integer number of samples.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int incomplete_samples_bytes = pos % (kChannels * kBytesPerSample);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_over_bytes_.assign(data, pos - incomplete_samples_bytes,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          incomplete_samples_bytes);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.resize(pos - incomplete_samples_bytes);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_capture_position_ += data.size();
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Normally PulseAudio will keep pipe buffer full, so we should always be able
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to read |bytes_to_read| bytes, but in case it's misbehaving we need to make
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // sure that |stream_position_bytes| doesn't go out of sync with the current
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // stream position.
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (stream_position_bytes - last_capture_position_ > kPipeBufferSizeBytes)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_capture_position_ = stream_position_bytes - kPipeBufferSizeBytes;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_LE(last_capture_position_, stream_position_bytes);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dispatch asynchronous notification to the stream observers.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::RefCountedString> data_ref =
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::RefCountedString::TakeString(&data);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_->Notify(&StreamObserver::OnDataRead, data_ref);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPipeReader::WaitForPipeReadable() {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer_.Stop();
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForIO::current()->WatchFileDescriptor(
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pipe_.GetPlatformFile(), false, base::MessageLoopForIO::WATCH_READ,
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      &file_descriptor_watcher_, this);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioPipeReaderTraits::Destruct(const AudioPipeReader* audio_pipe_reader) {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  audio_pipe_reader->task_runner_->DeleteSoon(FROM_HERE, audio_pipe_reader);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
227