All Classes Namespaces Files Functions Variables Enumerations Enumerator
libs/controller/UsbJoystick.cpp
Go to the documentation of this file.
00001 
00010 #include "UsbJoystick.h"
00011 #include "SdlJoystickInit.h"
00012 #include <SDL.h>
00013 #include <SDL_joystick.h>
00014 #include <vector>
00015 #include <string>
00016 
00017 using namespace qrk;
00018 using namespace std;
00019 
00020 
00021 struct UsbJoystick::pImpl : private SdlJoystickInit
00022 {
00024   class JoystickGroup
00025   {
00026   public:
00027 
00029     class JoystickInfo
00030     {
00031     public:
00032       SDL_Joystick* ptr_;
00033       int own_index_;
00034       vector<short> axis_value_;
00035       vector<bool> button_value_;
00036 
00037       JoystickInfo(void) : ptr_(NULL), own_index_(-1)
00038       {
00039       }
00040     };
00041     vector<JoystickInfo> js_;
00042 
00043     static JoystickGroup* object(void)
00044     {
00045       static JoystickGroup singleton_object;
00046       return &singleton_object;
00047     }
00048   };
00049 
00050   JoystickGroup* joysticks_;
00051   string error_message_;
00052   size_t own_id_;
00053   size_t axis_num_;
00054   size_t buttons_num_;
00055 
00056   pImpl(void)
00057     : joysticks_(JoystickGroup::object()), error_message_("no error"),
00058       own_id_(joysticks_->js_.size()), axis_num_(0), buttons_num_(0)
00059   {
00060     JoystickGroup::JoystickInfo joystick_info_;
00061     joysticks_->js_.push_back(joystick_info_);
00062   }
00063 
00064 
00065   bool connect(int index)
00066   {
00067     if (SDL_JoystickOpened(index)) {
00068       error_message_ = "already connected.";
00069       return false;
00070     }
00071 
00072     SDL_Joystick* p = SDL_JoystickOpen(index);
00073     if (p == NULL) {
00074       error_message_ = SDL_GetError();
00075       return false;
00076     }
00077     joysticks_->js_[own_id_].ptr_ = p;
00078     joysticks_->js_[own_id_].own_index_ = index;
00079     axis_num_ = SDL_JoystickNumAxes(p);
00080     buttons_num_ = SDL_JoystickNumButtons(p);
00081     for (size_t i = 0; i < axis_num_; ++i) {
00082       joysticks_->js_[own_id_].axis_value_.push_back(0);
00083     }
00084     for (size_t i = 0; i < buttons_num_; ++i) {
00085       joysticks_->js_[own_id_].button_value_.push_back(false);
00086     }
00087     return true;
00088   }
00089 
00090 
00091   void joyAxisEventHandler(SDL_JoyAxisEvent& event)
00092   {
00093     joysticks_->js_[event.which].axis_value_[event.axis] = event.value;
00094   }
00095 
00096 
00097   void joyButtonEventHandler(SDL_JoyButtonEvent& event)
00098   {
00099     joysticks_->js_[event.which].button_value_[event.button] =
00100       (event.state == SDL_PRESSED) ? true : false;
00101   }
00102 };
00103 
00104 
00105 UsbJoystick::UsbJoystick(void) : pimpl(new pImpl)
00106 {
00107 }
00108 
00109 
00110 UsbJoystick::~UsbJoystick(void)
00111 {
00112   disconnect();
00113 }
00114 
00115 
00116 const char* UsbJoystick::what(void) const
00117 {
00118   return pimpl->error_message_.c_str();
00119 }
00120 
00121 
00122 bool UsbJoystick::connect(int id)
00123 {
00124   if (id >= 0) {
00125     return pimpl->connect(id);
00126 
00127   } else {
00128     size_t n = joystickNum();
00129     if (n <= 0) {
00130       pimpl->error_message_ = "No joystick device.";
00131       return false;
00132     }
00133     for (size_t i = 0; i < n; ++i) {
00134       if (pimpl->connect(i)) {
00135         return true;
00136       }
00137     }
00138   }
00139   pimpl->error_message_ = "Joystick devices are full connected.";
00140   return false;
00141 }
00142 
00143 
00144 void UsbJoystick::disconnect(void)
00145 {
00146   if (isConnected()) {
00147     SDL_JoystickClose(pimpl->joysticks_->js_[pimpl->own_id_].ptr_);
00148   }
00149 }
00150 
00151 
00152 bool UsbJoystick::isConnected(void) const
00153 {
00154   return (pimpl->joysticks_->js_[pimpl->own_id_].ptr_ == NULL) ? false : true;
00155 }
00156 
00157 
00158 size_t UsbJoystick::axisNum(void) const
00159 {
00160   return pimpl->axis_num_;
00161 }
00162 
00163 
00164 int UsbJoystick::axisValue(size_t index)
00165 {
00166   if (! isConnected()) {
00167     pimpl->error_message_ = "not connected.";
00168     return 0;
00169   }
00170   return pimpl->joysticks_->js_[pimpl->own_id_].axis_value_[index];
00171 }
00172 
00173 
00174 size_t UsbJoystick::buttonsNum(void) const
00175 {
00176   return pimpl->buttons_num_;
00177 }
00178 
00179 
00180 bool UsbJoystick::isButtonPressed(size_t index)
00181 {
00182   if (! isConnected()) {
00183     pimpl->error_message_ = "not connected.";
00184     return 0;
00185   }
00186   return pimpl->joysticks_->js_[pimpl->own_id_].button_value_[index];
00187 }
00188 
00189 
00190 size_t UsbJoystick::joystickNum(void)
00191 {
00192   return SDL_NumJoysticks();
00193 }
00194 
00195 
00196 void UsbJoystick::setEvent(void* event)
00197 {
00198   SDL_Event* sdl_event = static_cast<SDL_Event*>(event);
00199   switch (sdl_event->type) {
00200 
00201   case SDL_JOYAXISMOTION:
00202     pimpl->joyAxisEventHandler(sdl_event->jaxis);
00203     break;
00204 
00205 #if 0
00206   case SDL_JOYBALLMOTION:
00207     pimpl->joyBallEventHandler(event.jball);
00208     break;
00209 
00210   case SDL_JOYHATMOTION:
00211     pimpl->joyHatEventHandler(event.jhat);
00212     break;
00213 #endif
00214 
00215   case SDL_JOYBUTTONDOWN:
00216   case SDL_JOYBUTTONUP:
00217     pimpl->joyButtonEventHandler(sdl_event->jbutton);
00218     break;
00219   }
00220 }