00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "gamepad-config-dialog.h"
00036
00037 #include "datahash/datahash_text.h"
00038 #include "datahash/datahash_util.h"
00039 #include "dialog/request.h"
00040 #include "gamepad-vgfx-element/gamepad-vgfx-element.h"
00041 #include "i18n/i18n.h"
00042
00043
00044 namespace gamepad {
00045
00046
00047
00048 static const char * s_defaultLocale = "en_US.UTF-8";
00049
00050
00051 static const char * s_widthString = "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM";
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 static int
00062 addHints
00063 (
00064 IN dialog::ContainerRequest& req,
00065 IN i18n::Manager * mgr
00066 )
00067 {
00068 ASSERT(mgr, "null");
00069
00070 const int bufsize = 32;
00071 char buffer[bufsize];
00072
00073 int count = 0;
00074 for (int i = 1; ;++i, ++count) {
00075 snprintf(buffer, bufsize, "hint%d", i);
00076 const char * string = mgr->getString(buffer);
00077 if (!string)
00078 break;
00079 req.addLabel(string);
00080 }
00081
00082 return count;
00083 }
00084
00085
00086
00087 static const char *
00088 getTypeString
00089 (
00090 IN Manager * mgr,
00091 IN const Type * type,
00092 IN const std::string& locale,
00093 OUT char * buffer,
00094 IN int bufsize
00095 )
00096 {
00097 ASSERT(mgr, "null");
00098 ASSERT(type, "null");
00099 ASSERT(buffer, "null");
00100 ASSERT(bufsize > 0, "bad buffer size: %d", bufsize);
00101
00102 smart_ptr<i18n::Manager> i18nMgr =
00103 getTypeLocaleMgr(type, locale.c_str(), s_defaultLocale,
00104 mgr->getDataDirectory());
00105 ASSERT(i18nMgr, "null");
00106
00107 strncpy(buffer, i18n::getString(i18nMgr, "friendlyName"), bufsize);
00108 return buffer;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 class Host : public converse::ConversationHost {
00121 public:
00122
00123 ~Host(void) throw() { }
00124
00125
00126 void initialize(IN smart_ptr<Manager>& mgr,
00127 IN int gamepadId);
00128
00129
00130 int getCurrentDialogIdTS(void);
00131 void handleReplyTS(IN int dialogId,
00132 IN const Datahash * reply);
00133 std::string getDialogDataTS(void);
00134 bool updateState(void);
00135
00136 private:
00137
00138 enum eDialog {
00139 eDialog_Done = 0,
00140 eDialog_ListPads = 1,
00141 eDialog_SelectSource = 2,
00142 eDialog_SelectType = 3,
00143 eDialog_Calibrate = 4,
00144 eDialog_Config = 5,
00145 eDialog_Test = 6,
00146 eDialog_DelConfirm = 7,
00147 eDialog_DelFail = 8,
00148
00149
00150 eDialog_Invalid = -1
00151 };
00152
00153
00154 void verifyTypeMgr(void);
00155
00156
00157 smart_ptr<Manager> m_mgr;
00158 smart_ptr<SourceDevice> m_device;
00159 Type * m_type;
00160 smart_ptr<Configurator> m_config;
00161 smart_ptr<i18n::Manager> m_configMgr;
00162 smart_ptr<i18n::Manager> m_typeMgr;
00163 VecString m_friendly;
00164 std::string m_locale;
00165 std::string m_direction;
00166 const char * m_logical;
00167 eDialog m_dialogId;
00168 int m_currStep;
00169 int m_testingId;
00170 int m_counter;
00171 bool m_pulseMain;
00172 };
00173
00174
00175
00176 void
00177 Host::initialize
00178 (
00179 IN smart_ptr<Manager>& mgr,
00180 IN int gamepadId
00181 )
00182 {
00183 ASSERT(mgr, "null");
00184
00185 m_mgr = mgr;
00186 m_type = NULL;
00187 m_counter = 0;
00188 m_currStep = -1;
00189 m_testingId = -1;
00190 m_logical = NULL;
00191 m_pulseMain = false;
00192
00193 const char * locale = i18n::getHostLocale();
00194 m_locale = (locale) ? locale : s_defaultLocale;
00195
00196
00197 m_configMgr = getConfigLocaleMgr(m_locale.c_str(), s_defaultLocale,
00198 mgr->getDataDirectory());
00199 ASSERT(m_configMgr, "null");
00200
00201 if (gamepadId >= 0) {
00202 m_dialogId = eDialog_Test;
00203 m_testingId = gamepadId;
00204 } else {
00205 m_dialogId = eDialog_ListPads;
00206 }
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 int
00218 Host::getCurrentDialogIdTS
00219 (
00220 void
00221 )
00222 {
00223 return m_dialogId;
00224 }
00225
00226
00227
00228 void
00229 Host::handleReplyTS
00230 (
00231 IN int dialogId,
00232 IN const Datahash * reply
00233 )
00234 {
00235 ASSERT(reply, "null");
00236
00237 DPRINTF("Got dialog reply for id=%d", dialogId);
00238
00239 if (dialogId != m_dialogId) {
00240 DPRINTF("Got response for wrong dialog id?");
00241 DPRINTF("My dialog id=%d", m_dialogId);
00242 return;
00243 }
00244 const char * value = getString(reply, "submit");
00245
00246 if (eDialog_ListPads == m_dialogId) {
00247 if (!strncmp("test.", value, 5)) {
00248
00249 int id = atoi(value + 5);
00250 DPRINTF("User wants to test gamepad %d", id);
00251 int nGamepads = m_mgr->getGamepadCount();
00252 if (id < 0 || id >= nGamepads) {
00253 m_testingId = -1;
00254 m_dialogId = eDialog_ListPads;
00255 } else {
00256 m_dialogId = eDialog_Test;
00257 m_testingId = id;
00258 }
00259 } else if (!strcmp("newpad", value)) {
00260 m_dialogId = eDialog_SelectSource;
00261 } else if (!strcmp("close", value)) {
00262 m_dialogId = eDialog_Done;
00263 } else {
00264 DPRINTF("Unknown reply submit: '%s'", value);
00265 m_dialogId = eDialog_ListPads;
00266 }
00267 } else if (eDialog_SelectSource == m_dialogId) {
00268 if (!strcmp("home", value)) {
00269 m_dialogId = eDialog_ListPads;
00270 } else if (!strncmp("src.", value, 4)) {
00271 const char * id = value + 4;
00272 DPRINTF("User wants source device with id='%s'", id);
00273 smart_ptr<SourceDevice> device =
00274 m_mgr->getSourceDeviceById(id);
00275 if (!device) {
00276 DPRINTF("Bad device? id=%s", id);
00277 m_dialogId = eDialog_ListPads;
00278 return;
00279 }
00280
00281
00282 m_device = device;
00283
00284
00285 m_dialogId = eDialog_SelectType;
00286 }
00287 } else if (eDialog_SelectType == m_dialogId) {
00288 if (!strcmp("src", value)) {
00289 m_dialogId = eDialog_SelectSource;
00290 } else if (!strncmp("type.", value, 5)) {
00291 const char * id = value + 5;
00292 DPRINTF("User wants gamepad type with id='%s'", id);
00293 smart_ptr<Type> type = m_mgr->getType(id);
00294 if (!type) {
00295 DPRINTF("Bad type? id='%s'", id);
00296 m_dialogId = eDialog_ListPads;
00297 return;
00298 }
00299
00300
00301 m_type = type;
00302
00303
00304 this->verifyTypeMgr();
00305
00306
00307 m_dialogId = eDialog_Calibrate;
00308 std::string name = "Gamepad: ";
00309 name += m_type->getName();
00310 name += ", Device: ";
00311 name += m_device->getPublicName();
00312 m_config = Configurator::create(m_mgr, m_device,
00313 type, name.c_str());
00314 ASSERT(m_config, "failed to create Configurator");
00315 m_currStep = -1;
00316 m_friendly.clear();
00317 }
00318 } else if (eDialog_Calibrate == m_dialogId) {
00319 ASSERT(m_config, "null");
00320 if (!strcmp("type", value)) {
00321
00322 m_dialogId = eDialog_SelectType;
00323 m_config = NULL;
00324 } else if (!strcmp("config", value)) {
00325
00326 m_dialogId = eDialog_Config;
00327 m_config->calibrationComplete();
00328 }
00329 } else if (eDialog_Config == m_dialogId) {
00330 ASSERT(m_config, "null");
00331 if (!strcmp("calibrate", value)) {
00332
00333 m_dialogId = eDialog_Calibrate;
00334 m_config->reset();
00335 m_friendly.clear();
00336 m_currStep = -1;
00337 }
00338 } else if (eDialog_Test == m_dialogId) {
00339 if (!strcmp("home", value)) {
00340
00341 m_dialogId = eDialog_ListPads;
00342 } else if (!strcmp("close", value)) {
00343 m_dialogId = eDialog_Done;
00344 } else if (!strncmp("delete.", value, 7)) {
00345
00346 const char * id = value + 7;
00347 DPRINTF("Want to delete gamepad with id='%s'", id);
00348 m_dialogId = eDialog_DelConfirm;
00349 } else {
00350 DPRINTF("Unrecognized submit: '%s'", value);
00351 }
00352 } else if (eDialog_DelConfirm == m_dialogId) {
00353 if (!strncmp("delete.", value, 7)) {
00354 const char * id = value + 7;
00355 if (m_mgr->deleteGamepad(id)) {
00356 DPRINTF("Success!");
00357 m_dialogId = eDialog_ListPads;
00358 } else {
00359 m_dialogId = eDialog_DelFail;
00360 }
00361 } else {
00362 m_dialogId = eDialog_ListPads;
00363 }
00364 } else if (eDialog_DelFail == m_dialogId) {
00365 if (!strcmp("home", value)) {
00366
00367 m_dialogId = eDialog_ListPads;
00368 }
00369 } else {
00370 DPRINTF("Got reply for unknown dialog?");
00371 m_dialogId = eDialog_ListPads;
00372 }
00373 }
00374
00375
00376
00377 std::string
00378 Host::getDialogDataTS
00379 (
00380 void
00381 )
00382 {
00383 ASSERT(m_mgr, "null");
00384 ASSERT(m_configMgr, "null");
00385
00386 const int bufsize = 256;
00387 char typeBuffer[bufsize];
00388
00389 dialog::ContainerRequest req;
00390 if (eDialog_ListPads == m_dialogId) {
00391
00392 req.addLabel(getString(m_configMgr, "gamepadList"));
00393 req.addLabel("");
00394 int N = m_mgr->getGamepadCount();
00395 if (N < 1) {
00396 req.addLabel(getString(m_configMgr, "noGamepads"));
00397 } else {
00398 for (int i = 0; i < N; ++i) {
00399 smart_ptr<gamepad::Gamepad> pad =
00400 m_mgr->getGamepad(i);
00401 if (!pad)
00402 continue;
00403 const gamepad::Type * type = pad->getType();
00404 if (!type) {
00405 DPRINTF("null gamepad type?");
00406 continue;
00407 }
00408
00409 char buffer[bufsize];
00410 snprintf(buffer, bufsize, "test.%d", i);
00411 req.addButton(buffer,
00412 getTypeString(m_mgr, type, m_locale,
00413 typeBuffer, bufsize));
00414 }
00415 }
00416 req.addLabel("");
00417 req.addButton("newpad", getString(m_configMgr, "newpad"));
00418 req.addLabel("");
00419 req.addButton("close", getString(m_configMgr, "closeMenu"));
00420 m_device = NULL;
00421 m_type = NULL;
00422 } else if (eDialog_SelectSource == m_dialogId) {
00423
00424 int N = m_mgr->getSourceDeviceCount();
00425 if (N < 1) {
00426 req.addLabel("No source devices found!");
00427 req.addLabel("Please plug in a gamepad.");
00428 } else {
00429 req.addLabel(getString(m_configMgr, "selectSource"));
00430 req.addLabel(getString(m_configMgr, "selectSource2"));
00431 req.addLabel("");
00432 req.addLabel(getString(m_configMgr, "selectSource3"));
00433 req.addLabel("");
00434 for (int i = 0; i < N; ++i) {
00435 smart_ptr<gamepad::SourceDevice> dev =
00436 m_mgr->getSourceDevice(i);
00437 if (!dev)
00438 continue;
00439 const char * name = dev->getPublicName();
00440 std::string submit = "src.";
00441 submit += dev->getUniqueId();
00442 req.addButton(submit.c_str(), name);
00443 }
00444 }
00445 req.addLabel("");
00446 req.addButton("home", getString(m_configMgr, "back"));
00447 m_device = NULL;
00448 m_type = NULL;
00449 } else if (eDialog_SelectType == m_dialogId) {
00450 ASSERT(m_device, "null");
00451
00452 req.addLabel(getString(m_configMgr, "selectType"));
00453 req.addLabel("");
00454 int N = m_mgr->getTypeCount();
00455 if (N < 1) {
00456 req.addLabel("No gamepad types supported!");
00457 req.addLabel("This is a bug in the code");
00458 } else {
00459 for (int i = 0; i < N; ++i) {
00460 smart_ptr<Type> type = m_mgr->getType(i);
00461 if (!type)
00462 continue;
00463 std::string submit = "type.";
00464 submit += type->getId();
00465 req.addButton(submit.c_str(),
00466 getTypeString(m_mgr, type, m_locale,
00467 typeBuffer, bufsize));
00468 }
00469 }
00470 req.addLabel("");
00471 req.addButton("src", getString(m_configMgr, "back"));
00472 m_type = NULL;
00473 } else if (eDialog_Calibrate == m_dialogId) {
00474 this->verifyTypeMgr();
00475 req.addLabel(getString(m_configMgr, "calibrating"));
00476 req.addLabel("");
00477 if (addHints(req, m_typeMgr) > 0) {
00478 req.addLabel("");
00479 }
00480
00481 req.addLabel(getString(m_configMgr, "calibrate"));
00482 req.addLabel(getString(m_configMgr, "pressNext"));
00483
00484 req.addLabel("");
00485 dialog::ContainerRequest req2(dialog::ContainerRequest::eAxis_Horizontal);
00486 req2.addButton("type", getString(m_configMgr, "back"));
00487 req2.addButton("config", getString(m_configMgr, "next"));
00488 req.addContainer(req2);
00489 } else if (eDialog_Config == m_dialogId) {
00490 this->verifyTypeMgr();
00491 for (VecString::const_iterator i = m_friendly.begin();
00492 i != m_friendly.end(); ++i) {
00493 req.addLabel(i->c_str());
00494 }
00495
00496 std::string custRequest = "element {\n";
00497 custRequest += "type ";
00498 custRequest += getVgfxSimpleElementName();
00499 custRequest += "\ntypeId ";
00500 custRequest += m_type->getId();
00501 if (m_logical) {
00502 custRequest += "\nflash ";
00503 custRequest += m_logical;
00504 if (m_pulseMain) {
00505 custRequest += "\npulse ";
00506 custRequest += m_type->getMainButton();
00507 }
00508 if ("" != m_direction) {
00509 custRequest += "\ndirection ";
00510 custRequest += m_direction;
00511 }
00512 }
00513 custRequest += "\n}\n";
00514
00515 req.addCustom(custRequest.c_str());
00516 req.addWidthString(s_widthString);
00517 req.addButton("calibrate", getString(m_configMgr, "startOver"));
00518 } else if (eDialog_Test == m_dialogId && m_testingId >= 0) {
00519 this->verifyTypeMgr();
00520 req.addLabel(getString(m_configMgr, "testTitle"));
00521 req.addLabel(getString(m_typeMgr, "friendlyName"));
00522 req.addLabel("");
00523 req.addLabel(getString(m_configMgr, "testInstruct"));
00524 req.addLabel("");
00525
00526 std::string custRequest = "element {\n";
00527 custRequest += "type ";
00528 custRequest += getVgfxTestElementName();
00529 custRequest += "\ngamepadId ";
00530
00531 char buffer[bufsize];
00532 snprintf(buffer, bufsize, "%d", m_testingId);
00533
00534 custRequest += buffer;
00535 custRequest += "\n}\n";
00536
00537 req.addCustom(custRequest.c_str());
00538
00539 dialog::ContainerRequest
00540 req2(dialog::ContainerRequest::eAxis_Horizontal);
00541 req2.addButton("home", getString(m_configMgr, "back"));
00542
00543 req2.addButton("close", getString(m_configMgr, "closeMenu"));
00544 smart_ptr<Gamepad> gp = m_mgr->getGamepad(m_testingId);
00545 if (gp) {
00546 std::string delTag = "delete.";
00547 delTag += gp->getId();
00548 req2.addButton(delTag.c_str(),
00549 getString(m_configMgr, "delete"));
00550 }
00551 req.addContainer(req2);
00552 } else if (eDialog_DelConfirm == m_dialogId) {
00553 req.addLabel(getString(m_configMgr, "delConfirm"));
00554 req.addLabel("");
00555 dialog::ContainerRequest
00556 req2(dialog::ContainerRequest::eAxis_Horizontal);
00557 req2.addButton("home", getString(m_configMgr, "back"));
00558 smart_ptr<Gamepad> gp = m_mgr->getGamepad(m_testingId);
00559 if (gp) {
00560 std::string delTag = "delete.";
00561 delTag += gp->getId();
00562 req2.addButton(delTag.c_str(),
00563 getString(m_configMgr, "delete"));
00564 }
00565 req.addContainer(req2);
00566 } else if (eDialog_DelFail == m_dialogId) {
00567 req.addLabel(getString(m_configMgr, "delFail"));
00568 req.addLabel("");
00569 req.addButton("home", getString(m_configMgr, "back"));
00570 } else if (eDialog_Done == m_dialogId) {
00571
00572 } else {
00573 DPRINTF("ERROR: Bad dialog id: %d", m_dialogId);
00574 m_dialogId = eDialog_ListPads;
00575 return "";
00576 }
00577
00578
00579 return req.get();
00580 }
00581
00582
00583
00584 bool
00585 Host::updateState
00586 (
00587 void
00588 )
00589 {
00590
00591 ++m_counter;
00592 if (0 == (m_counter % 128)) {
00593 return true;
00594 }
00595 if (!m_device)
00596 return false;
00597
00598
00599 if (m_config) {
00600 this->verifyTypeMgr();
00601 config_status_t status;
00602 if (!m_config->update(status)) {
00603 DPRINTF("Done configuring this gamepad!");
00604
00605
00606 smart_ptr<Map> map = m_config->getMapping();
00607 ASSERT(map, "null mapping from configurator");
00608
00609
00610 m_dialogId = eDialog_ListPads;
00611 m_config = NULL;
00612 m_friendly.clear();
00613
00614
00615 smart_ptr<Gamepad> gamepad;
00616 Manager::eResult result =
00617 m_mgr->createGamepad(m_device, map, gamepad);
00618 if (Manager::eResult_Success != result) {
00619 DPRINTF("Failed to create gamepad?");
00620 } else {
00621 DPRINTF("Success!");
00622 }
00623
00624
00625 return true;
00626 }
00627
00628
00629 if (m_currStep != status.currStep) {
00630 m_logical = NULL;
00631 m_pulseMain = false;
00632 m_friendly.clear();
00633 m_currStep = status.currStep;
00634
00635
00636 m_direction = "";
00637 switch (status.instruct) {
00638 case eInstruction_DpadLeft:
00639 case eInstruction_JoyLeft:
00640 m_direction = "left";
00641 break;
00642
00643 case eInstruction_DpadUp:
00644 case eInstruction_JoyUp:
00645 m_direction = "up";
00646 break;
00647
00648 case eInstruction_DpadRight:
00649 m_direction = "right";
00650 break;
00651
00652 case eInstruction_DpadDown:
00653 m_direction = "down";
00654 break;
00655
00656 default: break;
00657 }
00658
00659
00660 std::string friendly = "";
00661 if (eInstruction_RequestControl & status.instruct) {
00662 friendly =
00663 getString(m_typeMgr, status.logical);
00664 friendly += ": ";
00665 m_logical = status.logical;
00666 }
00667 const char * token =
00668 getInstructionToken(status.instruct);
00669 friendly += getString(m_configMgr, token);
00670 m_friendly.push_back(friendly);
00671 if (eInstruction_PressMainAction & status.instruct) {
00672 m_friendly.push_back(
00673 getString(m_typeMgr, "pressMainAction"));
00674 m_pulseMain = true;
00675 }
00676 return true;
00677 }
00678 }
00679
00680
00681 return false;
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 void
00693 Host::verifyTypeMgr
00694 (
00695 void
00696 )
00697 {
00698 if (m_typeMgr)
00699 return;
00700
00701 if (!m_type) {
00702 ASSERT(m_testingId >= 0, "no type and no testing id?");
00703 smart_ptr<Gamepad> gamepad = m_mgr->getGamepad(m_testingId);
00704 ASSERT_THROW(gamepad, "gamepad is now disconnected");
00705 m_type = gamepad->getType();
00706 }
00707 ASSERT(m_type, "null");
00708 m_typeMgr = getTypeLocaleMgr(m_type, m_locale.c_str(),
00709 s_defaultLocale, m_mgr->getDataDirectory());
00710 ASSERT(m_typeMgr, "null");
00711 }
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721 smart_ptr<converse::ConversationHost>
00722 createConfigurationHost
00723 (
00724 IN smart_ptr<Manager>& mgr,
00725 IN int gamepadId
00726 )
00727 {
00728 ASSERT(mgr, "null");
00729
00730 smart_ptr<Host> local = new Host;
00731 ASSERT(local, "out of memory");
00732
00733 local->initialize(mgr, gamepadId);
00734
00735 return local;
00736 }
00737
00738
00739
00740 };
00741