2 * Copyright 2008-09, Oliver Ruiz Dorantes, <oliver.ruiz.dorantes_at_gmail.com>
3 * All rights reserved. Distributed under the terms of the MIT License.
9 #include <LayoutBuilder.h>
12 #include <MessageRunner.h>
13 #include <ScrollView.h>
14 #include <StatusBar.h>
15 #include <SpaceLayoutItem.h>
19 #include <bluetooth/bdaddrUtils.h>
20 #include <bluetooth/DiscoveryAgent.h>
21 #include <bluetooth/DiscoveryListener.h>
22 #include <bluetooth/LocalDevice.h>
25 #include "DeviceListItem.h"
26 #include "InquiryPanel.h"
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "Inquiry panel"
32 using Bluetooth::DeviceListItem
;
34 // private funcionaility provided by kit
35 extern uint8
GetInquiryTime();
37 static const uint32 kMsgStart
= 'InSt';
38 static const uint32 kMsgFinish
= 'InFn';
39 static const uint32 kMsgShowDebug
= 'ShDG';
41 static const uint32 kMsgInquiry
= 'iQbt';
42 static const uint32 kMsgAddListDevice
= 'aDdv';
44 static const uint32 kMsgSelected
= 'isLt';
45 static const uint32 kMsgSecond
= 'sCMs';
46 static const uint32 kMsgRetrieve
= 'IrEt';
49 class PanelDiscoveryListener
: public DiscoveryListener
{
53 PanelDiscoveryListener(InquiryPanel
* iPanel
)
63 DeviceDiscovered(RemoteDevice
* btDevice
, DeviceClass cod
)
65 BMessage
* message
= new BMessage(kMsgAddListDevice
);
67 message
->AddPointer("remoteItem", new DeviceListItem(btDevice
));
69 fInquiryPanel
->PostMessage(message
);
74 InquiryCompleted(int discType
)
76 BMessage
* message
= new BMessage(kMsgFinish
);
77 fInquiryPanel
->PostMessage(message
);
82 InquiryStarted(status_t status
)
84 BMessage
* message
= new BMessage(kMsgStart
);
85 fInquiryPanel
->PostMessage(message
);
89 InquiryPanel
* fInquiryPanel
;
94 InquiryPanel::InquiryPanel(BRect frame
, LocalDevice
* lDevice
)
96 BWindow(frame
, B_TRANSLATE_SYSTEM_NAME("Bluetooth"), B_FLOATING_WINDOW
,
97 B_NOT_ZOOMABLE
| B_AUTO_UPDATE_SIZE_LIMITS
, B_ALL_WORKSPACES
),
101 fLocalDevice(lDevice
)
104 fScanProgress
= new BStatusBar("status",
105 B_TRANSLATE("Scanning progress"), "");
106 activeColor
= fScanProgress
->BarColor();
108 if (fLocalDevice
== NULL
)
109 fLocalDevice
= LocalDevice::GetLocalDevice();
111 fMessage
= new BTextView("description", B_WILL_DRAW
);
112 fMessage
->SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
113 fMessage
->SetLowColor(fMessage
->ViewColor());
114 fMessage
->MakeEditable(false);
115 fMessage
->MakeSelectable(false);
117 fInquiryButton
= new BButton("Inquiry", B_TRANSLATE("Inquiry"),
118 new BMessage(kMsgInquiry
), B_WILL_DRAW
);
120 fAddButton
= new BButton("add", B_TRANSLATE("Add device to list"),
121 new BMessage(kMsgAddToRemoteList
), B_WILL_DRAW
);
122 fAddButton
->SetEnabled(false);
124 fRemoteList
= new BListView("AttributeList", B_SINGLE_SELECTION_LIST
);
125 fRemoteList
->SetSelectionMessage(new BMessage(kMsgSelected
));
127 fScrollView
= new BScrollView("ScrollView", fRemoteList
, 0, false, true);
128 fScrollView
->SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
130 if (fLocalDevice
!= NULL
) {
131 fMessage
->SetText(B_TRANSLATE(
132 "Check that the Bluetooth capabilities of your"
133 " remote device are activated. Press 'Inquiry' to start scanning."
134 " The needed time for the retrieval of the names is unknown, "
135 "although should not take more than 3 seconds per device. "
136 "Afterwards you will be able to add them to your main list,"
137 " where you will be able to pair with them."));
138 fInquiryButton
->SetEnabled(true);
139 fDiscoveryAgent
= fLocalDevice
->GetDiscoveryAgent();
140 fDiscoveryListener
= new PanelDiscoveryListener(this);
142 SetTitle((const char*)(fLocalDevice
->GetFriendlyName().String()));
144 fMessage
->SetText(B_TRANSLATE("There isn't any Bluetooth LocalDevice "
145 "registered on the system."));
146 fInquiryButton
->SetEnabled(false);
149 fRetrieveMessage
= new BMessage(kMsgRetrieve
);
150 fSecondsMessage
= new BMessage(kMsgSecond
);
152 BLayoutBuilder::Group
<>(this, B_VERTICAL
, 10)
155 .Add(fScanProgress
, 10)
157 .AddGroup(B_HORIZONTAL
, 10)
167 InquiryPanel::MessageReceived(BMessage
* message
)
169 static float timer
= 0; // expected time of the inquiry process
170 static float scanningTime
= 0;
171 static int32 retrievalIndex
= 0;
172 static bool labelPlaced
= false;
174 switch (message
->what
) {
177 fDiscoveryAgent
->StartInquiry(BT_GIAC
, fDiscoveryListener
, GetInquiryTime());
179 timer
= BT_BASE_INQUIRY_TIME
* GetInquiryTime() + 1;
180 // does it works as expected?
181 fScanProgress
->SetMaxValue(timer
);
185 case kMsgAddListDevice
:
187 DeviceListItem
* listItem
;
189 message
->FindPointer("remoteItem", (void **)&listItem
);
191 fRemoteList
->AddItem(listItem
);
195 case kMsgAddToRemoteList
:
197 message
->PrintToStream();
198 int32 index
= fRemoteList
->CurrentSelection(0);
199 DeviceListItem
* item
= (DeviceListItem
*) fRemoteList
->RemoveItem(index
);;
201 BMessage
message(kMsgAddToRemoteList
);
202 message
.AddPointer("device", item
);
204 be_app
->PostMessage(&message
);
205 // TODO: all others listitems can be deleted
214 fRemoteList
->MakeEmpty();
215 fScanProgress
->Reset();
216 fScanProgress
->SetTo(1);
217 fScanProgress
->SetTrailingText(B_TRANSLATE("Starting scan..."));
218 fScanProgress
->SetBarColor(activeColor
);
220 fAddButton
->SetEnabled(false);
221 fInquiryButton
->SetEnabled(false);
223 BMessageRunner::StartSending(fMessenger
, fSecondsMessage
, 1000000, timer
);
236 fScanProgress
->SetTo(100);
237 fScanProgress
->SetTrailingText(B_TRANSLATE("Retrieving names..."));
238 BMessageRunner::StartSending(fMessenger
, fRetrieveMessage
, 1000000, 1);
243 if (fScanning
&& scanningTime
< timer
) {
244 // TODO time formatting could use Locale Kit
246 // TODO should not be needed if SetMaxValue works...
247 fScanProgress
->SetTo(scanningTime
* 100 / timer
);
248 BString elapsedTime
= B_TRANSLATE("Remaining %1 seconds");
251 seconds
<< (int)(timer
- scanningTime
);
253 elapsedTime
.ReplaceFirst("%1", seconds
.String());
254 fScanProgress
->SetTrailingText(elapsedTime
.String());
256 scanningTime
= scanningTime
+ 1;
264 if (retrievalIndex
< fDiscoveryAgent
->RetrieveDevices(0).CountItems()) {
269 BString
progressText(B_TRANSLATE("Retrieving name of %1"));
272 namestr
<< bdaddrUtils::ToString(fDiscoveryAgent
273 ->RetrieveDevices(0).ItemAt(retrievalIndex
)
274 ->GetBluetoothAddress());
275 progressText
.ReplaceFirst("%1", namestr
.String());
276 fScanProgress
->SetTrailingText(progressText
.String());
279 // Really erally expensive operation should be done in a separate thread
280 // once Haiku gets a BarberPole in API replacing the progress bar
281 ((DeviceListItem
*)fRemoteList
->ItemAt(retrievalIndex
))
282 ->SetDevice((BluetoothDevice
*) fDiscoveryAgent
283 ->RetrieveDevices(0).ItemAt(retrievalIndex
));
284 fRemoteList
->InvalidateItem(retrievalIndex
);
290 BMessageRunner::StartSending(fMessenger
, fRetrieveMessage
, 500000, 1);
297 fScanProgress
->SetBarColor(
298 ui_color(B_PANEL_BACKGROUND_COLOR
));
299 fScanProgress
->SetTrailingText(
300 B_TRANSLATE("Scanning completed."));
301 fInquiryButton
->SetEnabled(true);
309 BWindow::MessageReceived(message
);
316 InquiryPanel::UpdateListStatus(void)
318 if (fRemoteList
->CurrentSelection() < 0 || fScanning
|| fRetrieving
)
319 fAddButton
->SetEnabled(false);
321 fAddButton
->SetEnabled(true);
326 InquiryPanel::QuitRequested(void)