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 <GroupLayoutBuilder.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 SetLayout(new BGroupLayout(B_HORIZONTAL
));
106 fScanProgress
= new BStatusBar("status",
107 B_TRANSLATE("Scanning progress"), "");
108 activeColor
= fScanProgress
->BarColor();
110 if (fLocalDevice
== NULL
)
111 fLocalDevice
= LocalDevice::GetLocalDevice();
113 fMessage
= new BTextView("description", B_WILL_DRAW
);
114 fMessage
->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR
));
115 fMessage
->SetLowColor(fMessage
->ViewColor());
116 fMessage
->MakeEditable(false);
117 fMessage
->MakeSelectable(false);
119 fInquiryButton
= new BButton("Inquiry", B_TRANSLATE("Inquiry"),
120 new BMessage(kMsgInquiry
), B_WILL_DRAW
);
122 fAddButton
= new BButton("add", B_TRANSLATE("Add device to list"),
123 new BMessage(kMsgAddToRemoteList
), B_WILL_DRAW
);
124 fAddButton
->SetEnabled(false);
126 fRemoteList
= new BListView("AttributeList", B_SINGLE_SELECTION_LIST
);
127 fRemoteList
->SetSelectionMessage(new BMessage(kMsgSelected
));
129 fScrollView
= new BScrollView("ScrollView", fRemoteList
, 0, false, true);
130 fScrollView
->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR
));
132 if (fLocalDevice
!= NULL
) {
133 fMessage
->SetText(B_TRANSLATE(
134 "Check that the Bluetooth capabilities of your"
135 " remote device are activated. Press 'Inquiry' to start scanning."
136 " The needed time for the retrieval of the names is unknown, "
137 "although should not take more than 3 seconds per device. "
138 "Afterwards you will be able to add them to your main list,"
139 " where you will be able to pair with them."));
140 fInquiryButton
->SetEnabled(true);
141 fDiscoveryAgent
= fLocalDevice
->GetDiscoveryAgent();
142 fDiscoveryListener
= new PanelDiscoveryListener(this);
145 SetTitle((const char*)(fLocalDevice
->GetFriendlyName().String()));
149 fMessage
->SetText(B_TRANSLATE("There isn't any Bluetooth LocalDevice "
150 "registered on the system."));
151 fInquiryButton
->SetEnabled(false);
154 fRetrieveMessage
= new BMessage(kMsgRetrieve
);
155 fSecondsMessage
= new BMessage(kMsgSecond
);
158 AddChild(BGroupLayoutBuilder(B_VERTICAL
, 10)
160 .Add(BSpaceLayoutItem::CreateVerticalStrut(5))
162 .Add(BSpaceLayoutItem::CreateVerticalStrut(5))
164 .Add(BSpaceLayoutItem::CreateVerticalStrut(5))
165 .Add(BGroupLayoutBuilder(B_HORIZONTAL
, 10)
170 .SetInsets(15, 25, 15, 15)
176 InquiryPanel::MessageReceived(BMessage
* message
)
178 static float timer
= 0; // expected time of the inquiry process
179 static float scanningTime
= 0;
180 static int32 retrievalIndex
= 0;
181 static bool labelPlaced
= false;
183 switch (message
->what
) {
186 fDiscoveryAgent
->StartInquiry(BT_GIAC
, fDiscoveryListener
, GetInquiryTime());
188 timer
= BT_BASE_INQUIRY_TIME
* GetInquiryTime() + 1;
189 // does it works as expected?
190 fScanProgress
->SetMaxValue(timer
);
194 case kMsgAddListDevice
:
196 DeviceListItem
* listItem
;
198 message
->FindPointer("remoteItem", (void **)&listItem
);
200 fRemoteList
->AddItem(listItem
);
204 case kMsgAddToRemoteList
:
206 message
->PrintToStream();
207 int32 index
= fRemoteList
->CurrentSelection(0);
208 DeviceListItem
* item
= (DeviceListItem
*) fRemoteList
->RemoveItem(index
);;
210 BMessage
message(kMsgAddToRemoteList
);
211 message
.AddPointer("device", item
);
213 be_app
->PostMessage(&message
);
214 // TODO: all others listitems can be deleted
223 fRemoteList
->MakeEmpty();
224 fScanProgress
->Reset();
225 fScanProgress
->SetTo(1);
226 fScanProgress
->SetTrailingText(B_TRANSLATE("Starting scan..."));
227 fScanProgress
->SetBarColor(activeColor
);
229 fAddButton
->SetEnabled(false);
230 fInquiryButton
->SetEnabled(false);
232 BMessageRunner::StartSending(fMessenger
, fSecondsMessage
, 1000000, timer
);
245 fScanProgress
->SetTo(100);
246 fScanProgress
->SetTrailingText(B_TRANSLATE("Retrieving names..."));
247 BMessageRunner::StartSending(fMessenger
, fRetrieveMessage
, 1000000, 1);
252 if (fScanning
&& scanningTime
< timer
) {
253 // TODO time formatting could use Locale Kit
255 // TODO should not be needed if SetMaxValue works...
256 fScanProgress
->SetTo(scanningTime
* 100 / timer
);
257 BString elapsedTime
= B_TRANSLATE("Remaining %1 seconds");
260 seconds
<< (int)(timer
- scanningTime
);
262 elapsedTime
.ReplaceFirst("%1", seconds
.String());
263 fScanProgress
->SetTrailingText(elapsedTime
.String());
265 scanningTime
= scanningTime
+ 1;
273 if (retrievalIndex
< fDiscoveryAgent
->RetrieveDevices(0).CountItems()) {
278 BString
progressText(B_TRANSLATE("Retrieving name of %1"));
281 namestr
<< bdaddrUtils::ToString(fDiscoveryAgent
282 ->RetrieveDevices(0).ItemAt(retrievalIndex
)
283 ->GetBluetoothAddress());
284 progressText
.ReplaceFirst("%1", namestr
.String());
285 fScanProgress
->SetTrailingText(progressText
.String());
288 // Really erally expensive operation should be done in a separate thread
289 // once Haiku gets a BarberPole in API replacing the progress bar
290 ((DeviceListItem
*)fRemoteList
->ItemAt(retrievalIndex
))
291 ->SetDevice((BluetoothDevice
*) fDiscoveryAgent
292 ->RetrieveDevices(0).ItemAt(retrievalIndex
));
293 fRemoteList
->InvalidateItem(retrievalIndex
);
299 BMessageRunner::StartSending(fMessenger
, fRetrieveMessage
, 500000, 1);
306 fScanProgress
->SetBarColor(
307 ui_color(B_PANEL_BACKGROUND_COLOR
));
308 fScanProgress
->SetTrailingText(
309 B_TRANSLATE("Scanning completed."));
310 fInquiryButton
->SetEnabled(true);
318 BWindow::MessageReceived(message
);
325 InquiryPanel::UpdateListStatus(void)
327 if (fRemoteList
->CurrentSelection() < 0 || fScanning
|| fRetrieving
)
328 fAddButton
->SetEnabled(false);
330 fAddButton
->SetEnabled(true);
335 InquiryPanel::QuitRequested(void)