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#include "remoting/host/audio_capturer_linux.h"
6
7#include "base/files/file_path.h"
8#include "base/lazy_instance.h"
9#include "base/logging.h"
10#include "remoting/proto/audio.pb.h"
11
12namespace remoting {
13
14namespace {
15
16base::LazyInstance<scoped_refptr<AudioPipeReader> >::Leaky
17    g_pulseaudio_pipe_sink_reader = LAZY_INSTANCE_INITIALIZER;
18
19}  // namespace
20
21// TODO(wez): Remove this and have the DesktopEnvironmentFactory own the
22// AudioPipeReader rather than having it process-global.
23// See crbug.com/161373 and crbug.com/104544.
24void AudioCapturerLinux::InitializePipeReader(
25    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
26    const base::FilePath& pipe_name) {
27  scoped_refptr<AudioPipeReader> pipe_reader;
28  if (!pipe_name.empty())
29    pipe_reader = AudioPipeReader::Create(task_runner, pipe_name);
30  g_pulseaudio_pipe_sink_reader.Get() = pipe_reader;
31}
32
33AudioCapturerLinux::AudioCapturerLinux(
34    scoped_refptr<AudioPipeReader> pipe_reader)
35    : pipe_reader_(pipe_reader),
36      silence_detector_(0) {
37}
38
39AudioCapturerLinux::~AudioCapturerLinux() {
40}
41
42bool AudioCapturerLinux::Start(const PacketCapturedCallback& callback) {
43  callback_ = callback;
44  silence_detector_.Reset(AudioPipeReader::kSamplingRate,
45                          AudioPipeReader::kChannels);
46  pipe_reader_->AddObserver(this);
47  return true;
48}
49
50void AudioCapturerLinux::Stop() {
51  pipe_reader_->RemoveObserver(this);
52  callback_.Reset();
53}
54
55bool AudioCapturerLinux::IsStarted() {
56  return !callback_.is_null();
57}
58
59void AudioCapturerLinux::OnDataRead(
60    scoped_refptr<base::RefCountedString> data) {
61  DCHECK(!callback_.is_null());
62
63  if (silence_detector_.IsSilence(
64          reinterpret_cast<const int16*>(data->data().data()),
65          data->data().size() / sizeof(int16))) {
66    return;
67  }
68
69  scoped_ptr<AudioPacket> packet(new AudioPacket());
70  packet->add_data(data->data());
71  packet->set_encoding(AudioPacket::ENCODING_RAW);
72  packet->set_sampling_rate(AudioPipeReader::kSamplingRate);
73  packet->set_bytes_per_sample(AudioPipeReader::kBytesPerSample);
74  packet->set_channels(AudioPipeReader::kChannels);
75  callback_.Run(packet.Pass());
76}
77
78bool AudioCapturer::IsSupported() {
79  return g_pulseaudio_pipe_sink_reader.Get().get() != NULL;
80}
81
82scoped_ptr<AudioCapturer> AudioCapturer::Create() {
83  scoped_refptr<AudioPipeReader> reader =
84      g_pulseaudio_pipe_sink_reader.Get();
85  if (!reader.get())
86    return scoped_ptr<AudioCapturer>();
87  return scoped_ptr<AudioCapturer>(new AudioCapturerLinux(reader));
88}
89
90}  // namespace remoting
91