cras_audio_client.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/cras_audio_client.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/format_macros.h"
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/stringprintf.h"
10558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chromeos/dbus/cras_audio_client_stub_impl.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/bus.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/message.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/object_path.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/object_proxy.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos {
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Error name if cras dbus call fails with empty ErrorResponse.
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const char kNoResponseError[] =
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    "org.chromium.cras.Error.NoResponse";
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The CrasAudioClient implementation used in production.
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class CrasAudioClientImpl : public CrasAudioClient {
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CrasAudioClientImpl() : cras_proxy_(NULL), weak_ptr_factory_(this) {}
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~CrasAudioClientImpl() {
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // CrasAudioClient overrides:
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    observers_.AddObserver(observer);
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    observers_.RemoveObserver(observer);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return observers_.HasObserver(observer);
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void GetVolumeState(const GetVolumeStateCallback& callback) OVERRIDE {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 cras::kGetVolumeState);
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_proxy_->CallMethod(
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &method_call,
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&CrasAudioClientImpl::OnGetVolumeState,
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(), callback));
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void GetNodes(const GetNodesCallback& callback,
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                        const ErrorCallback& error_callback) OVERRIDE {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 cras::kGetNodes);
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    cras_proxy_->CallMethodWithErrorCallback(
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &method_call,
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&CrasAudioClientImpl::OnGetNodes,
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(), callback),
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        base::Bind(&CrasAudioClientImpl::OnError,
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(), error_callback));
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void SetOutputNodeVolume(uint64 node_id, int32 volume) OVERRIDE {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                 cras::kSetOutputNodeVolume);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    writer.AppendUint64(node_id);
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    writer.AppendInt32(volume);
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_proxy_->CallMethod(
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &method_call,
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void SetOutputUserMute(bool mute_on) OVERRIDE {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                 cras::kSetOutputUserMute);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    writer.AppendBool(mute_on);
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_proxy_->CallMethod(
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &method_call,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void SetInputNodeGain(uint64 node_id, int32 input_gain) OVERRIDE {
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                 cras::kSetInputNodeGain);
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    writer.AppendUint64(node_id);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    writer.AppendInt32(input_gain);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_proxy_->CallMethod(
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &method_call,
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetInputMute(bool mute_on) OVERRIDE {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 cras::kSetInputMute);
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    writer.AppendBool(mute_on);
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_proxy_->CallMethod(
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &method_call,
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetActiveOutputNode(uint64 node_id) OVERRIDE {
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 cras::kSetActiveOutputNode);
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    writer.AppendUint64(node_id);
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_proxy_->CallMethod(
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &method_call,
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetActiveInputNode(uint64 node_id) OVERRIDE {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 cras::kSetActiveInputNode);
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    writer.AppendUint64(node_id);
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_proxy_->CallMethod(
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &method_call,
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void AddActiveInputNode(uint64 node_id) OVERRIDE {
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 cras::kAddActiveInputNode);
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    writer.AppendUint64(node_id);
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cras_proxy_->CallMethod(
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        &method_call,
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void RemoveActiveInputNode(uint64 node_id) OVERRIDE {
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    dbus::MethodCall method_call(cras::kCrasControlInterface,
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 cras::kRemoveActiveInputNode);
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    writer.AppendUint64(node_id);
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cras_proxy_->CallMethod(
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        &method_call,
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
157424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) protected:
158424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual void Init(dbus::Bus* bus) OVERRIDE {
159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    cras_proxy_ = bus->GetObjectProxy(cras::kCrasServiceName,
160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                      dbus::ObjectPath(cras::kCrasServicePath));
161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Monitor NameOwnerChanged signal.
163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    cras_proxy_->SetNameOwnerChangedCallback(
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::NameOwnerChangedReceived,
165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Monitor the D-Bus signal for output mute change.
168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    cras_proxy_->ConnectToSignal(
169424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kCrasControlInterface,
170424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kOutputMuteChanged,
171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::OutputMuteChangedReceived,
172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
173424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::SignalConnected,
174424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
176424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Monitor the D-Bus signal for input mute change.
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    cras_proxy_->ConnectToSignal(
178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kCrasControlInterface,
179424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kInputMuteChanged,
180424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::InputMuteChangedReceived,
181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
182424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::SignalConnected,
183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Monitor the D-Bus signal for nodes change.
186424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    cras_proxy_->ConnectToSignal(
187424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kCrasControlInterface,
188424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kNodesChanged,
189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::NodesChangedReceived,
190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
191424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::SignalConnected,
192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
193424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Monitor the D-Bus signal for active output node change.
195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    cras_proxy_->ConnectToSignal(
196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kCrasControlInterface,
197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kActiveOutputNodeChanged,
198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::ActiveOutputNodeChangedReceived,
199424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
200424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::SignalConnected,
201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Monitor the D-Bus signal for active input node change.
204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    cras_proxy_->ConnectToSignal(
205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kCrasControlInterface,
206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        cras::kActiveInputNodeChanged,
207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::ActiveInputNodeChangedReceived,
208424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&CrasAudioClientImpl::SignalConnected,
210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called when the cras signal is initially connected.
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void SignalConnected(const std::string& interface_name,
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       const std::string& signal_name,
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       bool success) {
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG_IF(ERROR, !success)
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        << "Failed to connect to cras signal:" << signal_name;
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void NameOwnerChangedReceived(const std::string& old_owner,
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                const std::string& new_owner) {
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, AudioClientRestarted());
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called when a OutputMuteChanged signal is received.
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OutputMuteChangedReceived(dbus::Signal* signal) {
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Chrome should always call SetOutputUserMute api to set the output
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // mute state and monitor user_mute state from OutputMuteChanged signal.
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(signal);
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    bool system_mute, user_mute;
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!reader.PopBool(&system_mute) || !reader.PopBool(&user_mute)) {
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Error reading signal from cras:"
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << signal->ToString();
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    FOR_EACH_OBSERVER(Observer, observers_, OutputMuteChanged(user_mute));
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called when a InputMuteChanged signal is received.
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void InputMuteChangedReceived(dbus::Signal* signal) {
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(signal);
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool mute;
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopBool(&mute)) {
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Error reading signal from cras:"
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << signal->ToString();
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, InputMuteChanged(mute));
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void NodesChangedReceived(dbus::Signal* signal) {
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, NodesChanged());
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void ActiveOutputNodeChangedReceived(dbus::Signal* signal) {
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(signal);
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint64 node_id;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopUint64(&node_id)) {
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Error reading signal from cras:"
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << signal->ToString();
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, ActiveOutputNodeChanged(node_id));
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void ActiveInputNodeChangedReceived(dbus::Signal* signal) {
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(signal);
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint64 node_id;
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopUint64(&node_id)) {
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Error reading signal from cras:"
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << signal->ToString();
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, ActiveInputNodeChanged(node_id));
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnGetVolumeState(const GetVolumeStateCallback& callback,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        dbus::Response* response) {
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success = true;
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VolumeState volume_state;
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (response) {
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dbus::MessageReader reader(response);
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!reader.PopInt32(&volume_state.output_volume) ||
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          !reader.PopBool(&volume_state.output_system_mute) ||
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          !reader.PopInt32(&volume_state.input_gain) ||
284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          !reader.PopBool(&volume_state.input_mute) ||
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          !reader.PopBool(&volume_state.output_user_mute)) {
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        success = false;
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        LOG(ERROR) << "Error reading response from cras: "
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   << response->ToString();
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      success = false;
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Error calling " << cras::kGetVolumeState;
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(volume_state, success);
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnGetNodes(const GetNodesCallback& callback,
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  dbus::Response* response) {
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success = true;
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AudioNodeList node_list;
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (response) {
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dbus::MessageReader response_reader(response);
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dbus::MessageReader array_reader(response);
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      while (response_reader.HasMoreData()) {
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!response_reader.PopArray(&array_reader)) {
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          success = false;
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          LOG(ERROR) << "Error reading response from cras: "
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     << response->ToString();
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          break;
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        AudioNode node;
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!GetAudioNode(response, &array_reader, &node)) {
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          success = false;
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          LOG(WARNING) << "Error reading audio node data from cras: "
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       << response->ToString();
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          break;
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // Filter out the "UNKNOWN" type of audio devices.
3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (node.type != "UNKNOWN")
3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          node_list.push_back(node);
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
3247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (node_list.empty())
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return;
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(node_list, success);
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void OnError(const ErrorCallback& error_callback,
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)               dbus::ErrorResponse* response) {
334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Error response has optional error message argument.
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    std::string error_name;
336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    std::string error_message;
337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (response) {
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      dbus::MessageReader reader(response);
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      error_name = response->GetErrorName();
340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      reader.PopString(&error_message);
341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    } else {
342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      error_name = kNoResponseError;
343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      error_message = "";
344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    error_callback.Run(error_name, error_message);
346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
347d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool GetAudioNode(dbus::Response* response,
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    dbus::MessageReader* array_reader,
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    AudioNode *node) {
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (array_reader->HasMoreData()) {
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dbus::MessageReader dict_entry_reader(response);
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dbus::MessageReader value_reader(response);
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string key;
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!array_reader->PopDictEntry(&dict_entry_reader) ||
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          !dict_entry_reader.PopString(&key) ||
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          !dict_entry_reader.PopVariant(&value_reader)) {
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         return false;
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (key == cras::kIsInputProperty) {
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!value_reader.PopBool(&node->is_input))
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return false;
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (key == cras::kIdProperty) {
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!value_reader.PopUint64(&node->id))
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return false;
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (key == cras::kDeviceNameProperty) {
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!value_reader.PopString(&node->device_name))
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return false;
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (key == cras::kTypeProperty) {
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!value_reader.PopString(&node->type))
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return false;
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (key == cras::kNameProperty) {
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!value_reader.PopString(&node->name))
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return false;
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (key == cras::kActiveProperty) {
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!value_reader.PopBool(&node->active))
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return false;
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (key == cras::kPluggedTimeProperty) {
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!value_reader.PopUint64(&node->plugged_time))
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return false;
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dbus::ObjectProxy* cras_proxy_;
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ObserverList<Observer> observers_;
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WeakPtrFactory<CrasAudioClientImpl> weak_ptr_factory_;
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CrasAudioClientImpl);
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CrasAudioClient::Observer::~Observer() {
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasAudioClient::Observer::AudioClientRestarted() {
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasAudioClient::Observer::OutputMuteChanged(bool mute_on) {
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasAudioClient::Observer::InputMuteChanged(bool mute_on) {
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasAudioClient::Observer::NodesChanged() {
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasAudioClient::Observer::ActiveOutputNodeChanged(uint64 node_id){
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasAudioClient::Observer::ActiveInputNodeChanged(uint64 node_id) {
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CrasAudioClient::CrasAudioClient() {
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CrasAudioClient::~CrasAudioClient() {
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)CrasAudioClient* CrasAudioClient::Create() {
427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return new CrasAudioClientImpl();
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace chromeos
431