2 * Copyright 2007-2009 Haiku.
3 * Distributed under the terms of the MIT License.
6 * Oliver Ruiz Dorantes oliver.ruiz.dorantes_at_gmail.com
7 * Ryan Leavengood leavengood@gmail.com
8 * Fredrik Modéen fredrik@modeen.se
12 #include "MessageWin.h"
16 //#include "FileReadWrite.h"
26 #include <ScrollView.h>
28 #include <StringView.h>
29 #include <Application.h>
33 #include <Directory.h>
37 #include <Messenger.h>
38 #include <Directory.h>
40 #include <FindDirectory.h>
43 #define JOYSTICKPATH "/dev/joystick/"
44 #define JOYSTICKFILEPATH "/boot/system/data/joysticks/"
45 #define JOYSTICKFILESETTINGS "/boot/home/config/settings/joysticks/"
46 #define SELECTGAMEPORTFIRST "Select a game port first"
49 ShowMessage(char* string
)
51 BAlert
*alert
= new BAlert("Message", string
, "OK");
52 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
56 JoyWin::JoyWin(BRect frame
, const char *title
)
57 : BWindow(frame
, title
, B_DOCUMENT_WINDOW_LOOK
, B_NORMAL_WINDOW_FEEL
,
58 B_NOT_ZOOMABLE
), fSystemUsedSelect(false),
59 fJoystick(new BJoystick
)
61 fProbeButton
= new BButton(BRect(15.00, 260.00, 115.00, 285.00),
62 "ProbeButton", "Probe", new BMessage(PROBE
));
64 fCalibrateButton
= new BButton(BRect(270.00, 260.00, 370.00, 285.00),
65 "CalibrateButton", "Calibrate", new BMessage(CALIBRATE
));
67 fGamePortL
= new BListView(BRect(15.00, 30.00, 145.00, 250.00),
69 fGamePortL
->SetSelectionMessage(new BMessage(PORT_SELECTED
));
70 fGamePortL
->SetInvocationMessage(new BMessage(PORT_INVOKE
));
72 fConControllerL
= new BListView(BRect(175.00,30.00,370.00,250.00),
74 fConControllerL
->SetSelectionMessage(new BMessage(JOY_SELECTED
));
75 fConControllerL
->SetInvocationMessage(new BMessage(JOY_INVOKE
));
77 fGamePortS
= new BStringView(BRect(15, 5, 160, 25), "gpString",
79 fGamePortS
->SetFont(be_bold_font
);
80 fConControllerS
= new BStringView(BRect(170, 5, 330, 25), "ccString",
81 "Connected controller");
83 fConControllerS
->SetFont(be_bold_font
);
85 fCheckbox
= new BCheckBox(BRect(131.00, 260.00, 227.00, 280.00),
86 "Disabled", "Disabled", new BMessage(DISABLEPORT
));
87 BBox
*box
= new BBox( Bounds(),"box", B_FOLLOW_ALL
,
88 B_WILL_DRAW
| B_FRAME_EVENTS
| B_FULL_UPDATE_ON_RESIZE
,
91 box
->SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
93 // Add listViews with their scrolls
94 box
->AddChild(new BScrollView("PortScroll", fGamePortL
,
95 B_FOLLOW_LEFT
| B_FOLLOW_TOP_BOTTOM
, B_WILL_DRAW
, false, true));
97 box
->AddChild(new BScrollView("ConScroll", fConControllerL
, B_FOLLOW_ALL
,
98 B_WILL_DRAW
, false, true));
101 box
->AddChild(fCheckbox
);
102 box
->AddChild(fGamePortS
);
103 box
->AddChild(fConControllerS
);
104 box
->AddChild(fProbeButton
);
105 box
->AddChild(fCalibrateButton
);
108 SetSizeLimits(400, 600, Bounds().Height(), Bounds().Height());
110 /* Add all the devices */
111 int32 nr
= fJoystick
->CountDevices();
112 for (int32 i
= 0; i
< nr
;i
++) {
113 //BString str(path.Path());
114 char buf
[B_OS_NAME_LENGTH
];
115 fJoystick
->GetDeviceName(i
, buf
, B_OS_NAME_LENGTH
);
116 fGamePortL
->AddItem(new PortItem(buf
));
118 fGamePortL
->Select(0);
120 /* Add the joysticks specifications */
121 _AddToList(fConControllerL
, JOY_SELECTED
, JOYSTICKFILEPATH
);
129 //delete fFileTempProbeJoystick;
130 be_app_messenger
.SendMessage(B_QUIT_REQUESTED
);
135 JoyWin::MessageReceived(BMessage
*message
)
137 // message->PrintToStream();
138 switch(message
->what
)
143 PortItem
*item
= _GetSelectedItem(fGamePortL
);
145 //ToDo: item->SetEnabled(true);
146 //don't work as you can't select a item that are disabled
147 if(fCheckbox
->Value()) {
148 item
->SetEnabled(false);
149 _SelectDeselectJoystick(fConControllerL
, false);
151 item
->SetEnabled(true);
152 _SelectDeselectJoystick(fConControllerL
, true);
153 _PerformProbe(item
->Text());
156 //printf("We have a null value\n");
162 PortItem
*item
= _GetSelectedItem(fGamePortL
);
164 fSystemUsedSelect
= true;
165 if (item
->IsEnabled()) {
166 //printf("SetEnabled = false\n");
167 fCheckbox
->SetValue(false);
168 _SelectDeselectJoystick(fConControllerL
, true);
170 //printf("SetEnabled = true\n");
171 fCheckbox
->SetValue(true);
172 _SelectDeselectJoystick(fConControllerL
, false);
175 if (_CheckJoystickExist(item
->Text()) == B_ERROR
) {
176 if (_ShowCantFindFileMessage(item
->Text()) == B_OK
) {
177 _PerformProbe(item
->Text());
180 BString
str(_FindFilePathForSymLink(JOYSTICKFILESETTINGS
,
183 BString
str(_FixPathToName(str
.String()));
184 int32 id
= _FindStringItemInList(fConControllerL
,
185 new PortItem(str
.String()));
187 fConControllerL
->Select(id
);
188 item
->SetJoystickName(BString(str
.String()));
193 fConControllerL
->DeselectAll();
194 ShowMessage((char*)SELECTGAMEPORTFIRST
);
202 PortItem
*item
= _GetSelectedItem(fGamePortL
);
204 //printf("invoke.. inte null\n");
205 _PerformProbe(item
->Text());
207 ShowMessage((char*)SELECTGAMEPORTFIRST
);
213 if (!fSystemUsedSelect
) {
214 PortItem
*controllerName
= _GetSelectedItem(fConControllerL
);
215 PortItem
*portname
= _GetSelectedItem(fGamePortL
);
216 if (portname
!= NULL
&& controllerName
!= NULL
) {
217 portname
->SetJoystickName(BString(controllerName
->Text()));
219 BString str
= portname
->GetOldJoystickName();
221 BString
strOldFile(JOYSTICKFILESETTINGS
);
222 strOldFile
.Append(portname
->Text());
223 BEntry
entry(strOldFile
.String());
226 BString
strLinkPlace(JOYSTICKFILESETTINGS
);
227 strLinkPlace
.Append(portname
->Text());
229 BString
strLinkTo(JOYSTICKFILEPATH
);
230 strLinkTo
.Append(controllerName
->Text());
232 BDirectory
*dir
= new BDirectory();
233 dir
->CreateSymLink(strLinkPlace
.String(),
234 strLinkTo
.String(), NULL
);
236 ShowMessage((char*)SELECTGAMEPORTFIRST
);
239 fSystemUsedSelect
= false;
246 PortItem
*controllerName
= _GetSelectedItem(fConControllerL
);
247 PortItem
*portname
= _GetSelectedItem(fGamePortL
);
248 if (portname
!= NULL
) {
249 if (controllerName
== NULL
)
250 _ShowNoDeviceConnectedMessage("known", portname
->Text());
252 _ShowNoDeviceConnectedMessage(controllerName
->Text(), portname
->Text());
255 Check for a device, and show calibrate window if so
259 ShowMessage((char*)SELECTGAMEPORTFIRST
);
263 BWindow::MessageReceived(message
);
270 JoyWin::QuitRequested()
273 return BWindow::QuitRequested();
277 //---------------------- Private ---------------------------------//
279 JoyWin::_AddToList(BListView
*list
, uint32 command
, const char* rootPath
,
284 if ( rootEntry
!= NULL
)
285 root
.SetTo( rootEntry
);
286 else if ( rootPath
!= NULL
)
287 root
.SetTo( rootPath
);
292 while ((root
.GetNextEntry(&entry
)) > B_ERROR
) {
293 if (entry
.IsDirectory()) {
294 _AddToList(list
, command
, rootPath
, &entry
);
297 entry
.GetPath(&path
);
298 BString
str(path
.Path());
299 str
.RemoveFirst(rootPath
);
300 list
->AddItem(new PortItem(str
.String()));
311 BRect
rect(100, 100, 500, 400);
312 calibw
= new CalibWin(rect
, "Calibrate", B_DOCUMENT_WINDOW_LOOK
,
313 B_NORMAL_WINDOW_FEEL
, B_NOT_RESIZABLE
| B_NOT_ZOOMABLE
);
320 JoyWin::_PerformProbe(const char* path
)
322 status_t err
= B_ERROR
;
323 err
= _ShowProbeMesage(path
);
328 MessageWin
* mesgw
= new MessageWin(Frame(),"Probing", B_MODAL_WINDOW_LOOK
,
329 B_MODAL_APP_WINDOW_FEEL
, B_NOT_RESIZABLE
| B_NOT_ZOOMABLE
);
332 int32 number
= fConControllerL
->CountItems();
334 for (int i
= 0; i
< number
; i
++) {
335 // Do a search in JOYSTICKFILEPATH with item->Text() find the string
336 // that starts with "gadget" (tex gadget = "GamePad Pro") remove
337 // spacing and the "=" ty to open this one, if failed move to next and
338 // try to open.. list those that suxesfully work
339 fConControllerL
->Select(i
);
340 int32 selected
= fConControllerL
->CurrentSelection();
341 item
= dynamic_cast<PortItem
*>(fConControllerL
->ItemAt(selected
));
342 BString
str("Looking for: ");
343 str
<< item
->Text() << " in port " << path
;
344 mesgw
->SetText(str
.String());
345 _FindSettingString(item
->Text(), JOYSTICKFILEPATH
);
346 //Need a check to find joysticks (don't know how right now so show a
347 // don't find message)
351 //Need a if !found then show this message. else list joysticks.
352 _ShowNoCompatibleJoystickMessage();
358 JoyWin::_ApplyChanges()
360 BString str
= _BuildDisabledJoysticksFile();
361 //ToDo; Save the string as the file "disabled_joysticks" under settings
362 // (/boot/home/config/settings/disabled_joysticks)
368 JoyWin::_GetSettings()
370 // ToDo; Read the file "disabled_joysticks" and make the port with the
371 // same name disabled (/boot/home/config/settings/disabled_joysticks)
377 JoyWin::_CheckJoystickExist(const char* path
)
379 BString
str(JOYSTICKFILESETTINGS
);
383 status_t status
= file
.SetTo(str
.String(), B_READ_ONLY
| B_FAIL_IF_EXISTS
);
385 if (status
== B_FILE_EXISTS
|| status
== B_OK
)
393 JoyWin::_ShowProbeMesage(const char* device
)
395 BString
str("An attempt will be made to probe the port '");
396 str
<< device
<< "' to try to figure out what kind of joystick (if any) ";
397 str
<< "are attached. There is a small chance this process might cause ";
398 str
<< "your machine to lock up and require a reboot. Make sure you have ";
399 str
<< "saved changes in all open applications before you start probing.";
401 BAlert
*alert
= new BAlert("test1", str
.String(), "Probe", "Cancel");
402 alert
->SetShortcut(1, B_ESCAPE
);
403 int32 bindex
= alert
->Go();
412 //Used when a files/joysticks are no were to be found
414 JoyWin::_ShowCantFindFileMessage(const char* port
)
416 BString
str("The file '");
417 str
<< _FixPathToName(port
).String() << "' used by '" << port
;
418 str
<< "' cannot be found.\n Do you want to ";
419 str
<< "try auto-detecting a joystick for this port?";
421 BAlert
*alert
= new BAlert("test1", str
.String(), "Stop", "Probe");
422 alert
->SetShortcut(1, B_ENTER
);
423 int32 bindex
= alert
->Go();
433 JoyWin::_ShowNoCompatibleJoystickMessage()
435 BString
str("There were no compatible joysticks detected on this game");
436 str
<< " port. Try another port, or ask the manufacturer of your joystick";
437 str
<< " for a driver designed for Haiku or BeOS.";
439 BAlert
*alert
= new BAlert("test1", str
.String(), "OK");
440 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
445 JoyWin::_ShowNoDeviceConnectedMessage(const char* joy
, const char* port
)
447 BString
str("There does not appear to be a ");
448 str
<< joy
<< " device connected to the port '" << port
<< "'.";
450 BAlert
*alert
= new BAlert("test1", str
.String(), "Stop");
451 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
456 // Use this function to get a string of disabled ports
458 JoyWin::_BuildDisabledJoysticksFile()
460 BString
temp("# This is a list of disabled joystick devices.");
461 temp
<< "# Do not include the /dev/joystick/ part of the device name.";
463 int32 number
= fGamePortL
->CountItems();
465 for (int i
= 0; i
< number
; i
++) {
466 item
= dynamic_cast<PortItem
*>(fGamePortL
->ItemAt(i
));
467 if (!item
->IsEnabled())
468 temp
<< "disable = \"" << item
->Text() << "\"";
475 JoyWin::_GetSelectedItem(BListView
* list
)
477 int32 id
= list
->CurrentSelection();
479 //PortItem *item = dynamic_cast<PortItem*>(list->ItemAt(id));
480 return dynamic_cast<PortItem
*>(list
->ItemAt(id
));
488 JoyWin::_FixPathToName(const char* port
)
491 temp
= temp
.Remove(0, temp
.FindLast('/') + 1) ;
497 JoyWin::_SelectDeselectJoystick(BListView
* list
, bool enable
)
500 int32 number
= fGamePortL
->CountItems();
502 for (int i
= 0; i
< number
; i
++) {
503 item
= dynamic_cast<PortItem
*>(list
->ItemAt(i
));
505 printf("%s: PortItem at %d is null!\n", __func__
, i
);
508 item
->SetEnabled(enable
);
514 JoyWin::_FindStringItemInList(BListView
*view
, PortItem
*item
)
516 PortItem
*strItem
= NULL
;
517 int32 number
= view
->CountItems();
518 for (int32 i
= 0; i
< number
; i
++) {
519 strItem
= dynamic_cast<PortItem
*>(view
->ItemAt(i
));
520 if (!strcmp(strItem
->Text(), item
->Text())) {
530 JoyWin::_FindFilePathForSymLink(const char* symLinkPath
, PortItem
*item
)
532 BPath
path(symLinkPath
);
533 path
.Append(item
->Text());
534 BEntry
entry(path
.Path());
535 if (entry
.IsSymLink()) {
536 BSymLink
symLink(&entry
);
538 entry
.GetParent(&parent
);
539 symLink
.MakeLinkedPath(&parent
, &path
);
540 BString
str(path
.Path());
548 JoyWin::_FindStick(const char* name
)
550 BJoystick
*stick
= new BJoystick();
551 return stick
->Open(name
);
556 JoyWin::_FindSettingString(const char* name
, const char* strPath
)
558 //Make a BJoystick try open it
563 fFileTempProbeJoystick
= new BFile(path
.Path(), B_READ_ONLY
);
565 //status_t err = find_directory(B_SYSTEM_ETC_DIRECTORY, &path);
566 // if (err == B_OK) {
567 //BString str(path.Path());
568 //str << "/joysticks/" << name;
569 //printf("path'%s'\n", str.String());
570 //err = file->SetTo(strPath, B_READ_ONLY);
571 status_t err
= fFileTempProbeJoystick
->InitCheck();
573 //FileReadWrite frw(fFileTempProbeJoystick);
574 //printf("Get going\n");
575 //printf("Opening file = %s\n", path.Path());
576 //while (frw.Next(str)) {
577 //printf("In While loop\n");
578 // printf("getline %s \n", str.String());
579 //Test to open joystick with x number
581 /*while (_GetLine(str)) {
582 //printf("In While loop\n");
583 printf("getline %s \n", str.String());
584 //Test to open joystick with x number
588 printf("BFile.SetTo error: %s, Path = %s\n", strerror(err
), str
.String());
590 // printf("find_directory error: %s\n", strerror(err));
597 //Function to get a line from a file
599 JoyWin::_GetLine(BString& string)
601 // Fill up the buffer with the first chunk of code
602 if (fPositionInBuffer == 0)
603 fAmtRead = fFileTempProbeJoystick->Read(&fBuffer, sizeof(fBuffer));
604 while (fAmtRead > 0) {
605 while (fPositionInBuffer < fAmtRead) {
606 // Return true if we hit a newline or the end of the file
607 if (fBuffer[fPositionInBuffer] == '\n') {
611 int32 bufferLen = string.Length();
612 int32 destBufferLen = bufferLen;
613 char destination[destBufferLen];
614 // if (fSourceEncoding)
615 // convert_to_utf8(fSourceEncoding, string.String(), &bufferLen, destination, &destBufferLen, &state);
616 string = destination;
619 string += fBuffer[fPositionInBuffer];
623 // Once the buffer runs out, grab some more and start again
624 fAmtRead = fFileTempProbeJoystick->Read(&fBuffer, sizeof(fBuffer));
625 fPositionInBuffer = 0;