1 /*
2 * Copyright 2008-2009, Oliver Ruiz Dorantes <oliver.ruiz.dorantes@gmail.com>
3 * Copyright 2012-2013, Tri-Edge AI, <triedgeai@gmail.com>
4 * Copyright 2021, Haiku, Inc.
5 * Distributed under the terms of the MIT License.
6 *
7 * Authors:
8 * Fredrik Modéen <fredrik_at_modeen.se>
9 */
10
11 #include "BluetoothSettingsView.h"
12
13 #include "defs.h"
14 #include "BluetoothSettings.h"
15 #include "BluetoothWindow.h"
16 #include "ExtendedLocalDeviceView.h"
17
18 #include <bluetooth/LocalDevice.h>
19
20 #include <Box.h>
21 #include <Catalog.h>
22 #include <LayoutBuilder.h>
23 #include <MenuField.h>
24 #include <MenuItem.h>
25 #include <PopUpMenu.h>
26 #include <OptionPopUp.h>
27 #include <Slider.h>
28 #include <SpaceLayoutItem.h>
29 #include <String.h>
30 #include <TextView.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #undef B_TRANSLATION_CONTEXT
36 #define B_TRANSLATION_CONTEXT "Settings view"
37
38 static const char* kAllLabel = B_TRANSLATE_MARK("From all devices");
39 static const char* kTrustedLabel =
40 B_TRANSLATE_MARK("Only from trusted devices");
41 static const char* kAlwaysLabel = B_TRANSLATE_MARK("Always ask");
42
43 static const char* kDesktopLabel = B_TRANSLATE_MARK("Desktop");
44 static const char* kServerLabel = B_TRANSLATE_MARK("Server");
45 static const char* kLaptopLabel = B_TRANSLATE_MARK("Laptop");
46 static const char* kHandheldLabel = B_TRANSLATE_MARK("Handheld");
47 static const char* kPhoneLabel = B_TRANSLATE_MARK("Smart phone");
48
49 // #pragma mark -
50
BluetoothSettingsView(const char * name)51 BluetoothSettingsView::BluetoothSettingsView(const char* name)
52 :
53 BView(name, 0),
54 fLocalDevicesMenu(NULL)
55 {
56 fSettings.LoadSettings();
57
58 fPolicyMenu = new BOptionPopUp("policy",
59 B_TRANSLATE("Incoming connections policy:"),
60 new BMessage(kMsgSetConnectionPolicy));
61 fPolicyMenu->AddOption(B_TRANSLATE_NOCOLLECT(kAllLabel), 1);
62 fPolicyMenu->AddOption(B_TRANSLATE_NOCOLLECT(kTrustedLabel), 2);
63 fPolicyMenu->AddOption(B_TRANSLATE_NOCOLLECT(kAlwaysLabel), 3);
64
65 fPolicyMenu->SetValue(fSettings.Policy());
66
67 BString label(B_TRANSLATE("Default inquiry time:"));
68 label << " " << fSettings.InquiryTime();
69 fInquiryTimeControl = new BSlider("time", label.String()
70 , new BMessage(kMsgSetInquiryTime), 15, 61, B_HORIZONTAL);
71 fInquiryTimeControl->SetLimitLabels(B_TRANSLATE("15 secs"),
72 B_TRANSLATE("61 secs"));
73 fInquiryTimeControl->SetHashMarks(B_HASH_MARKS_BOTTOM);
74 fInquiryTimeControl->SetHashMarkCount(20);
75 fInquiryTimeControl->SetEnabled(true);
76 fInquiryTimeControl->SetValue(fSettings.InquiryTime());
77
78 fExtDeviceView = new ExtendedLocalDeviceView(NULL);
79
80 // localdevices menu
81 _BuildLocalDevicesMenu();
82 fLocalDevicesMenuField = new BMenuField("devices",
83 B_TRANSLATE("Local devices found on system:"),
84 fLocalDevicesMenu);
85
86 if (ActiveLocalDevice != NULL) {
87 fExtDeviceView->SetLocalDevice(ActiveLocalDevice);
88 fExtDeviceView->SetEnabled(true);
89
90 DeviceClass rememberedClass = ActiveLocalDevice->GetDeviceClass();
91 if (!rememberedClass.IsUnknownDeviceClass())
92 fSettings.SetLocalDeviceClass(rememberedClass);
93 }
94
95 fClassMenu = new BOptionPopUp("DeviceClass", B_TRANSLATE("Identify host as:"),
96 new BMessage(kMsgSetDeviceClass));
97 fClassMenu->AddOption(B_TRANSLATE_NOCOLLECT(kDesktopLabel), 1);
98 fClassMenu->AddOption(B_TRANSLATE_NOCOLLECT(kServerLabel), 2);
99 fClassMenu->AddOption(B_TRANSLATE_NOCOLLECT(kLaptopLabel), 3);
100 fClassMenu->AddOption(B_TRANSLATE_NOCOLLECT(kHandheldLabel), 4);
101 fClassMenu->AddOption(B_TRANSLATE_NOCOLLECT(kPhoneLabel), 5);
102
103 fClassMenu->SetValue(_GetClassForMenu());
104
105 BLayoutBuilder::Grid<>(this, 0)
106 .SetInsets(10)
107 .Add(fClassMenu, 0, 0)
108 .Add(fPolicyMenu, 0, 1)
109
110 .Add(fInquiryTimeControl, 0, 2, 2)
111
112 .Add(fLocalDevicesMenuField->CreateLabelLayoutItem(), 0, 5)
113 .Add(fLocalDevicesMenuField->CreateMenuBarLayoutItem(), 1, 5)
114
115 .Add(fExtDeviceView, 0, 6, 2)
116 .End();
117 }
118
119
~BluetoothSettingsView()120 BluetoothSettingsView::~BluetoothSettingsView()
121 {
122 fSettings.SaveSettings();
123 }
124
125
126 void
AttachedToWindow()127 BluetoothSettingsView::AttachedToWindow()
128 {
129 if (Parent() != NULL)
130 SetViewColor(Parent()->ViewColor());
131 else
132 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
133
134 fLocalDevicesMenu->SetTargetForItems(this);
135 fInquiryTimeControl->SetTarget(this);
136 }
137
138
139 void
MessageReceived(BMessage * message)140 BluetoothSettingsView::MessageReceived(BMessage* message)
141 {
142 //message->PrintToStream();
143 switch (message->what) {
144
145 case kMsgLocalSwitched:
146 {
147 LocalDevice* lDevice;
148
149 if (message->FindPointer("LocalDevice",
150 (void**)&lDevice) == B_OK) {
151
152 _MarkLocalDevice(lDevice);
153 }
154
155 break;
156 }
157
158 case kMsgSetConnectionPolicy:
159 {
160 int32 policy;
161 if (message->FindInt32("be:value", (int32*)&policy) == B_OK) {
162 fSettings.SetPolicy(policy);
163 }
164 break;
165 }
166
167 case kMsgSetInquiryTime:
168 {
169 fSettings.SetInquiryTime(fInquiryTimeControl->Value());
170 BString label(B_TRANSLATE("Default inquiry time:"));
171 label << " " << fInquiryTimeControl->Value();
172 fInquiryTimeControl->SetLabel(label.String());
173 break;
174 }
175
176 case kMsgSetDeviceClass:
177 {
178 int32 deviceClass;
179 if (message->FindInt32("be:value",
180 (int32*)&deviceClass) == B_OK) {
181
182 if (deviceClass == 5)
183 _SetDeviceClass(2, 3, 0x72);
184 else
185 _SetDeviceClass(1, deviceClass, 0x72);
186 }
187
188 break;
189 }
190 case kMsgRefresh:
191 {
192 _BuildLocalDevicesMenu();
193 fLocalDevicesMenu->SetTargetForItems(this);
194
195 break;
196 }
197 default:
198 BView::MessageReceived(message);
199 break;
200 }
201 }
202
203
204 bool
_SetDeviceClass(uint8 major,uint8 minor,uint16 service)205 BluetoothSettingsView::_SetDeviceClass(uint8 major, uint8 minor,
206 uint16 service)
207 {
208 bool haveRun = true;
209
210 fSettings.SetLocalDeviceClass(DeviceClass(major, minor, service));
211
212 if (ActiveLocalDevice != NULL)
213 ActiveLocalDevice->SetDeviceClass(fSettings.LocalDeviceClass());
214 else
215 haveRun = false;
216
217 return haveRun;
218 }
219
220
221 void
_BuildLocalDevicesMenu()222 BluetoothSettingsView::_BuildLocalDevicesMenu()
223 {
224 LocalDevice* lDevice;
225
226 if (!fLocalDevicesMenu)
227 fLocalDevicesMenu = new BPopUpMenu(B_TRANSLATE("Pick device"
228 B_UTF8_ELLIPSIS));
229
230 while (fLocalDevicesMenu->CountItems() > 0) {
231 BMenuItem* item = fLocalDevicesMenu->RemoveItem((int32)0);
232
233 if (item != NULL) {
234 delete item;
235 }
236 }
237
238 ActiveLocalDevice = NULL;
239
240 for (uint32 i = 0; i < LocalDevice::GetLocalDeviceCount(); i++) {
241 lDevice = LocalDevice::GetLocalDevice();
242
243 if (lDevice != NULL) {
244 BMessage* message = new BMessage(kMsgLocalSwitched);
245 message->AddPointer("LocalDevice", lDevice);
246
247 BMenuItem* item = new BMenuItem(
248 (lDevice->GetFriendlyName().String()), message);
249
250 if (bdaddrUtils::Compare(lDevice->GetBluetoothAddress(),
251 fSettings.PickedDevice())) {
252
253 item->SetMarked(true);
254 ActiveLocalDevice = lDevice;
255 }
256
257 fLocalDevicesMenu->AddItem(item);
258 }
259 }
260 }
261
262 void
_MarkLocalDevice(LocalDevice * lDevice)263 BluetoothSettingsView::_MarkLocalDevice(LocalDevice* lDevice)
264 {
265 // TODO: Device integrity should be rechecked.
266
267 fExtDeviceView->SetLocalDevice(lDevice);
268 fExtDeviceView->SetEnabled(true);
269 ActiveLocalDevice = lDevice;
270 fSettings.SetPickedDevice(lDevice->GetBluetoothAddress());
271 }
272
273
274 int
_GetClassForMenu()275 BluetoothSettingsView::_GetClassForMenu()
276 {
277 int deviceClass =
278 fSettings.LocalDeviceClass().MajorDeviceClass()+
279 fSettings.LocalDeviceClass().MinorDeviceClass();
280
281 // As of now we only support MajorDeviceClass = 1 and MinorDeviceClass 1-4
282 // and MajorDeviceClass = 2 and MinorDeviceClass 3.
283 if (fSettings.LocalDeviceClass().MajorDeviceClass() == 1
284 && (fSettings.LocalDeviceClass().MinorDeviceClass() > 0
285 && fSettings.LocalDeviceClass().MinorDeviceClass() < 5))
286 deviceClass -= 1;
287
288 return deviceClass;
289 }
290