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 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 120 BluetoothSettingsView::~BluetoothSettingsView() 121 { 122 fSettings.SaveSettings(); 123 } 124 125 126 void 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 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 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 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 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 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