00001 #include "ControlBase.h"
00002 #include "Motion/MMAccessor.h"
00003 #include "Shared/Config.h"
00004 #ifdef TGT_HAS_LEDS
00005 # include "Motion/LedMC.h"
00006 #endif
00007 #include "Shared/string_util.h"
00008 #include "Sound/SoundManager.h"
00009 #include "Wireless/Wireless.h"
00010 #include <iomanip>
00011 #include <sstream>
00012
00013 ControlBase * ControlBase::activate(MC_ID display, Socket * gui) {
00014 display_id=display;
00015 gui_comm=gui;
00016 hilightFirst();
00017 refresh();
00018 return this;
00019 }
00020
00021 void ControlBase::pause() {
00022 if(doRewrite) {
00023 doRewrite=false;
00024 }
00025 }
00026
00027 void ControlBase::refresh() {
00028
00029 #ifdef TGT_HAS_LEDS
00030 if(display_id!=invalid_MC_ID) {
00031 if(hilights.size()>0) {
00032 MMAccessor<LedMC> display(display_id);
00033 unsigned int cur=hilights.front();
00034 if(options.size()<=10)
00035 display.mc()->displayNumber(cur,LedEngine::onedigit);
00036 else
00037 display.mc()->displayNumber(cur,LedEngine::twodigit);
00038 }
00039 }
00040 #endif
00041
00042
00043 if(gui_comm==NULL || !wireless->isConnected(gui_comm->sock)) {
00044 #ifndef PLATFORM_APERIOS
00045 if(!wireless->isConnected(sout->sock))
00046 return;
00047 #endif
00048
00049 const char * const nosel=" ";
00050 const char * slctd="**";
00051 if(config->main.use_VT100) {
00052 slctd="\33[1m**\33[0m";
00053 if(doRewrite)
00054 clearMenu();
00055 sout->printf("\33[1m%s\33[0m:\n",getName().c_str());
00056 } else
00057 sout->printf("%s:\n",getName().c_str());
00058 unsigned int digits=0;
00059 for(unsigned int i=1; i<options.size(); i*=10)
00060 digits++;
00061 for(unsigned int i=0; i<options.size(); i++) {
00062 if(options[i]==NULL)
00063 for(unsigned int j=0; j<strlen(nosel)+digits+2; j++)
00064 sout->printf(" ");
00065 else
00066 sout->printf("%s%*d%s ",(find(hilights.begin(),hilights.end(),i)!=hilights.end()?slctd:nosel),digits,i,(options[i]->slotsSize()>0?">":"."));
00067
00068 sout->printf("%s\n",getSlotName(i).c_str());
00069 }
00070 if(options.size()==0)
00071 sout->printf(" Empty menu\n");
00072 doRewrite=true;
00073 } else {
00074
00075
00076
00077
00078 std::stringstream ss;
00079 ss << "refresh\n"
00080 << getName() << '\n'
00081 << options.size() << '\n';
00082 for(unsigned int i=0; i<options.size(); i++) {
00083 if(options[i]==NULL)
00084 ss << "0\n0\n----------\n0\n\n";
00085 else {
00086 std::string desc = options[i]->getDescription();
00087 ss << options[i]->options.size() << '\n'
00088 << (binary_search(hilights.begin(),hilights.end(),i)?1:0) << '\n'
00089 << options[i]->getName() << '\n'
00090 << std::count(desc.begin(),desc.end(),'\n') << '\n'
00091 << desc << '\n';
00092 }
00093 }
00094
00095
00096 gui_comm->write((const byte*)ss.str().c_str(),ss.str().size());
00097
00098
00099
00100 }
00101 }
00102
00103 void ControlBase::deactivate() {
00104 hilights.clear();
00105 #ifdef TGT_HAS_LEDS
00106 if(display_id!=invalid_MC_ID) {
00107 MMAccessor<LedMC> display(display_id);
00108 display.mc()->clear();
00109 }
00110 #endif
00111 if(doRewrite) {
00112 if(config->main.use_VT100)
00113 clearMenu();
00114 doRewrite=false;
00115 }
00116 display_id=invalid_MC_ID;
00117 }
00118
00119 ControlBase* ControlBase::doSelect() {
00120
00121
00122 if(hilights.size()==0) {
00123 sndman->playFile(config->controller.select_snd);
00124 return this;
00125 }
00126 for(unsigned int i=0;i<hilights.size();i++) {
00127 unsigned int cur=hilights[i];
00128 if(cur>=options.size() || options[cur]==NULL) {
00129 #ifdef TGT_HAS_LEDS
00130 if(display_id!=invalid_MC_ID) {
00131 MMAccessor<LedMC> display(display_id);
00132 display.mc()->cflash(FaceLEDMask,.5f,100);
00133 }
00134 #endif
00135 if(cur>=options.size())
00136 sout->printf("Invalid choice\n");
00137 else
00138 sout->printf("NULL option\n");
00139 continue;
00140 }
00141 #ifdef TGT_HAS_LEDS
00142 if(display_id!=invalid_MC_ID) {
00143 MMAccessor<LedMC> display(display_id);
00144 display.mc()->flash(FaceLEDMask,100);
00145 display.mc()->clear();
00146 }
00147 #endif
00148 if(doRewrite) {
00149 if(config->main.use_VT100)
00150 clearMenu();
00151 doRewrite=false;
00152 }
00153 sndman->playFile(config->controller.select_snd);
00154 if(hilights.size()>1) {
00155 options[cur]->activate(display_id,gui_comm);
00156 options[cur]->deactivate();
00157 }
00158 }
00159 if(hilights.size()==1)
00160 return options[hilights.front()];
00161 return this;
00162 }
00163
00164 ControlBase* ControlBase::doNextItem() {
00165
00166 if(options.size()==0)
00167 return this;
00168 unsigned int cur=0;
00169 for(unsigned int i=0; i<hilights.size(); i++)
00170 if(hilights[i]>=cur)
00171 cur=(hilights[i]+1)%options.size();
00172 while(options[cur]==NULL)
00173 cur=(cur+1)%options.size();
00174 hilights.clear();
00175 hilights.push_back(cur);
00176 sndman->playFile(config->controller.next_snd);
00177 refresh();
00178
00179 return this;
00180 }
00181
00182 ControlBase* ControlBase::doPrevItem() {
00183
00184 if(options.size()==0)
00185 return this;
00186 unsigned int cur=options.size()-1;
00187 for(unsigned int i=hilights.size(); i>0; i--)
00188 if(hilights[i-1]<=cur)
00189 cur=(hilights[i-1]+options.size()-1)%options.size();
00190 while(options[cur]==NULL)
00191 cur=(cur+options.size()-1)%options.size();
00192 hilights.clear();
00193 hilights.push_back(cur);
00194 sndman->playFile(config->controller.prev_snd);
00195 refresh();
00196
00197 return this;
00198 }
00199
00200 ControlBase * ControlBase::doCancel() {
00201 sndman->playFile(config->controller.cancel_snd);
00202 return NULL;
00203 }
00204
00205
00206 ControlBase* ControlBase::doReadStdIn(const std::string& prompt) {
00207
00208 #ifdef TGT_HAS_LEDS
00209 if(display_id!=invalid_MC_ID) {
00210 MMAccessor<LedMC> display(display_id);
00211 display.mc()->cset(FaceLEDMask,.5f);
00212 }
00213 #endif
00214 sndman->playFile(config->controller.read_snd);
00215
00216
00217 if(gui_comm==NULL || !wireless->isConnected(gui_comm->sock)) {
00218
00219 if(prompt.size()>0)
00220 sout->printf("%s\n",prompt.c_str());
00221 sout->printf("#> ");
00222 if(!wireless->isConnected(sout->sock)) {
00223 std::string choice;
00224 std::cin >> choice;
00225 std::cout << std::endl;
00226 return takeInput(choice);
00227 }
00228 return this;
00229 } else {
00230
00231 if(prompt.size()>0) {
00232 unsigned int lines=std::count(prompt.begin(),prompt.end(),'\n');
00233 gui_comm->printf("status\n%u\n%s\n",lines,prompt.c_str());
00234 }
00235 return this;
00236 }
00237 }
00238
00239 ControlBase* ControlBase::takeInput(const std::string& str) {
00240 std::vector<std::string> args;
00241 std::vector<unsigned int> offsets;
00242 if(!string_util::parseArgs(str,args,offsets)) {
00243 serr->printf("ControlBase::takeInput(\"%s\") was not understood.\n",str.c_str());
00244 refresh();
00245 return this;
00246 } else {
00247
00248 if(args.size()==0) {
00249 refresh();
00250 return this;
00251 }
00252
00253 unsigned int choice=-1U;
00254 bool ambiguous=false;
00255 for(unsigned int i=0; i<options.size(); i++) {
00256 if(options[i]!=NULL && options[i]->name == args[0]) {
00257 if(choice==-1U)
00258 choice=i;
00259 else
00260 ambiguous=true;
00261 }
00262 }
00263
00264 if(!ambiguous && choice==-1U) {
00265 std::string argname=string_util::makeLower(args[0]);
00266 for(unsigned int i=0; i<options.size(); i++) {
00267 if(options[i]!=NULL) {
00268 std::string optname=string_util::makeLower(options[i]->name);
00269 if(optname.compare(0,argname.size(),argname)==0) {
00270 if(choice==-1U)
00271 choice=i;
00272 else
00273 ambiguous=true;
00274 }
00275 }
00276 }
00277 }
00278
00279 if(ambiguous || choice==-1U) {
00280 char* endp=NULL;
00281 choice=strtol(args[0].c_str(),&endp,10);
00282 if(endp==NULL || endp==args[0].c_str()) {
00283 if(config->main.use_VT100) {
00284 sout->printf("\r\33[1A");
00285 clearMenu();
00286 doRewrite=false;
00287 }
00288 return invalidInput(str,ambiguous);
00289 } else if(choice<options.size() && options[choice]!=NULL) {
00290 ambiguous=false;
00291 } else {
00292 if(config->main.use_VT100) {
00293 sout->printf("\r\33[1A");
00294 clearMenu();
00295 doRewrite=false;
00296 }
00297 return invalidInput(str,ambiguous);
00298 }
00299 }
00300
00301 if(args.size()>1)
00302 return options[choice]->takeInput(str.substr(offsets[1]));
00303 else {
00304 hilights.clear();
00305 hilights.push_back(choice);
00306 return doSelect();
00307 }
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 return this;
00348 }
00349
00350 bool ControlBase::validInput(const std::string& str) {
00351 unsigned int choice=atoi(str.c_str());
00352 return (choice<options.size() && options[choice]!=NULL);
00353 }
00354
00355 ControlBase* ControlBase::findSlot(const std::string& slotName) const {
00356
00357 for(unsigned int i=0; i<options.size(); i++) {
00358 if(options[i]!=NULL && options[i]->name.compare(0,slotName.size(),slotName)==0)
00359 return options[i];
00360 }
00361
00362 std::string argname=string_util::makeLower(slotName);
00363 bool ambiguous=false;
00364 unsigned int choice=-1U;
00365 for(unsigned int i=0; i<options.size(); i++) {
00366 if(options[i]!=NULL) {
00367 std::string optname=string_util::makeLower(options[i]->name);
00368 if(optname.compare(0,argname.size(),argname)==0) {
00369 if(choice==-1U)
00370 choice=i;
00371 else
00372 ambiguous=true;
00373 }
00374 }
00375 }
00376
00377 if(ambiguous || choice==-1U) {
00378 char* endp=NULL;
00379 choice=strtol(slotName.c_str(),&endp,10);
00380 if(endp==NULL || endp==slotName.c_str()) {
00381 return NULL;
00382 } else if(choice<options.size() && options[choice]!=NULL) {
00383 ambiguous=false;
00384 } else {
00385 return NULL;
00386 }
00387 }
00388 return ambiguous ? NULL : options[choice];
00389 }
00390
00391 std::string ControlBase::getSlotName(unsigned int i) const {
00392 if(options[i]!=NULL)
00393 return options[i]->getName();
00394 else {
00395 static std::string dashes("----------");
00396 return dashes;
00397 }
00398 }
00399
00400
00401 void ControlBase::setSlot(unsigned int i,ControlBase* o) {
00402 while(options.size()<=i)
00403 options.push_back(NULL);
00404 options[i]=o;
00405 }
00406
00407 void ControlBase::pushSlot(ControlBase* o) {
00408 options.push_back(o);
00409 }
00410
00411 void ControlBase::clearSlots() {
00412 for(unsigned int i=0; i<options.size(); i++)
00413 delete options[i];
00414 options.clear();
00415 hilights.clear();
00416 }
00417
00418 void ControlBase::setHilights(const std::vector<unsigned int>& hi) {
00419 float avg=hilightsAvg();
00420 hilights.clear();
00421 for(unsigned int i=0; i<hi.size(); i++)
00422 if(hi[i]<options.size())
00423 hilights.push_back(hi[i]);
00424 float newavg=hilightsAvg();
00425 if(avg!=-1 || newavg!=-1) {
00426 if(avg<=newavg)
00427 sndman->playFile(config->controller.next_snd);
00428 else
00429 sndman->playFile(config->controller.prev_snd);
00430 }
00431 refresh();
00432 }
00433
00434 void ControlBase::hilightFirst() {
00435 hilights.clear();
00436 for(unsigned int i=0; i<options.size(); i++)
00437 if(options[i]!=NULL) {
00438 hilights.push_back(i);
00439 return;
00440 }
00441 }
00442
00443 ControlBase* ControlBase::registerControllerEntry(ControlBase* c, const std::string& menu, int flags) {
00444 ControlRegistry_t& reg = getControllerEntries();
00445 bool isnew = reg.find(menu)==reg.end() || reg[menu].find(c->getName())==reg[menu].end();
00446 reg[menu][c->getName()] = std::make_pair(c,flags);
00447 if(!isnew)
00448 std::cerr << "Warning: duplicate registation for " << c->getName() << " in Controller menu " << menu << std::endl;
00449 return c;
00450 }
00451
00452 void ControlBase::clearMenu() {
00453 if(config->main.use_VT100) {
00454 sout->printf("\r\33[%luA",(unsigned long)(options.size()+1));
00455 sout->printf("\33[J");
00456 }
00457 }
00458
00459 ControlBase* ControlBase::invalidInput(const std::string& msg, bool ambiguous) {
00460 if(ambiguous)
00461 serr->printf("ControlBase(\"%s\")::takeInput(\"%s\") was ambiguous\n",name.c_str(),msg.c_str());
00462 else
00463 serr->printf("ControlBase(\"%s\")::takeInput(\"%s\") was not a valid index or option name.\n",name.c_str(),msg.c_str());
00464 refresh();
00465 return this;
00466 }
00467
00468 float ControlBase::hilightsAvg() const {
00469 if(hilights.size()==0)
00470 return -1;
00471 unsigned int total=0;
00472 for(unsigned int i=0; i<hilights.size(); i++)
00473 total+=hilights[i];
00474 return (float)total/(float)hilights.size();
00475 }
00476
00477
00478
00479
00480
00481
00482