| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/host/linux/audio_pipe_reader.h" | 5 #include "remoting/host/linux/audio_pipe_reader.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
| 10 #include <sys/types.h> | 10 #include <sys/types.h> |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 | 56 |
| 57 AudioPipeReader::~AudioPipeReader() {} | 57 AudioPipeReader::~AudioPipeReader() {} |
| 58 | 58 |
| 59 void AudioPipeReader::AddObserver(StreamObserver* observer) { | 59 void AudioPipeReader::AddObserver(StreamObserver* observer) { |
| 60 observers_->AddObserver(observer); | 60 observers_->AddObserver(observer); |
| 61 } | 61 } |
| 62 void AudioPipeReader::RemoveObserver(StreamObserver* observer) { | 62 void AudioPipeReader::RemoveObserver(StreamObserver* observer) { |
| 63 observers_->RemoveObserver(observer); | 63 observers_->RemoveObserver(observer); |
| 64 } | 64 } |
| 65 | 65 |
| 66 void AudioPipeReader::OnFileCanReadWithoutBlocking(int fd) { | |
| 67 DCHECK_EQ(fd, pipe_.GetPlatformFile()); | |
| 68 StartTimer(); | |
| 69 } | |
| 70 | |
| 71 void AudioPipeReader::OnFileCanWriteWithoutBlocking(int fd) { | |
| 72 NOTREACHED(); | |
| 73 } | |
| 74 | |
| 75 void AudioPipeReader::StartOnAudioThread() { | 66 void AudioPipeReader::StartOnAudioThread() { |
| 76 DCHECK(task_runner_->BelongsToCurrentThread()); | 67 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 77 | 68 |
| 78 if (!file_watcher_.Watch(pipe_path_.DirName(), true, | 69 if (!file_watcher_.Watch(pipe_path_.DirName(), true, |
| 79 base::Bind(&AudioPipeReader::OnDirectoryChanged, | 70 base::Bind(&AudioPipeReader::OnDirectoryChanged, |
| 80 base::Unretained(this)))) { | 71 base::Unretained(this)))) { |
| 81 LOG(ERROR) << "Failed to watch pulseaudio directory " | 72 LOG(ERROR) << "Failed to watch pulseaudio directory " |
| 82 << pipe_path_.DirName().value(); | 73 << pipe_path_.DirName().value(); |
| 83 } | 74 } |
| 84 | 75 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 108 if (new_pipe.IsValid() && pipe_.IsValid()) { | 99 if (new_pipe.IsValid() && pipe_.IsValid()) { |
| 109 struct stat old_stat; | 100 struct stat old_stat; |
| 110 struct stat new_stat; | 101 struct stat new_stat; |
| 111 if (fstat(pipe_.GetPlatformFile(), &old_stat) == 0 && | 102 if (fstat(pipe_.GetPlatformFile(), &old_stat) == 0 && |
| 112 fstat(new_pipe.GetPlatformFile(), &new_stat) == 0 && | 103 fstat(new_pipe.GetPlatformFile(), &new_stat) == 0 && |
| 113 old_stat.st_ino == new_stat.st_ino) { | 104 old_stat.st_ino == new_stat.st_ino) { |
| 114 return; | 105 return; |
| 115 } | 106 } |
| 116 } | 107 } |
| 117 | 108 |
| 118 file_descriptor_watcher_.StopWatchingFileDescriptor(); | 109 pipe_watch_controller_.reset(); |
| 119 timer_.Stop(); | 110 timer_.Stop(); |
| 120 | 111 |
| 121 pipe_ = std::move(new_pipe); | 112 pipe_ = std::move(new_pipe); |
| 122 | 113 |
| 123 if (pipe_.IsValid()) { | 114 if (pipe_.IsValid()) { |
| 124 // Get buffer size for the pipe. | 115 // Get buffer size for the pipe. |
| 125 pipe_buffer_size_ = fpathconf(pipe_.GetPlatformFile(), _PC_PIPE_BUF); | 116 pipe_buffer_size_ = fpathconf(pipe_.GetPlatformFile(), _PC_PIPE_BUF); |
| 126 if (pipe_buffer_size_ < 0) { | 117 if (pipe_buffer_size_ < 0) { |
| 127 PLOG(ERROR) << "fpathconf(_PC_PIPE_BUF)"; | 118 PLOG(ERROR) << "fpathconf(_PC_PIPE_BUF)"; |
| 128 pipe_buffer_size_ = 4096; | 119 pipe_buffer_size_ = 4096; |
| 129 } | 120 } |
| 130 | 121 |
| 131 // Read from the pipe twice per buffer length, to avoid starving the stream. | 122 // Read from the pipe twice per buffer length, to avoid starving the stream. |
| 132 capture_period_ = base::TimeDelta::FromSeconds(1) * pipe_buffer_size_ / | 123 capture_period_ = base::TimeDelta::FromSeconds(1) * pipe_buffer_size_ / |
| 133 kSampleBytesPerSecond / 2; | 124 kSampleBytesPerSecond / 2; |
| 134 | 125 |
| 135 WaitForPipeReadable(); | 126 WaitForPipeReadable(); |
| 136 } | 127 } |
| 137 } | 128 } |
| 138 | 129 |
| 139 void AudioPipeReader::StartTimer() { | 130 void AudioPipeReader::StartTimer() { |
| 140 DCHECK(task_runner_->BelongsToCurrentThread()); | 131 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 132 DCHECK(pipe_watch_controller_); |
| 133 pipe_watch_controller_.reset(); |
| 141 started_time_ = base::TimeTicks::Now(); | 134 started_time_ = base::TimeTicks::Now(); |
| 142 last_capture_position_ = 0; | 135 last_capture_position_ = 0; |
| 143 timer_.Start(FROM_HERE, capture_period_, this, &AudioPipeReader::DoCapture); | 136 timer_.Start(FROM_HERE, capture_period_, this, &AudioPipeReader::DoCapture); |
| 144 } | 137 } |
| 145 | 138 |
| 146 void AudioPipeReader::DoCapture() { | 139 void AudioPipeReader::DoCapture() { |
| 147 DCHECK(task_runner_->BelongsToCurrentThread()); | 140 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 148 DCHECK(pipe_.IsValid()); | 141 DCHECK(pipe_.IsValid()); |
| 149 | 142 |
| 150 // Calculate how much we need read from the pipe. Pulseaudio doesn't control | 143 // Calculate how much we need read from the pipe. Pulseaudio doesn't control |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 DCHECK_LE(last_capture_position_, stream_position_bytes); | 188 DCHECK_LE(last_capture_position_, stream_position_bytes); |
| 196 | 189 |
| 197 // Dispatch asynchronous notification to the stream observers. | 190 // Dispatch asynchronous notification to the stream observers. |
| 198 scoped_refptr<base::RefCountedString> data_ref = | 191 scoped_refptr<base::RefCountedString> data_ref = |
| 199 base::RefCountedString::TakeString(&data); | 192 base::RefCountedString::TakeString(&data); |
| 200 observers_->Notify(FROM_HERE, &StreamObserver::OnDataRead, data_ref); | 193 observers_->Notify(FROM_HERE, &StreamObserver::OnDataRead, data_ref); |
| 201 } | 194 } |
| 202 | 195 |
| 203 void AudioPipeReader::WaitForPipeReadable() { | 196 void AudioPipeReader::WaitForPipeReadable() { |
| 204 timer_.Stop(); | 197 timer_.Stop(); |
| 205 base::MessageLoopForIO::current()->WatchFileDescriptor( | 198 DCHECK(!pipe_watch_controller_); |
| 206 pipe_.GetPlatformFile(), false, base::MessageLoopForIO::WATCH_READ, | 199 pipe_watch_controller_ = base::FileDescriptorWatcher::WatchReadable( |
| 207 &file_descriptor_watcher_, this); | 200 pipe_.GetPlatformFile(), |
| 201 base::Bind(&AudioPipeReader::StartTimer, base::Unretained(this))); |
| 208 } | 202 } |
| 209 | 203 |
| 210 // static | 204 // static |
| 211 void AudioPipeReaderTraits::Destruct(const AudioPipeReader* audio_pipe_reader) { | 205 void AudioPipeReaderTraits::Destruct(const AudioPipeReader* audio_pipe_reader) { |
| 212 audio_pipe_reader->task_runner_->DeleteSoon(FROM_HERE, audio_pipe_reader); | 206 audio_pipe_reader->task_runner_->DeleteSoon(FROM_HERE, audio_pipe_reader); |
| 213 } | 207 } |
| 214 | 208 |
| 215 } // namespace remoting | 209 } // namespace remoting |
| OLD | NEW |