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