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