• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

xid_device_config_t.cpp

Go to the documentation of this file.
00001 /* Copyright (c) 2010, Cedrus Corporation
00002  * All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are
00006  * met:
00007  *
00008  * Redistributions of source code must retain the above copyright notice,
00009  * this list of conditions and the following disclaimer.  
00010  *
00011  * Redistributions in binary form must reproduce the above copyright
00012  * notice, this list of conditions and the following disclaimer in the
00013  * documentation and/or other materials provided with the distribution.
00014  *
00015  * Neither the name of Cedrus Corporation nor the names of its
00016  * contributors may be used to endorse or promote products derived from
00017  * this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00022  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00023  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00025  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00029  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00032 #include "xid_device_config_t.h"
00033 #include <Windows.h>
00034 #include <iostream>
00035 
00036 #include "string_tokenizer.hpp"
00037 
00038 boost::shared_ptr<cedrus::xid_device_config_t>
00039     cedrus::xid_device_config_t::config_for_device(
00040         int product_id,
00041         int model_id,
00042         const std::wstring &devconfig_location)
00043 {
00044     boost::shared_ptr<xid_device_config_t> devconfig;
00045     
00046     if(product_id == -99 || model_id == -99)
00047     {
00048         // invalid product or model id
00049         return devconfig;
00050     }
00051 
00052     if(devconfig_location.empty())
00053     {
00054         // no path to devconfig files.  Won't be able to load them so return
00055         // an invalid
00056         return devconfig;
00057     }
00058 
00059     devconfig.reset(new xid_device_config_t(devconfig_location));
00060     
00061     devconfig->load_devconfig(product_id, model_id);
00062 
00063     return devconfig;
00064 }
00065 
00066 cedrus::xid_device_config_t::xid_device_config_t(
00067     const std::wstring &config_file_location)
00068     : config_file_location_(config_file_location),
00069       needs_interbyte_delay_(true),
00070       number_of_lines_(8),
00071       digital_out_prefix_('a')
00072 {
00073 }
00074 
00075 
00076 cedrus::xid_device_config_t::~xid_device_config_t(void)
00077 {
00078 }
00079 
00080 void cedrus::xid_device_config_t::load_devconfig(int product_id, int model_id)
00081 {
00082     std::wstring search_mask = config_file_location_ + L"*.devconfig";
00083     WIN32_FIND_DATA file_info;
00084     HANDLE find_handle = FindFirstFile(
00085         search_mask.c_str(),
00086         &file_info);
00087 
00088     while(find_handle)
00089     {
00090         long device_id = -1;
00091         std::string device_name;
00092         long xid_product_id = -1;
00093         long xid_model_id = -1;
00094         std::string digital_output_command;
00095         std::wstring ignored_ports;
00096 
00097         wchar_t result[1024];
00098 
00099         std::wstring full_file_path = config_file_location_ +
00100             file_info.cFileName;
00101 
00102         xid_product_id = GetPrivateProfileInt(
00103             L"DeviceInfo",
00104             L"XidProductID",
00105             0,
00106             full_file_path.c_str());
00107 
00108         xid_model_id = GetPrivateProfileInt(
00109             L"DeviceInfo",
00110             L"XidModelID",
00111             0,
00112             full_file_path.c_str());
00113 
00114         if(xid_product_id == product_id)
00115         {
00116             // if this is an RB device, make sure the model IDs match
00117             if(product_id == 2 && xid_model_id != model_id)
00118             {
00119                 if(!FindNextFile(find_handle, &file_info))
00120                     break;
00121                 continue;
00122             }
00123             
00124             // we've found the configuration for this device
00125 
00126             // does this device need an interbyte delay?
00127             if(GetPrivateProfileString(
00128                 L"DeviceOptions",
00129                 L"XidNeedsInterByteDelay",
00130                 L"No",
00131                 result,
00132                 sizeof(result),
00133                 full_file_path.c_str()) != 0)
00134             {
00135                 std::wstring byte_delay(result);
00136                 
00137                 if(byte_delay.compare(L"Yes") == 0)
00138                 {
00139                     needs_interbyte_delay_ = true;
00140                 }
00141             }
00142 
00143             // get the digital output prefix
00144             if(GetPrivateProfileString(
00145                 L"DeviceOptions",
00146                 L"XidDigitalOutputCommand",
00147                 L"a",
00148                 result,
00149                 sizeof(result),
00150                 full_file_path.c_str()) != 0)
00151             {
00152                 std::wstring response(result);
00153                 std::string std_response;
00154                 std_response.assign(response.begin(), response.end());
00155                 digital_out_prefix_ = std_response[0];
00156             }
00157             
00158             wchar_t port_str[255];
00159             
00160             // xid devices support up to 255 ports.  In reality, usually only
00161             // 2 or 3 are used
00162             for(int i = 0; i <= 255; ++i)
00163             {
00164                 wsprintf(port_str, L"Port%d", i);
00165 
00166                 int return_size = GetPrivateProfileSection(
00167                     port_str,
00168                     result,
00169                     sizeof(result),
00170                     full_file_path.c_str());
00171                 if(return_size == 0)
00172                 {
00173                     // section not found.  This should be impossible to get to.
00174                     continue;
00175                 }
00176 
00177                 // The result of GetPrivateProfileSection() is a an array of
00178                 // NULL delimited strings.  Here we create a response std::string
00179                 // with the contents of the result[] array with nulls replaced
00180                 // by commas for easier tokenizing.
00181                 std::wstring res_str;
00182                 res_str.reserve(return_size);
00183                 for(int j = 0; j < return_size; ++j)
00184                 {
00185                     if(result[j] != 0)
00186                     {
00187                         res_str.append(1, result[j]);
00188                     }
00189                     else
00190                     {
00191                         if(j != (return_size-1))
00192                             res_str.append(1, L',');
00193                     }
00194                 }
00195 
00196                 // Tokenize the result into Key=Value strings.
00197                 std::vector<std::wstring> key_value_pairs =
00198                     cedrus::tokenize<std::wstring>(res_str,L",");
00199                 
00200                 // turn the Key=Value strings into a std::map
00201                 std::map<std::wstring, std::wstring> res_map;
00202                 for(std::vector<std::wstring>::iterator iter = key_value_pairs.begin();
00203                     iter != key_value_pairs.end(); ++iter)
00204                 {
00205                     std::vector<std::wstring> key_value = 
00206                         cedrus::tokenize<std::wstring>(*iter, L"=");
00207 
00208                     res_map.insert(std::make_pair(key_value[0],key_value[1]));
00209                 }
00210 
00211                 std::map<std::wstring,std::wstring>::iterator found = 
00212                     res_map.find(L"PortName");
00213 
00214                 if(found == res_map.end())
00215                 {
00216                     // no port name found.  Try the next one
00217                     continue;
00218                 }
00219 
00220                 if(found->second.compare(L"Keys") == 0 ||
00221                    found->second.compare(L"Voice Key") == 0 ||
00222                    found->second.compare(L"Event Marker") == 0)
00223                 {
00224                     // found a RB-Series response pad, Lumina system,
00225                     // SV-1 Voice Key, or StimTracker.
00226                     found = res_map.find(L"NumberOfLines");
00227                     if(found != res_map.end())
00228                     {
00229                         number_of_lines_ = _wtoi(found->second.c_str());
00230                     }
00231                 
00232                     // devconfig files have up to 8 key mappings
00233                     for(int i = 1; i <=8; ++i)
00234                     {
00235                         wchar_t key_name[100];
00236                         memset(key_name, 0, sizeof(key_name));
00237                         wsprintf(key_name,L"XidDeviceKeyMap%d", i);
00238                         
00239                         found = res_map.find(std::wstring(key_name));
00240                         if(found != res_map.end())
00241                         {
00242                             int key_num = _wtoi(found->second.c_str());
00243                             key_map_.insert(std::make_pair(i, key_num));
00244                         }
00245                     }
00246                 }
00247                 else
00248                 {
00249                     // no valid port found. Try the next one.
00250                     continue;
00251                 }
00252             }
00253         }
00254 
00255         if(!FindNextFile(find_handle, &file_info))
00256             break;
00257     }
00258 
00259     FindClose(find_handle);
00260 }
00261 
00262 int cedrus::xid_device_config_t::get_mapped_key(int key) const
00263 {
00264     if(key_map_.empty())
00265         return key;
00266 
00267     std::map<int,int>::const_iterator found = 
00268         key_map_.find(key);
00269 
00270     if(found == key_map_.end())
00271         return -1;
00272 
00273     return found->second;
00274 }
00275 
00276 int cedrus::xid_device_config_t::number_of_lines() const
00277 {
00278     return number_of_lines_;
00279 }
00280 
00281 bool cedrus::xid_device_config_t::needs_interbyte_delay() const
00282 {
00283     return needs_interbyte_delay_;
00284 }
00285 
00286 char cedrus::xid_device_config_t::digital_out_prefix() const
00287 {
00288     return digital_out_prefix_;
00289 }

Generated on Wed Dec 15 2010 13:17:12 for XID device library by  doxygen 1.7.2