1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "bluetooth_a2dp_src.h"
16 #include "bluetooth_errorcode.h"
17 #include "napi_bluetooth_profile.h"
18 #include "napi_bluetooth_a2dp_src.h"
19 #include "napi_bluetooth_event.h"
20 #include "napi_bluetooth_error.h"
21 #include "napi_bluetooth_host.h"
22 #include "napi_bluetooth_utils.h"
23
24 namespace OHOS {
25 namespace Bluetooth {
26 using namespace std;
27
28 NapiA2dpSourceObserver NapiA2dpSource::observer_;
29 bool NapiA2dpSource::isRegistered_ = false;
30
DefineA2dpSourceJSClass(napi_env env)31 void NapiA2dpSource::DefineA2dpSourceJSClass(napi_env env)
32 {
33 napi_value constructor;
34 napi_property_descriptor properties[] = {
35 DECLARE_NAPI_FUNCTION("on", On),
36 DECLARE_NAPI_FUNCTION("off", Off),
37 DECLARE_NAPI_FUNCTION("getConnectionDevices", GetConnectionDevices),
38 DECLARE_NAPI_FUNCTION("getDeviceState", GetDeviceState),
39 DECLARE_NAPI_FUNCTION("getPlayingState", GetPlayingState),
40 DECLARE_NAPI_FUNCTION("connect", Connect),
41 DECLARE_NAPI_FUNCTION("disconnect", Disconnect),
42 };
43
44 napi_define_class(env, "A2dpSource", NAPI_AUTO_LENGTH, A2dpSourceConstructor, nullptr,
45 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
46
47 napi_value napiProfile;
48 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
49 NapiProfile::SetProfile(env, ProfileId::PROFILE_A2DP_SOURCE, napiProfile);
50 HILOGI("finished");
51 }
52
A2dpSourceConstructor(napi_env env,napi_callback_info info)53 napi_value NapiA2dpSource::A2dpSourceConstructor(napi_env env, napi_callback_info info)
54 {
55 napi_value thisVar = nullptr;
56 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
57 return thisVar;
58 }
59
On(napi_env env,napi_callback_info info)60 napi_value NapiA2dpSource::On(napi_env env, napi_callback_info info)
61 {
62 HILOGI("enter");
63 std::unique_lock<std::shared_mutex> guard(NapiA2dpSourceObserver::g_a2dpSrcCallbackInfosMutex);
64
65 napi_value ret = nullptr;
66 ret = NapiEvent::OnEvent(env, info, observer_.callbackInfos_);
67 if (!isRegistered_) {
68 A2dpSource *profile = A2dpSource::GetProfile();
69 profile->RegisterObserver(&observer_);
70 isRegistered_ = true;
71 }
72 HILOGI("napi A2dpSource is registered");
73 return ret;
74 }
75
Off(napi_env env,napi_callback_info info)76 napi_value NapiA2dpSource::Off(napi_env env, napi_callback_info info)
77 {
78 HILOGI("enter");
79 std::unique_lock<std::shared_mutex> guard(NapiA2dpSourceObserver::g_a2dpSrcCallbackInfosMutex);
80
81 napi_value ret = nullptr;
82 ret = NapiEvent::OffEvent(env, info, observer_.callbackInfos_);
83 HILOGI("Napi A2dpSource is unregistered");
84 return ret;
85 }
86
GetConnectionDevices(napi_env env,napi_callback_info info)87 napi_value NapiA2dpSource::GetConnectionDevices(napi_env env, napi_callback_info info)
88 {
89 HILOGI("enter");
90 napi_value ret = nullptr;
91 napi_create_array(env, &ret);
92 A2dpSource *profile = A2dpSource::GetProfile();
93 vector<int> states;
94 states.push_back(1);
95 vector<BluetoothRemoteDevice> devices = profile->GetDevicesByStates(states);
96 vector<string> deviceVector;
97 for (auto &device: devices) {
98 deviceVector.push_back(device.GetDeviceAddr());
99 }
100 ConvertStringVectorToJS(env, ret, deviceVector);
101 return ret;
102 }
103
GetDeviceState(napi_env env,napi_callback_info info)104 napi_value NapiA2dpSource::GetDeviceState(napi_env env, napi_callback_info info)
105 {
106 HILOGI("enter");
107
108 size_t expectedArgsCount = ARGS_SIZE_ONE;
109 size_t argc = expectedArgsCount;
110 napi_value argv[ARGS_SIZE_ONE] = {0};
111 napi_value thisVar = nullptr;
112
113 napi_value ret = nullptr;
114 napi_get_undefined(env, &ret);
115
116 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
117 if (argc != expectedArgsCount) {
118 HILOGE("Requires 1 argument.");
119 return ret;
120 }
121 string deviceId;
122 if (!ParseString(env, deviceId, argv[PARAM0])) {
123 HILOGE("string expected.");
124 return ret;
125 }
126
127 A2dpSource *profile = A2dpSource::GetProfile();
128 BluetoothRemoteDevice device(deviceId, 1);
129 int state = profile->GetDeviceState(device);
130 napi_value result = nullptr;
131 int status = GetProfileConnectionState(state);
132 napi_create_int32(env, status, &result);
133 HILOGI("status: %{public}d", status);
134 return result;
135 }
136
GetPlayingState(napi_env env,napi_callback_info info)137 napi_value NapiA2dpSource::GetPlayingState(napi_env env, napi_callback_info info)
138 {
139 HILOGI("start");
140 int state = PlayingState::STATE_NOT_PLAYING;
141 napi_value ret = nullptr;
142 napi_create_int32(env, state, &ret);
143
144 std::string remoteAddr {};
145 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
146 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, ret);
147
148 int transport = GetDeviceTransport(remoteAddr);
149 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
150 A2dpSource *profile = A2dpSource::GetProfile();
151 int32_t res = profile->GetPlayingState(remoteDevice, state);
152 HILOGI("res: %{public}d", res);
153 NAPI_BT_ASSERT_RETURN(env, (res == BT_SUCCESS), res, ret);
154
155 return NapiGetInt32Ret(env, state);
156 }
157
Connect(napi_env env,napi_callback_info info)158 napi_value NapiA2dpSource::Connect(napi_env env, napi_callback_info info)
159 {
160 HILOGI("start");
161 std::string remoteAddr {};
162 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
163 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
164
165 int transport = GetDeviceTransport(remoteAddr);
166 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
167 A2dpSource *profile = A2dpSource::GetProfile();
168 int32_t ret = profile->Connect(remoteDevice);
169 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_SUCCESS, ret);
170
171 return NapiGetBooleanTrue(env);
172 }
173
Disconnect(napi_env env,napi_callback_info info)174 napi_value NapiA2dpSource::Disconnect(napi_env env, napi_callback_info info)
175 {
176 HILOGI("start");
177 std::string remoteAddr {};
178 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
179 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
180
181 int transport = GetDeviceTransport(remoteAddr);
182 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
183 A2dpSource *profile = A2dpSource::GetProfile();
184 int32_t ret = profile->Disconnect(remoteDevice);
185 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_SUCCESS, ret);
186
187 return NapiGetBooleanTrue(env);
188 }
189 } // namespace Bluetooth
190 } // namespace OHOS