gamepad-config-dialog.cpp

Go to the documentation of this file.
00001 /*
00002  * gamepad-config-dialog.cpp
00003  *
00004  * Copyright (C) 2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Implementation of gamepad configuration conversation host.
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "gamepad-config-dialog.h"      // always include our own header first
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 //      static helper methods
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 //      Host -- class that implements the gamepad::ConfigurationHost interface
00116 //              to create a set of gamepad configuration dialogs.
00117 //
00118 ////////////////////////////////////////////////////////////////////////////////
00119 
00120 class Host : public converse::ConversationHost {
00121 public:
00122         // constructor, destructor ---------------------------------------------
00123         ~Host(void) throw() { }
00124 
00125         // public class methods ------------------------------------------------
00126         void initialize(IN smart_ptr<Manager>& mgr,
00127                                 IN int gamepadId);
00128 
00129         // converse::ConversationHost class interface methods ------------------
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         // private enums -------------------------------------------------------
00138         enum eDialog {
00139                 eDialog_Done            = 0, // zero means quit dialog
00140                 eDialog_ListPads        = 1, // first dialog: list gamepads
00141                 eDialog_SelectSource    = 2, // allow player to select source
00142                 eDialog_SelectType      = 3, // player selects gamepad type
00143                 eDialog_Calibrate       = 4, // calibrating device
00144                 eDialog_Config          = 5, // using configurator
00145                 eDialog_Test            = 6, // testing a gamepad
00146                 eDialog_DelConfirm      = 7, // really want to delete?
00147                 eDialog_DelFail         = 8, // couldn't delete gamepad?
00148 
00149                 // keep this last!
00150                 eDialog_Invalid         = -1
00151         };
00152 
00153         // private helper methods ----------------------------------------------
00154         void verifyTypeMgr(void);
00155 
00156         // private member data -------------------------------------------------
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;      // current logical control
00167         eDialog                 m_dialogId;     // current dialog ID
00168         int                     m_currStep;
00169         int                     m_testingId;
00170         int                     m_counter;
00171         bool                    m_pulseMain;    // pulse main button?
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         // load i18n manager for basic config strings
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 //      Host -- converse::ConversationHost class interface methods
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         //dumpHash("Gamepad dialog reply", reply);
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                         // player wants to test a gamepad!
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;  // start over!
00278                                 return;
00279                         }
00280 
00281                         // okay, remember this source device
00282                         m_device = device;
00283 
00284                         // next step: pick a gamepad type
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;  // start over!
00297                                 return;
00298                         }
00299 
00300                         // okay, remember this type
00301                         m_type = type;
00302 
00303                         // load i18n manager for this type
00304                         this->verifyTypeMgr();
00305 
00306                         // next step: calibration!
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                         // back up!
00322                         m_dialogId = eDialog_SelectType;
00323                         m_config = NULL;
00324                 } else if (!strcmp("config", value)) {
00325                         // move forward...
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                         // back up!
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                         // back to home screen
00341                         m_dialogId = eDialog_ListPads;
00342                 } else if (!strcmp("close", value)) {
00343                         m_dialogId = eDialog_Done;
00344                 } else if (!strncmp("delete.", value, 7)) {
00345                         // delete this gamepad!
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                         // back to home screen
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                 // construct dialog showing all discovered gamepads
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;       // skip
00403                                 const gamepad::Type * type = pad->getType();
00404                                 if (!type) {
00405                                         DPRINTF("null gamepad type?");
00406                                         continue;       // skip
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                 // construct dialog showing all source devices
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;       // skip
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                 // construct dialog showing all gamepad types
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;       // skip
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                 // do nothing
00572         } else {
00573                 DPRINTF("ERROR: Bad dialog id: %d", m_dialogId);
00574                 m_dialogId = eDialog_ListPads;
00575                 return "";
00576         }
00577 
00578         // return whatever dialog we've constructed
00579         return req.get();
00580 }
00581 
00582 
00583 
00584 bool
00585 Host::updateState
00586 (
00587 void
00588 )
00589 {
00590         // occasionally return true just to make sure we have correct state
00591         ++m_counter;
00592         if (0 == (m_counter % 128)) {
00593                 return true;
00594         }
00595         if (!m_device)
00596                 return false;   // nothing to do
00597 
00598         // have a configurator?
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                         // get mapping
00606                         smart_ptr<Map> map = m_config->getMapping();
00607                         ASSERT(map, "null mapping from configurator");
00608 
00609                         // reset our internal state
00610                         m_dialogId = eDialog_ListPads;
00611                         m_config = NULL;
00612                         m_friendly.clear();
00613 
00614                         // now create gamepad object
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                         // all done
00625                         return true;
00626                 }
00627 
00628                 // have we changed steps?
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                         // need to specify direction?
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                         // construct new friendly string
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;    // caller should refresh dialog!
00677                 }
00678         }
00679 
00680         // default exit: no change
00681         return false;
00682 }
00683 
00684 
00685 
00686 ////////////////////////////////////////////////////////////////////////////////
00687 //
00688 //      Host -- private helper methods
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 //      public API
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 };      // gamepad namespace
00741