1 // Copyright 2014 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.
5 #include "chromeos/dbus/bluetooth_media_client.h"
8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/observer_list.h"
12 #include "dbus/message.h"
13 #include "dbus/object_manager.h"
14 #include "dbus/object_proxy.h"
15 #include "third_party/cros_system_api/dbus/service_constants.h"
19 // Since there is no property associated with Media objects, an empty callback
21 void DoNothing(const std::string
& property_name
) {
24 // TODO(mcchou): Add these service constants into dbus/service_constants.h
26 const char kBluetoothMediaInterface
[] = "org.bluez.Media1";
28 // Method names supported by Media Interface.
29 const char kRegisterEndpoint
[] = "RegisterEndpoint";
30 const char kUnregisterEndpoint
[] = "UnregisterEndpoint";
32 // The set of properties which are used to register a media endpoint.
33 const char kUUIDEndpointProperty
[] = "UUID";
34 const char kCodecEndpointProperty
[] = "Codec";
35 const char kCapabilitiesEndpointProperty
[] = "Capabilities";
42 const char BluetoothMediaClient::kNoResponseError
[] =
43 "org.chromium.Error.NoResponse";
46 const char BluetoothMediaClient::kBluetoothAudioSinkUUID
[] =
47 "0000110b-0000-1000-8000-00805f9b34fb";
49 BluetoothMediaClient::EndpointProperties::EndpointProperties() : codec(0x00) {
52 BluetoothMediaClient::EndpointProperties::~EndpointProperties() {
55 class BluetoothMediaClientImpl
56 : public BluetoothMediaClient
, dbus::ObjectManager::Interface
{
58 BluetoothMediaClientImpl()
59 : object_manager_(nullptr), weak_ptr_factory_(this) {}
61 ~BluetoothMediaClientImpl() override
{
62 object_manager_
->UnregisterInterface(kBluetoothMediaInterface
);
65 // dbus::ObjectManager::Interface overrides.
67 dbus::PropertySet
* CreateProperties(
68 dbus::ObjectProxy
* object_proxy
,
69 const dbus::ObjectPath
& object_path
,
70 const std::string
& interface_name
) override
{
71 return new dbus::PropertySet(object_proxy
, interface_name
,
72 base::Bind(&DoNothing
));
75 void ObjectAdded(const dbus::ObjectPath
& object_path
,
76 const std::string
& interface_name
) override
{
77 VLOG(1) << "Remote Media added: " << object_path
.value();
78 FOR_EACH_OBSERVER(BluetoothMediaClient::Observer
, observers_
,
79 MediaAdded(object_path
));
82 void ObjectRemoved(const dbus::ObjectPath
& object_path
,
83 const std::string
& interface_name
) override
{
84 VLOG(1) << "Remote Media removed: " << object_path
.value();
85 FOR_EACH_OBSERVER(BluetoothMediaClient::Observer
, observers_
,
86 MediaRemoved(object_path
));
89 // BluetoothMediaClient overrides.
91 void AddObserver(BluetoothMediaClient::Observer
* observer
) override
{
93 observers_
.AddObserver(observer
);
96 void RemoveObserver(BluetoothMediaClient::Observer
* observer
) override
{
98 observers_
.RemoveObserver(observer
);
101 void RegisterEndpoint(const dbus::ObjectPath
& object_path
,
102 const dbus::ObjectPath
& endpoint_path
,
103 const EndpointProperties
& properties
,
104 const base::Closure
& callback
,
105 const ErrorCallback
& error_callback
) override
{
106 dbus::MethodCall
method_call(kBluetoothMediaInterface
, kRegisterEndpoint
);
108 dbus::MessageWriter
writer(&method_call
);
109 dbus::MessageWriter
array_writer(nullptr);
110 dbus::MessageWriter
dict_entry_writer(nullptr);
112 // Send the path to the endpoint.
113 writer
.AppendObjectPath(endpoint_path
);
115 writer
.OpenArray("{sv}", &array_writer
);
118 array_writer
.OpenDictEntry(&dict_entry_writer
);
119 dict_entry_writer
.AppendString(kUUIDEndpointProperty
);
120 dict_entry_writer
.AppendVariantOfString(properties
.uuid
);
121 array_writer
.CloseContainer(&dict_entry_writer
);
124 array_writer
.OpenDictEntry(&dict_entry_writer
);
125 dict_entry_writer
.AppendString(kCodecEndpointProperty
);
126 dict_entry_writer
.AppendVariantOfByte(properties
.codec
);
127 array_writer
.CloseContainer(&dict_entry_writer
);
129 // Send Capabilities.
130 dbus::MessageWriter
variant_writer(nullptr);
131 array_writer
.OpenDictEntry(&dict_entry_writer
);
132 dict_entry_writer
.AppendString(kCapabilitiesEndpointProperty
);
133 dict_entry_writer
.OpenVariant("ay", &variant_writer
);
134 variant_writer
.AppendArrayOfBytes(properties
.capabilities
.data(),
135 properties
.capabilities
.size());
136 dict_entry_writer
.CloseContainer(&variant_writer
);
137 array_writer
.CloseContainer(&dict_entry_writer
);
139 writer
.CloseContainer(&array_writer
);
141 // Get Object Proxy based on the service name and the service path and call
142 // RegisterEndpoint medthod.
143 scoped_refptr
<dbus::ObjectProxy
> object_proxy(
144 object_manager_
->GetObjectProxy(object_path
));
145 object_proxy
->CallMethodWithErrorCallback(
147 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
148 base::Bind(&BluetoothMediaClientImpl::OnSuccess
,
149 weak_ptr_factory_
.GetWeakPtr(), callback
),
150 base::Bind(&BluetoothMediaClientImpl::OnError
,
151 weak_ptr_factory_
.GetWeakPtr(), error_callback
));
154 void UnregisterEndpoint(const dbus::ObjectPath
& object_path
,
155 const dbus::ObjectPath
& endpoint_path
,
156 const base::Closure
& callback
,
157 const ErrorCallback
& error_callback
) override
{
158 dbus::MethodCall
method_call(kBluetoothMediaInterface
, kUnregisterEndpoint
);
160 // Send the path to the endpoint.
161 dbus::MessageWriter
writer(&method_call
);
162 writer
.AppendObjectPath(endpoint_path
);
164 // Get Object Proxy based on the service name and the service path and call
165 // RegisterEndpoint medthod.
166 scoped_refptr
<dbus::ObjectProxy
> object_proxy(
167 object_manager_
->GetObjectProxy(object_path
));
168 object_proxy
->CallMethodWithErrorCallback(
170 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
171 base::Bind(&BluetoothMediaClientImpl::OnSuccess
,
172 weak_ptr_factory_
.GetWeakPtr(), callback
),
173 base::Bind(&BluetoothMediaClientImpl::OnError
,
174 weak_ptr_factory_
.GetWeakPtr(), error_callback
));
178 void Init(dbus::Bus
* bus
) override
{
180 object_manager_
= bus
->GetObjectManager(
181 bluetooth_object_manager::kBluetoothObjectManagerServiceName
,
183 bluetooth_object_manager::kBluetoothObjectManagerServicePath
));
184 object_manager_
->RegisterInterface(kBluetoothMediaInterface
, this);
188 // Called when a response for successful method call is received.
189 void OnSuccess(const base::Closure
& callback
,
190 dbus::Response
* response
) {
195 // Called when a response for a failed method call is received.
196 void OnError(const ErrorCallback
& error_callback
,
197 dbus::ErrorResponse
* response
) {
198 // Error response has an optional error message argument.
199 std::string error_name
;
200 std::string error_message
;
202 dbus::MessageReader
reader(response
);
203 error_name
= response
->GetErrorName();
204 reader
.PopString(&error_message
);
206 error_name
= kNoResponseError
;
208 error_callback
.Run(error_name
, error_message
);
211 dbus::ObjectManager
* object_manager_
;
213 // List of observers interested in event notifications from us.
214 ObserverList
<BluetoothMediaClient::Observer
> observers_
;
216 base::WeakPtrFactory
<BluetoothMediaClientImpl
> weak_ptr_factory_
;
218 DISALLOW_COPY_AND_ASSIGN(BluetoothMediaClientImpl
);
221 BluetoothMediaClient::BluetoothMediaClient() {
224 BluetoothMediaClient::~BluetoothMediaClient() {
227 BluetoothMediaClient
* BluetoothMediaClient::Create() {
228 return new BluetoothMediaClientImpl();
231 } // namespace chromeos