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 VLOG(1) << "RegisterEndpoint - endpoint: " << endpoint_path
.value();
108 dbus::MethodCall
method_call(kBluetoothMediaInterface
, kRegisterEndpoint
);
110 dbus::MessageWriter
writer(&method_call
);
111 dbus::MessageWriter
array_writer(nullptr);
112 dbus::MessageWriter
dict_entry_writer(nullptr);
114 // Send the path to the endpoint.
115 writer
.AppendObjectPath(endpoint_path
);
117 writer
.OpenArray("{sv}", &array_writer
);
120 array_writer
.OpenDictEntry(&dict_entry_writer
);
121 dict_entry_writer
.AppendString(kUUIDEndpointProperty
);
122 dict_entry_writer
.AppendVariantOfString(properties
.uuid
);
123 array_writer
.CloseContainer(&dict_entry_writer
);
126 array_writer
.OpenDictEntry(&dict_entry_writer
);
127 dict_entry_writer
.AppendString(kCodecEndpointProperty
);
128 dict_entry_writer
.AppendVariantOfByte(properties
.codec
);
129 array_writer
.CloseContainer(&dict_entry_writer
);
131 // Send Capabilities.
132 dbus::MessageWriter
variant_writer(nullptr);
133 array_writer
.OpenDictEntry(&dict_entry_writer
);
134 dict_entry_writer
.AppendString(kCapabilitiesEndpointProperty
);
135 dict_entry_writer
.OpenVariant("ay", &variant_writer
);
136 variant_writer
.AppendArrayOfBytes(properties
.capabilities
.data(),
137 properties
.capabilities
.size());
138 dict_entry_writer
.CloseContainer(&variant_writer
);
139 array_writer
.CloseContainer(&dict_entry_writer
);
141 writer
.CloseContainer(&array_writer
);
143 // Get Object Proxy based on the service name and the service path and call
144 // RegisterEndpoint medthod.
145 scoped_refptr
<dbus::ObjectProxy
> object_proxy(
146 object_manager_
->GetObjectProxy(object_path
));
147 object_proxy
->CallMethodWithErrorCallback(
149 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
150 base::Bind(&BluetoothMediaClientImpl::OnSuccess
,
151 weak_ptr_factory_
.GetWeakPtr(), callback
),
152 base::Bind(&BluetoothMediaClientImpl::OnError
,
153 weak_ptr_factory_
.GetWeakPtr(), error_callback
));
156 void UnregisterEndpoint(const dbus::ObjectPath
& object_path
,
157 const dbus::ObjectPath
& endpoint_path
,
158 const base::Closure
& callback
,
159 const ErrorCallback
& error_callback
) override
{
160 VLOG(1) << "UnregisterEndpoint - endpoint: " << endpoint_path
.value();
162 dbus::MethodCall
method_call(kBluetoothMediaInterface
, kUnregisterEndpoint
);
164 // Send the path to the endpoint.
165 dbus::MessageWriter
writer(&method_call
);
166 writer
.AppendObjectPath(endpoint_path
);
168 // Get Object Proxy based on the service name and the service path and call
169 // RegisterEndpoint medthod.
170 scoped_refptr
<dbus::ObjectProxy
> object_proxy(
171 object_manager_
->GetObjectProxy(object_path
));
172 object_proxy
->CallMethodWithErrorCallback(
174 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
175 base::Bind(&BluetoothMediaClientImpl::OnSuccess
,
176 weak_ptr_factory_
.GetWeakPtr(), callback
),
177 base::Bind(&BluetoothMediaClientImpl::OnError
,
178 weak_ptr_factory_
.GetWeakPtr(), error_callback
));
182 void Init(dbus::Bus
* bus
) override
{
184 object_manager_
= bus
->GetObjectManager(
185 bluetooth_object_manager::kBluetoothObjectManagerServiceName
,
187 bluetooth_object_manager::kBluetoothObjectManagerServicePath
));
188 object_manager_
->RegisterInterface(kBluetoothMediaInterface
, this);
192 // Called when a response for successful method call is received.
193 void OnSuccess(const base::Closure
& callback
,
194 dbus::Response
* response
) {
199 // Called when a response for a failed method call is received.
200 void OnError(const ErrorCallback
& error_callback
,
201 dbus::ErrorResponse
* response
) {
202 // Error response has an optional error message argument.
203 std::string error_name
;
204 std::string error_message
;
206 dbus::MessageReader
reader(response
);
207 error_name
= response
->GetErrorName();
208 reader
.PopString(&error_message
);
210 error_name
= kNoResponseError
;
212 error_callback
.Run(error_name
, error_message
);
215 dbus::ObjectManager
* object_manager_
;
217 // List of observers interested in event notifications from us.
218 ObserverList
<BluetoothMediaClient::Observer
> observers_
;
220 base::WeakPtrFactory
<BluetoothMediaClientImpl
> weak_ptr_factory_
;
222 DISALLOW_COPY_AND_ASSIGN(BluetoothMediaClientImpl
);
225 BluetoothMediaClient::BluetoothMediaClient() {
228 BluetoothMediaClient::~BluetoothMediaClient() {
231 BluetoothMediaClient
* BluetoothMediaClient::Create() {
232 return new BluetoothMediaClientImpl();
235 } // namespace chromeos