summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-01 01:15:17 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-01 01:15:17 +0000
commitdcb41734dcf22b7a2150209e26e42bf3447077fc (patch)
tree2836275e33b3f1795f4ca338b9947e47c192b735 /remoting
parent904e9138fb2ca78ba6ae1f1054f9ce8cfe19eda5 (diff)
downloadchromium_src-dcb41734dcf22b7a2150209e26e42bf3447077fc.zip
chromium_src-dcb41734dcf22b7a2150209e26e42bf3447077fc.tar.gz
chromium_src-dcb41734dcf22b7a2150209e26e42bf3447077fc.tar.bz2
Fix AudioCapturer implementation to read from audio pipe even when there are no active clients.
Pulseaudio blocks playback when the host stops reading from the audio pipe. Previously the host was reading from the pipe only when there is an active client. Fixed the capturer to always read from the pipe, so that we don't halt playback when user disconnects. Also changed sampling rate to 48000 to avoid resampling in the host. BUG=153090 Review URL: https://codereview.chromium.org/11316010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@165275 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/host/audio_capturer_linux.cc168
-rw-r--r--remoting/host/audio_capturer_linux.h47
-rw-r--r--remoting/host/linux/audio_pipe_reader.cc171
-rw-r--r--remoting/host/linux/audio_pipe_reader.h78
-rw-r--r--remoting/host/remoting_me2me_host.cc23
-rw-r--r--remoting/remoting.gyp2
-rwxr-xr-xremoting/tools/me2me_virtual_host.py2
7 files changed, 309 insertions, 182 deletions
diff --git a/remoting/host/audio_capturer_linux.cc b/remoting/host/audio_capturer_linux.cc
index b4a8fd0..c8293de 100644
--- a/remoting/host/audio_capturer_linux.cc
+++ b/remoting/host/audio_capturer_linux.cc
@@ -4,18 +4,10 @@
#include "remoting/host/audio_capturer_linux.h"
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/eintr_wrapper.h"
#include "base/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "remoting/proto/audio.pb.h"
-#include "remoting/host/chromoting_host_context.h"
namespace remoting {
@@ -23,74 +15,36 @@ namespace {
// PulseAudio's module-pipe-sink must be configured to use the following
// parameters for the sink we read from.
-const AudioPacket_SamplingRate kSamplingRate = AudioPacket::SAMPLING_RATE_44100;
-const int kChannels = 2;
-const int kBytesPerSample = 2;
-
-// Read data from the pipe every 40ms.
-const int kCapturingPeriodMs = 40;
-
-#if !defined(F_SETPIPE_SZ)
-// F_SETPIPE_SZ is supported only starting linux 2.6.35, but we want to be able
-// to compile this code on machines with older kernel.
-#define F_SETPIPE_SZ 1031
-#endif // defined(F_SETPIPE_SZ)
-
-// Pipename used to capture audio stream from.
-// TODO(sergeyu): Pass this to AudioCapturerLinux constructor once we have
-// Linux-specific DesktopEnvironmentFactory
-base::LazyInstance<FilePath>::Leaky
- g_audio_pipe_name = LAZY_INSTANCE_INITIALIZER;
-
-const int IsPacketOfSilence(const std::string& data) {
- const int64* int_buf = reinterpret_cast<const int64*>(data.data());
- for (size_t i = 0; i < data.size() / sizeof(int64); i++) {
- if (int_buf[i] != 0)
- return false;
- }
- for (size_t i = data.size() - data.size() % sizeof(int64);
- i < data.size(); i++) {
- if (data.data()[i] != 0)
- return false;
- }
- return true;
-}
+const AudioPacket_SamplingRate kSamplingRate = AudioPacket::SAMPLING_RATE_48000;
+
+base::LazyInstance<scoped_refptr<AudioPipeReader> >::Leaky
+ g_pulseaudio_pipe_sink_reader = LAZY_INSTANCE_INITIALIZER;
} // namespace
-AudioCapturerLinux::AudioCapturerLinux(const FilePath& pipe_name) {
- pipe_fd_ = HANDLE_EINTR(open(
- pipe_name.value().c_str(), O_RDONLY | O_NONBLOCK));
- if (pipe_fd_ < 0) {
- LOG(ERROR) << "Failed to open " << pipe_name.value();
- return;
- }
-
- // Set buffer size for the pipe to the double of what's required for samples
- // of each capturing period.
- int pipe_buffer_size = 2 * kCapturingPeriodMs * kSamplingRate * kChannels *
- kBytesPerSample / base::Time::kMillisecondsPerSecond;
- int result = HANDLE_EINTR(fcntl(pipe_fd_, F_SETPIPE_SZ, pipe_buffer_size));
- if (result < 0) {
- PLOG(ERROR) << "fcntl";
- }
-
- WaitForPipeReadable();
+void AudioCapturerLinux::InitializePipeReader(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const FilePath& pipe_name) {
+ g_pulseaudio_pipe_sink_reader.Get() =
+ new AudioPipeReader(task_runner, pipe_name);
+}
+
+AudioCapturerLinux::AudioCapturerLinux(
+ scoped_refptr<AudioPipeReader> pipe_reader)
+ : pipe_reader_(pipe_reader) {
}
AudioCapturerLinux::~AudioCapturerLinux() {
}
bool AudioCapturerLinux::Start(const PacketCapturedCallback& callback) {
- if (pipe_fd_ < 0)
- return false;
-
callback_ = callback;
-
+ pipe_reader_->AddObserver(this);
return true;
}
void AudioCapturerLinux::Stop() {
+ pipe_reader_->RemoveObserver(this);
callback_.Reset();
}
@@ -98,74 +52,12 @@ bool AudioCapturerLinux::IsStarted() {
return !callback_.is_null();
}
-void AudioCapturerLinux::OnFileCanReadWithoutBlocking(int fd) {
- DCHECK_EQ(fd, pipe_fd_);
- StartTimer();
-}
-
-void AudioCapturerLinux::OnFileCanWriteWithoutBlocking(int fd) {
- NOTREACHED();
-}
-
-void AudioCapturerLinux::StartTimer() {
- started_time_ = base::TimeTicks::Now();
- last_capture_samples_ = 0;
- timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCapturingPeriodMs),
- this, &AudioCapturerLinux::DoCapture);
-}
-
-void AudioCapturerLinux::DoCapture() {
- DCHECK_GT(pipe_fd_, 0);
-
- // Calculate how much we need read from the pipe. Pulseaudio doesn't control
- // how much data it writes to the pipe, so we need to pace the stream, so
- // that we read the exact number of the samples per second we need.
- base::TimeDelta stream_position = base::TimeTicks::Now() - started_time_;
- int64 stream_position_samples = stream_position.InMilliseconds() *
- kSamplingRate / base::Time::kMillisecondsPerSecond;
- int64 samples_to_capture =
- stream_position_samples - last_capture_samples_;
- last_capture_samples_ = stream_position_samples;
- int64 read_size =
- samples_to_capture * kChannels * kBytesPerSample;
-
- std::string data = left_over_bytes_;
- int pos = data.size();
- left_over_bytes_.clear();
- data.resize(read_size);
-
- while (pos < read_size) {
- int read_result = HANDLE_EINTR(
- read(pipe_fd_, string_as_array(&data) + pos, read_size - pos));
- if (read_result >= 0) {
- pos += read_result;
- } else {
- if (errno != EWOULDBLOCK && errno != EAGAIN)
- PLOG(ERROR) << "read";
- break;
- }
- }
-
- if (pos == 0) {
- WaitForPipeReadable();
- return;
- }
-
- // Save any incomplete samples we've read for later. Each packet should
- // contain integer number of samples.
- int incomplete_samples_bytes = pos % (kChannels * kBytesPerSample);
- left_over_bytes_.assign(data, pos - incomplete_samples_bytes,
- incomplete_samples_bytes);
- data.resize(pos - incomplete_samples_bytes);
-
- if (callback_.is_null())
- return;
-
- if (IsPacketOfSilence(data))
- return;
+void AudioCapturerLinux::OnDataRead(
+ scoped_refptr<base::RefCountedString> data) {
+ DCHECK(!callback_.is_null());
scoped_ptr<AudioPacket> packet(new AudioPacket());
- packet->add_data(data);
+ packet->add_data(data->data());
packet->set_encoding(AudioPacket::ENCODING_RAW);
packet->set_sampling_rate(kSamplingRate);
packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2);
@@ -173,26 +65,16 @@ void AudioCapturerLinux::DoCapture() {
callback_.Run(packet.Pass());
}
-void AudioCapturerLinux::WaitForPipeReadable() {
- timer_.Stop();
- MessageLoopForIO::current()->WatchFileDescriptor(
- pipe_fd_, false, MessageLoopForIO::WATCH_READ,
- &file_descriptor_watcher_, this);
-}
-
-void AudioCapturerLinux::SetPipeName(const FilePath& pipe_name) {
- g_audio_pipe_name.Get() = pipe_name;
-}
-
bool AudioCapturer::IsSupported() {
- return !g_audio_pipe_name.Get().empty();
+ return g_pulseaudio_pipe_sink_reader.Get() != NULL;
}
scoped_ptr<AudioCapturer> AudioCapturer::Create() {
- FilePath path = g_audio_pipe_name.Get();
- if (path.empty())
+ scoped_refptr<AudioPipeReader> reader =
+ g_pulseaudio_pipe_sink_reader.Get();
+ if (!reader)
return scoped_ptr<AudioCapturer>();
- return scoped_ptr<AudioCapturer>(new AudioCapturerLinux(path));
+ return scoped_ptr<AudioCapturer>(new AudioCapturerLinux(reader));
}
} // namespace remoting
diff --git a/remoting/host/audio_capturer_linux.h b/remoting/host/audio_capturer_linux.h
index 8a825ff..1a9453c 100644
--- a/remoting/host/audio_capturer_linux.h
+++ b/remoting/host/audio_capturer_linux.h
@@ -5,24 +5,28 @@
#ifndef REMOTING_HOST_AUDIO_CAPTURER_LINUX_H_
#define REMOTING_HOST_AUDIO_CAPTURER_LINUX_H_
+#include "base/memory/ref_counted.h"
#include "remoting/host/audio_capturer.h"
-
-#include "base/message_loop.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "remoting/host/linux/audio_pipe_reader.h"
class FilePath;
namespace remoting {
+// Linux implementation of AudioCapturer interface which captures audio by
+// reading samples from a Pulseaudio "pipe" sink.
class AudioCapturerLinux : public AudioCapturer,
- public MessageLoopForIO::Watcher {
+ public AudioPipeReader::StreamObserver {
public:
- // Must be called to configure the capturer before the first instance is
- // created.
- static void SetPipeName(const FilePath& pipe_name);
-
- explicit AudioCapturerLinux(const FilePath& pipe_name);
+ // Must be called to configure the capturer before the first capturer instance
+ // is created. |task_runner| is an IO thread that is passed to AudioPipeReader
+ // to read from the pipe.
+ static void InitializePipeReader(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const FilePath& pipe_name);
+
+ explicit AudioCapturerLinux(
+ scoped_refptr<AudioPipeReader> pipe_reader);
virtual ~AudioCapturerLinux();
// AudioCapturer interface.
@@ -30,30 +34,13 @@ class AudioCapturerLinux : public AudioCapturer,
virtual void Stop() OVERRIDE;
virtual bool IsStarted() OVERRIDE;
- // MessageLoopForIO::Watcher interface.
- virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
- virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
+ // AudioPipeReader::StreamObserver interface.
+ virtual void OnDataRead(scoped_refptr<base::RefCountedString> data) OVERRIDE;
private:
- void StartTimer();
- void DoCapture();
- void WaitForPipeReadable();
-
- int pipe_fd_;
- base::RepeatingTimer<AudioCapturerLinux> timer_;
+ scoped_refptr<AudioPipeReader> pipe_reader_;
PacketCapturedCallback callback_;
- // Time when capturing was started.
- base::TimeTicks started_time_;
-
- // Stream position of the last capture.
- int64 last_capture_samples_;
-
- // Bytes left from the previous read.
- std::string left_over_bytes_;
-
- MessageLoopForIO::FileDescriptorWatcher file_descriptor_watcher_;
-
DISALLOW_COPY_AND_ASSIGN(AudioCapturerLinux);
};
diff --git a/remoting/host/linux/audio_pipe_reader.cc b/remoting/host/linux/audio_pipe_reader.cc
new file mode 100644
index 0000000..4bd3400
--- /dev/null
+++ b/remoting/host/linux/audio_pipe_reader.cc
@@ -0,0 +1,171 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/linux/audio_pipe_reader.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+
+namespace remoting {
+
+namespace {
+
+// PulseAudio's module-pipe-sink must be configured to use the following
+// parameters for the sink we read from.
+const int kSamplingRate = 48000;
+const int kChannels = 2;
+const int kBytesPerSample = 2;
+
+// Read data from the pipe every 40ms.
+const int kCapturingPeriodMs = 40;
+
+#if !defined(F_SETPIPE_SZ)
+// F_SETPIPE_SZ is supported only starting linux 2.6.35, but we want to be able
+// to compile this code on machines with older kernel.
+#define F_SETPIPE_SZ 1031
+#endif // defined(F_SETPIPE_SZ)
+
+const int IsPacketOfSilence(const std::string& data) {
+ const int64* int_buf = reinterpret_cast<const int64*>(data.data());
+ for (size_t i = 0; i < data.size() / sizeof(int64); i++) {
+ if (int_buf[i] != 0)
+ return false;
+ }
+ for (size_t i = data.size() - data.size() % sizeof(int64);
+ i < data.size(); i++) {
+ if (data.data()[i] != 0)
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+AudioPipeReader::AudioPipeReader(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const FilePath& pipe_name)
+ : task_runner_(task_runner),
+ observers_(new ObserverListThreadSafe<StreamObserver>()) {
+ task_runner_->PostTask(FROM_HERE, base::Bind(
+ &AudioPipeReader::StartOnAudioThread, this, pipe_name));
+}
+
+void AudioPipeReader::StartOnAudioThread(const FilePath& pipe_name) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ pipe_fd_ = HANDLE_EINTR(open(
+ pipe_name.value().c_str(), O_RDONLY | O_NONBLOCK));
+ if (pipe_fd_ < 0) {
+ LOG(ERROR) << "Failed to open " << pipe_name.value();
+ return;
+ }
+
+ // Set buffer size for the pipe to the double of what's required for samples
+ // of each capturing period.
+ int pipe_buffer_size = 2 * kCapturingPeriodMs * kSamplingRate * kChannels *
+ kBytesPerSample / base::Time::kMillisecondsPerSecond;
+ int result = HANDLE_EINTR(fcntl(pipe_fd_, F_SETPIPE_SZ, pipe_buffer_size));
+ if (result < 0) {
+ PLOG(ERROR) << "fcntl";
+ }
+
+ WaitForPipeReadable();
+}
+
+AudioPipeReader::~AudioPipeReader() {
+}
+
+void AudioPipeReader::AddObserver(StreamObserver* observer) {
+ observers_->AddObserver(observer);
+}
+void AudioPipeReader::RemoveObserver(StreamObserver* observer) {
+ observers_->RemoveObserver(observer);
+}
+
+void AudioPipeReader::OnFileCanReadWithoutBlocking(int fd) {
+ DCHECK_EQ(fd, pipe_fd_);
+ StartTimer();
+}
+
+void AudioPipeReader::OnFileCanWriteWithoutBlocking(int fd) {
+ NOTREACHED();
+}
+
+void AudioPipeReader::StartTimer() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ started_time_ = base::TimeTicks::Now();
+ last_capture_samples_ = 0;
+ timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCapturingPeriodMs),
+ this, &AudioPipeReader::DoCapture);
+}
+
+void AudioPipeReader::DoCapture() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK_GT(pipe_fd_, 0);
+
+ // Calculate how much we need read from the pipe. Pulseaudio doesn't control
+ // how much data it writes to the pipe, so we need to pace the stream, so
+ // that we read the exact number of the samples per second we need.
+ base::TimeDelta stream_position = base::TimeTicks::Now() - started_time_;
+ int64 stream_position_samples = stream_position.InMilliseconds() *
+ kSamplingRate / base::Time::kMillisecondsPerSecond;
+ int64 samples_to_capture =
+ stream_position_samples - last_capture_samples_;
+ last_capture_samples_ = stream_position_samples;
+ int64 read_size =
+ samples_to_capture * kChannels * kBytesPerSample;
+
+ std::string data = left_over_bytes_;
+ int pos = data.size();
+ left_over_bytes_.clear();
+ data.resize(read_size);
+
+ while (pos < read_size) {
+ int read_result = HANDLE_EINTR(
+ read(pipe_fd_, string_as_array(&data) + pos, read_size - pos));
+ if (read_result >= 0) {
+ pos += read_result;
+ } else {
+ if (errno != EWOULDBLOCK && errno != EAGAIN)
+ PLOG(ERROR) << "read";
+ break;
+ }
+ }
+
+ if (pos == 0) {
+ WaitForPipeReadable();
+ return;
+ }
+
+ // Save any incomplete samples we've read for later. Each packet should
+ // contain integer number of samples.
+ int incomplete_samples_bytes = pos % (kChannels * kBytesPerSample);
+ left_over_bytes_.assign(data, pos - incomplete_samples_bytes,
+ incomplete_samples_bytes);
+ data.resize(pos - incomplete_samples_bytes);
+
+ if (IsPacketOfSilence(data))
+ return;
+
+ // Dispatch asynchronous notification to the stream observers.
+ scoped_refptr<base::RefCountedString> data_ref =
+ base::RefCountedString::TakeString(&data);
+ observers_->Notify(&StreamObserver::OnDataRead, data_ref);
+}
+
+void AudioPipeReader::WaitForPipeReadable() {
+ timer_.Stop();
+ MessageLoopForIO::current()->WatchFileDescriptor(
+ pipe_fd_, false, MessageLoopForIO::WATCH_READ,
+ &file_descriptor_watcher_, this);
+}
+
+} // namespace remoting
diff --git a/remoting/host/linux/audio_pipe_reader.h b/remoting/host/linux/audio_pipe_reader.h
new file mode 100644
index 0000000..e8b1adc
--- /dev/null
+++ b/remoting/host/linux/audio_pipe_reader.h
@@ -0,0 +1,78 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_LINUX_AUDIO_PIPE_READER_H_
+#define REMOTING_HOST_LINUX_AUDIO_PIPE_READER_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/message_loop.h"
+#include "base/observer_list_threadsafe.h"
+#include "base/time.h"
+#include "base/timer.h"
+
+class FilePath;
+
+namespace remoting {
+
+// AudioPipeReader class reads from a named pipe to which an audio server (e.g.
+// pulseaudio) writes the sound that's being played back and then sends data to
+// all registered observers.
+class AudioPipeReader
+ : public base::RefCountedThreadSafe<AudioPipeReader>,
+ public MessageLoopForIO::Watcher {
+ public:
+ class StreamObserver {
+ public:
+ virtual void OnDataRead(scoped_refptr<base::RefCountedString> data) = 0;
+ };
+
+ // |task_runner| defines the IO thread on which the object will be reading
+ // data from the pipe.
+ AudioPipeReader(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const FilePath& pipe_name);
+
+ // Register or unregister an observer. Each observer receives data on the
+ // thread on which it was registered and guaranteed not to be called after
+ // RemoveObserver().
+ void AddObserver(StreamObserver* observer);
+ void RemoveObserver(StreamObserver* observer);
+
+ // MessageLoopForIO::Watcher interface.
+ virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
+ virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
+
+ private:
+ friend class base::RefCountedThreadSafe<AudioPipeReader>;
+ virtual ~AudioPipeReader();
+
+ void StartOnAudioThread(const FilePath& pipe_name);
+ void StartTimer();
+ void DoCapture();
+ void WaitForPipeReadable();
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ int pipe_fd_;
+ base::RepeatingTimer<AudioPipeReader> timer_;
+ scoped_refptr<ObserverListThreadSafe<StreamObserver> > observers_;
+
+ // Time when capturing was started.
+ base::TimeTicks started_time_;
+
+ // Stream position of the last capture.
+ int64 last_capture_samples_;
+
+ // Bytes left from the previous read.
+ std::string left_over_bytes_;
+
+ MessageLoopForIO::FileDescriptorWatcher file_descriptor_watcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioPipeReader);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_LINUX_AUDIO_PIPE_READER_H_
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index 4e08d0c..8dd59e8 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -475,6 +475,21 @@ void HostProcess::StartHostProcess() {
return;
}
+#if defined(OS_LINUX)
+ // TODO(sergeyu): Pass configuration parameters to the Linux-specific version
+ // of DesktopEnvironmentFactory when we have it.
+ remoting::VideoFrameCapturer::EnableXDamage(true);
+
+ // If an audio pipe is specific on the command-line then initialize
+ // AudioCapturerLinux to capture from it.
+ FilePath audio_pipe_name = CommandLine::ForCurrentProcess()->
+ GetSwitchValuePath(kAudioPipeSwitchName);
+ if (!audio_pipe_name.empty()) {
+ remoting::AudioCapturerLinux::InitializePipeReader(
+ context_->audio_task_runner(), audio_pipe_name);
+ }
+#endif // defined(OS_LINUX)
+
// Create a desktop environment factory appropriate to the build type &
// platform.
#if defined(OS_WIN)
@@ -947,14 +962,6 @@ int main(int argc, char** argv) {
new remoting::AutoThreadTaskRunner(message_loop.message_loop_proxy(),
quit_message_loop)));
-#if defined(OS_LINUX)
- // TODO(sergeyu): Pass configuration parameters to the Linux-specific version
- // of DesktopEnvironmentFactory when we have it.
- remoting::VideoFrameCapturer::EnableXDamage(true);
- remoting::AudioCapturerLinux::SetPipeName(CommandLine::ForCurrentProcess()->
- GetSwitchValuePath(kAudioPipeSwitchName));
-#endif // defined(OS_LINUX)
-
if (!context->Start())
return remoting::kInitializationFailed;
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 19c0dc8..dc25e75 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -1602,6 +1602,8 @@
'host/it2me_host_user_interface.h',
'host/json_host_config.cc',
'host/json_host_config.h',
+ 'host/linux/audio_pipe_reader.cc',
+ 'host/linux/audio_pipe_reader.h',
'host/linux/x11_util.cc',
'host/linux/x11_util.h',
'host/linux/x_server_clipboard.cc',
diff --git a/remoting/tools/me2me_virtual_host.py b/remoting/tools/me2me_virtual_host.py
index 55fb5e4..2275781 100755
--- a/remoting/tools/me2me_virtual_host.py
+++ b/remoting/tools/me2me_virtual_host.py
@@ -233,7 +233,7 @@ class Desktop:
pulse_config.write("load-module module-native-protocol-unix\n")
pulse_config.write(
("load-module module-pipe-sink sink_name=%s file=\"%s\" " +
- "rate=44100 channels=2 format=s16le\n") %
+ "rate=48000 channels=2 format=s16le\n") %
(sink_name, pipe_name))
pulse_config.close()
except IOError, e: