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 break; 190 } 191 } 192 193 194 bool 195 BluetoothSettingsView::_SetDeviceClass(uint8 major, uint8 minor, 196 uint16 service) 197 { 198 bool haveRun = true; 199 200 fSettings.Data.LocalDeviceClass.SetRecord(major, minor, service); 201 202 if (ActiveLocalDevice != NULL) 203 ActiveLocalDevice->SetDeviceClass(fSettings.Data.LocalDeviceClass); 204 else 205 haveRun = false; 206 207 return haveRun; 208 } 209 210 211 void 212 BluetoothSettingsView::_BuildConnectionPolicy() 213 { 214 BMessage* message = NULL; 215 BMenuItem* item = NULL; 216 217 fPolicyMenu = new BPopUpMenu(B_TRANSLATE("Policy" B_UTF8_ELLIPSIS)); 218 219 message = new BMessage(kMsgSetConnectionPolicy); 220 message->AddInt8("Policy", 1); 221 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kAllLabel), message); 222 fPolicyMenu->AddItem(item); 223 224 message = new BMessage(kMsgSetConnectionPolicy); 225 message->AddInt8("Policy", 2); 226 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kTrustedLabel), message); 227 fPolicyMenu->AddItem(item); 228 229 message = new BMessage(kMsgSetConnectionPolicy); 230 message->AddInt8("Policy", 3); 231 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kAlwaysLabel), NULL); 232 fPolicyMenu->AddItem(item); 233 } 234 235 void 236 BluetoothSettingsView::_BuildClassMenu() 237 { 238 BMessage* message = NULL; 239 BMenuItem* item = NULL; 240 241 fClassMenu = new BPopUpMenu(B_TRANSLATE("Identify us as" B_UTF8_ELLIPSIS)); 242 243 message = new BMessage(kMsgSetDeviceClass); 244 message->AddInt8("DeviceClass", 1); 245 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kDesktopLabel), message); 246 fClassMenu->AddItem(item); 247 248 if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 && 249 fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 1) 250 item->SetMarked(true); 251 252 message = new BMessage(kMsgSetDeviceClass); 253 message->AddInt8("DeviceClass", 2); 254 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kServerLabel), message); 255 fClassMenu->AddItem(item); 256 257 if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 && 258 fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 2) 259 item->SetMarked(true); 260 261 message = new BMessage(kMsgSetDeviceClass); 262 message->AddInt8("DeviceClass", 3); 263 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kLaptopLabel), message); 264 fClassMenu->AddItem(item); 265 266 if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 && 267 fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 3) 268 item->SetMarked(true); 269 270 message = new BMessage(kMsgSetDeviceClass); 271 message->AddInt8("DeviceClass", 4); 272 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kHandheldLabel), message); 273 fClassMenu->AddItem(item); 274 275 if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 && 276 fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 4) 277 item->SetMarked(true); 278 279 message = new BMessage(kMsgSetDeviceClass); 280 message->AddInt8("DeviceClass", 5); 281 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kPhoneLabel), message); 282 fClassMenu->AddItem(item); 283 284 if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 2 && 285 fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 3) 286 item->SetMarked(true); 287 } 288 289 290 void 291 BluetoothSettingsView::_BuildLocalDevicesMenu() 292 { 293 LocalDevice* lDevice; 294 295 if (!fLocalDevicesMenu) 296 fLocalDevicesMenu = new BPopUpMenu(B_TRANSLATE("Pick device" 297 B_UTF8_ELLIPSIS)); 298 299 while (fLocalDevicesMenu->CountItems() > 0) { 300 BMenuItem* item = fLocalDevicesMenu->RemoveItem((int32)0); 301 302 if (item != NULL) { 303 delete item; 304 } 305 } 306 307 ActiveLocalDevice = NULL; 308 309 for (uint32 i = 0; i < LocalDevice::GetLocalDeviceCount(); i++) { 310 lDevice = LocalDevice::GetLocalDevice(); 311 312 if (lDevice != NULL) { 313 BMessage* message = new BMessage(kMsgLocalSwitched); 314 message->AddPointer("LocalDevice", lDevice); 315 316 BMenuItem* item = new BMenuItem( 317 (lDevice->GetFriendlyName().String()), message); 318 319 if (bdaddrUtils::Compare(lDevice->GetBluetoothAddress(), 320 fSettings.Data.PickedDevice)) { 321 322 item->SetMarked(true); 323 ActiveLocalDevice = lDevice; 324 } 325 326 fLocalDevicesMenu->AddItem(item); 327 } 328 } 329 } 330 331 void 332 BluetoothSettingsView::_MarkLocalDevice(LocalDevice* lDevice) 333 { 334 // TODO: Device integrity should be rechecked. 335 336 fExtDeviceView->SetLocalDevice(lDevice); 337 fExtDeviceView->SetEnabled(true); 338 ActiveLocalDevice = lDevice; 339 fSettings.Data.PickedDevice = lDevice->GetBluetoothAddress(); 340 } 341