00001 #include "MMCombo.h"
00002 #include "Shared/WorldState.h"
00003 #include "Shared/Profiler.h"
00004 #include "Shared/debuget.h"
00005 #include "Shared/Config.h"
00006 #include "Shared/SharedObject.h"
00007 #include "Shared/ProcessID.h"
00008 #include "Events/EventRouter.h"
00009 #include "Behaviors/BehaviorBase.h"
00010 #include "Motion/MotionManager.h"
00011 #include "SoundPlay/SoundManager.h"
00012 #include "Vision/Vision.h"
00013 #include "Events/TextMsgEvent.h"
00014 #include "Shared/WMclass.h"
00015
00016 #include "Shared/ERS210Info.h"
00017 #include "Shared/ERS220Info.h"
00018
00019 #include <OPENR/OSyslog.h>
00020 #include <OPENR/core_macro.h>
00021 #include <OPENR/OFbkImage.h>
00022
00023 using namespace std;
00024
00025 extern BehaviorBase& startupBehavior;
00026
00027 MMCombo::MMCombo()
00028 : OObject(), motmanMemRgn(NULL), worldStateMemRgn(NULL),
00029 soundManagerMemRgn(NULL), eventTranslatorQueueMemRgn(NULL),
00030 runLevel(0), num_open(0), etrans(), RPOPENR_isready(true), isStopped(true)
00031 {
00032 for(unsigned int i=0; i<NumOutputs; i++) {
00033 primIDs[i]=oprimitiveID_UNDEF;
00034 open[i]=false;
00035 }
00036 Profiler::initBuckets();
00037 }
00038
00039
00040 OStatus
00041 MMCombo::DoInit(const OSystemEvent&)
00042 {
00043 isStopped=false;
00044
00045 NEW_ALL_SUBJECT_AND_OBSERVER;
00046 REGISTER_ALL_ENTRY;
00047 SET_ALL_READY_AND_NOTIFY_ENTRY;
00048
00049
00050 observer[obsReceiveWorldState]->SetBufCtrlParam(0,1,1);
00051 observer[obsReceiveMotionManager]->SetBufCtrlParam(0,1,1);
00052 observer[obsMotionManagerComm]->SetBufCtrlParam(0,1,MotionManager::MAX_MOTIONS+1);
00053
00054
00055
00056 config=new Config("/ms/config/tekkotsu.cfg");
00057
00058 erouter = new EventRouter;
00059
00060 if(strcmp(objectName,"MainObj")==0) {
00061 ProcessID::setID(ProcessID::MainProcess);
00062
00063 bool isSlowOutput[NumOutputs];
00064 for(unsigned int i=0; i<NumOutputs; i++)
00065 isSlowOutput[i]=!IsFastOutput[i];
00066
00067 SetupOutputs(isSlowOutput);
00068
00069
00070 OPowerStatus observationStatus;
00071 observationStatus.Set(orsbALL,obsbALL,opsoREMAINING_CAPACITY_NOTIFY_EVERY_CHANGE,opsoTEMPERATURE_NOTIFY_EVERY_CHANGE,opsoTIME_DIF_NOTIFY_EVERY_CHANGE,opsoVOLUME_NOTIFY_EVERY_CHANGE);
00072 OServiceEntry entry(myOID_, Extra_Entry[entryGotPowerEvent]);
00073 OStatus result = OPENR::ObservePowerStatus(observationStatus, entry);
00074 if(result != oSUCCESS) {
00075 OSYSLOG1((osyslogERROR, "%s : %s %d","MMCombo::DoStart()","OPENR::ObservePowerStatus() FAILED", result));
00076 return oFAIL;
00077 }
00078
00079
00080 wireless = new Wireless();
00081 sout=wireless->socket(SocketNS::SOCK_STREAM,Wireless::WIRELESS_DEF_RECV_SIZE,Wireless::WIRELESS_DEF_SEND_SIZE*6);
00082 serr=wireless->socket(SocketNS::SOCK_STREAM,Wireless::WIRELESS_DEF_RECV_SIZE,Wireless::WIRELESS_DEF_SEND_SIZE*2);
00083 wireless->setDaemon(sout);
00084 wireless->setDaemon(serr);
00085 serr->setFlushType(SocketNS::FLUSH_BLOCKING);
00086 sout->setTextForward();
00087 serr->setForward(sout);
00088
00089
00090 worldStateMemRgn = InitRegion(sizeof(WorldState));
00091 state=new ((WorldState*)worldStateMemRgn->Base()) WorldState;
00092
00093
00094 eventTranslatorQueueMemRgn = InitRegion(sizeof(EventTranslator::Queue_t));
00095 EventTranslator::Queue_t * etransq=new ((EventTranslator::Queue_t*)eventTranslatorQueueMemRgn->Base()) EventTranslator::Queue_t;
00096 etrans.setQueue(etransq);
00097 MotionCommand::setQueue(etransq);
00098
00099
00100 vision=new Vision();
00101
00102 vision->enableEvents(VisionEventNS::PinkBallSID);
00103 vision->enableEvents(VisionEventNS::RedBallSID);
00104 vision->enableEvents(VisionEventNS::MarkersSID);
00105
00106 }
00107 if(strcmp(objectName,"MotoObj")==0) {
00108 ProcessID::setID(ProcessID::MotionProcess);
00109
00110 SetupOutputs(IsFastOutput);
00111 OPENR::SetMotorPower(opowerON);
00112 OPENR::EnableJointGain(oprimitiveID_UNDEF);
00113
00114
00115 motmanMemRgn = InitRegion(sizeof(MotionManager));
00116 motman = new (motmanMemRgn->Base()) MotionManager();
00117 motman->InitAccess(subject[sbjMotionManagerComm]);
00118 }
00119 startupBehavior.AddReference();
00120 return oSUCCESS;
00121 }
00122
00123 OStatus
00124 MMCombo::DoStart(const OSystemEvent&)
00125 {
00126
00127
00128
00129
00130 if(strcmp(objectName,"MainObj")==0) {
00131 wireless->listen(sout, config->main.console_port);
00132 wireless->listen(serr, config->main.stderr_port);
00133 OPowerStatus power;
00134 OPENR::GetPowerStatus(&power);
00135 state->read(power,erouter);
00136 }
00137
00138 isStopped=false;
00139
00140 ENABLE_ALL_SUBJECT;
00141 ASSERT_READY_TO_ALL_OBSERVER;
00142
00143 addRunLevel();
00144
00145 return oSUCCESS;
00146 }
00147
00148 OStatus
00149 MMCombo::DoStop(const OSystemEvent&)
00150 {
00151 cout << objectName << "::DoStop()..." << endl;
00152 if(strcmp(objectName,"MainObj")==0) {
00153 startupBehavior.DoStop();
00154 wireless->close(sout);
00155 wireless->close(serr);
00156 }
00157 DISABLE_ALL_SUBJECT;
00158 DEASSERT_READY_TO_ALL_OBSERVER;
00159 isStopped=true;
00160 cout << objectName << "::DoStop()-DONE" << endl;
00161 return oSUCCESS;
00162 }
00163
00164 OStatus
00165 MMCombo::DoDestroy(const OSystemEvent&)
00166 {
00167 cout << objectName << "::DoDestroy()..." << endl;
00168 startupBehavior.RemoveReference();
00169 if(strcmp(objectName,"MainObj")==0) {
00170 delete erouter;
00171 motmanMemRgn->RemoveReference();
00172 }
00173 if(strcmp(objectName,"MotoObj")==0) {
00174 worldStateMemRgn->RemoveReference();
00175 eventTranslatorQueueMemRgn->RemoveReference();
00176 }
00177 soundManagerMemRgn->RemoveReference();
00178 DELETE_ALL_SUBJECT_AND_OBSERVER;
00179 cout << objectName << "::DoDestroy()-DONE" << endl;
00180 return oSUCCESS;
00181 }
00182
00183
00184
00185
00186 void
00187 MMCombo::ReadyRegisterWorldState(const OReadyEvent&){
00188 static bool is_init=true;
00189 if(is_init) {
00190 is_init=false;
00191 cout << objectName << " Registering WorldState" << endl;
00192 if(strcmp(objectName,"MainObj")==0) {
00193 subject[sbjRegisterWorldState]->SetData(worldStateMemRgn);
00194 subject[sbjRegisterWorldState]->NotifyObservers();
00195 }
00196 }
00197 }
00198
00199 void
00200 MMCombo::GotWorldState(const ONotifyEvent& event){
00201 cout << objectName << "-GOTWORLDSTATE..." << flush;
00202
00203 if(strcmp(objectName,"MotoObj")==0) {
00204 ASSERT(event.NumOfData()==1,"Too many WorldStates");
00205 worldStateMemRgn = event.RCData(0);
00206 worldStateMemRgn->AddReference();
00207 state = reinterpret_cast<WorldState*>(worldStateMemRgn->Base());
00208 }
00209 observer[obsReceiveWorldState]->AssertReady();
00210 cout << "done" << endl;
00211 }
00212
00213
00214
00215
00216
00217 void
00218 MMCombo::ReadyRegisterMotionManager(const OReadyEvent&){
00219 static bool is_init=true;
00220 if(is_init) {
00221 is_init=false;
00222 cout << objectName << " Registering MotionManager" << endl;
00223 if(strcmp(objectName,"MotoObj")==0) {
00224 subject[sbjRegisterMotionManager]->SetData(motmanMemRgn);
00225 subject[sbjRegisterMotionManager]->NotifyObservers();
00226 }
00227 }
00228 }
00229
00230 void
00231 MMCombo::GotMotionManager(const ONotifyEvent& event){
00232 cout << objectName << "-GOTWORLDSTATE..." << flush;
00233
00234 if(strcmp(objectName,"MainObj")==0) {
00235 ASSERT(event.NumOfData()==1,"Too many MotionManagers");
00236 motmanMemRgn = event.RCData(0);
00237 motmanMemRgn->AddReference();
00238 motman = reinterpret_cast<MotionManager*>(motmanMemRgn->Base());
00239 cout << "MAIN INIT MOTMAN..." << flush;
00240
00241 motman->InitAccess(subject[sbjMotionManagerComm]);
00242 addRunLevel();
00243 }
00244 observer[obsReceiveMotionManager]->AssertReady();
00245 cout << "done" << endl;
00246 }
00247
00248
00249
00250
00251 void
00252 MMCombo::ReadyRegisterEventTranslatorQueue(const OReadyEvent&){
00253 static bool is_init=true;
00254 if(is_init) {
00255 is_init=false;
00256 cout << objectName << " Registering EventTranslatorQueue" << endl;
00257 if(strcmp(objectName,"MainObj")==0) {
00258 subject[sbjRegisterEventTranslatorQueue]->SetData(eventTranslatorQueueMemRgn);
00259 subject[sbjRegisterEventTranslatorQueue]->NotifyObservers();
00260 }
00261 }
00262 }
00263
00264 void
00265 MMCombo::GotEventTranslatorQueue(const ONotifyEvent& event){
00266 cout << objectName << "-GOTEventTranslatorQueue..." << flush;
00267
00268 if(strcmp(objectName,"MotoObj")==0) {
00269 ASSERT(event.NumOfData()==1,"Too many EventTranslatorQueue");
00270 eventTranslatorQueueMemRgn = event.RCData(0);
00271 eventTranslatorQueueMemRgn->AddReference();
00272 EventTranslator::Queue_t * etransq=reinterpret_cast<EventTranslator::Queue_t*>(eventTranslatorQueueMemRgn->Base());
00273 etrans.setQueue(etransq);
00274 MotionCommand::setQueue(etransq);
00275 erouter->addTrapper(&etrans);
00276 }
00277 observer[obsReceiveEventTranslatorQueue]->AssertReady();
00278 cout << "done" << endl;
00279 }
00280
00281
00282 void
00283 MMCombo::ReadySendJoints(const OReadyEvent& sysevent) {
00284
00285 if(isStopped) {
00286
00287 return;
00288 }
00289
00290 static unsigned int id=-1U;
00291 Profiler::Timer timer;
00292 if(ProcessID::getID()==ProcessID::MotionProcess) {
00293 if(state) {
00294 if(id==-1U)
00295 id=state->motionProfile.getNewID("ReadySendJoints()");
00296 timer.setID(id,&state->motionProfile);
00297 }
00298 } else if(ProcessID::getID()==ProcessID::MainProcess) {
00299 if(id==-1U)
00300 id=state->mainProfile.getNewID("ReadySendJoints()");
00301 timer.setID(id,&state->mainProfile);
00302 }
00303
00304 if(num_open==0)
00305 return;
00306
00307
00308 RCRegion* rgn=NULL;
00309 for (unsigned int i = 0; i < NUM_COMMAND_VECTOR; i++) {
00310 if (region[i]->NumberOfReference() == 1) {
00311 rgn=region[i];
00312
00313
00314
00315
00316
00317
00318 break;
00319 }
00320 }
00321 ASSERTRET(rgn!=NULL,"Could not find unused command vector");
00322 ASSERTRET(rgn->Base()!=NULL,"Bad Command Vector");
00323 OCommandVectorData* cmdVecData = reinterpret_cast<OCommandVectorData*>(rgn->Base());
00324
00325
00326
00327 if(ProcessID::getID()==ProcessID::MotionProcess) {
00328 float outputs[NumFrames][NumOutputs];
00329 if(state!=NULL) {
00330 motman->getOutputs(outputs);
00331 motman->updatePIDs(primIDs);
00332 motman->updateWorldState();
00333 } else {
00334 for(unsigned int f=0; f<NumFrames; f++)
00335 for(unsigned int i=0; i<NumOutputs; i++)
00336 outputs[f][i]=0;
00337 }
00338
00339
00340 unsigned int used=0;
00341 for(unsigned int i=PIDJointOffset; i<PIDJointOffset+NumPIDJoints; i++)
00342 if(open[i]) {
00343 OJointCommandValue2* jval = reinterpret_cast<OJointCommandValue2*>(cmdVecData->GetData(used)->value);
00344 for(unsigned int frame=0; frame<NumFrames; frame++)
00345 jval[frame].value = (slongword)(outputs[frame][i]*1e6);
00346 used++;
00347 }
00348 for(unsigned int i=LEDOffset; i<LEDOffset+NumLEDs; i++)
00349 if(open[i]) {
00350 OLEDCommandValue2* jval = reinterpret_cast<OLEDCommandValue2*>(cmdVecData->GetData(used)->value);
00351 for(unsigned int frame=0; frame<NumFrames; frame++)
00352 jval[frame].led = calcLEDValue(i-LEDOffset,outputs[frame][i]);
00353 used++;
00354 }
00355 for(unsigned int i=BinJointOffset; i<BinJointOffset+NumBinJoints; i++)
00356 if(open[i]) {
00357 OJointCommandValue3* jval = reinterpret_cast<OJointCommandValue3*>(cmdVecData->GetData(used)->value);
00358 for(unsigned int frame=0; frame<NumSlowFrames; frame++)
00359 jval[frame].value = (outputs[frame][i]<.5?ojoint3_STATE1:ojoint3_STATE0);
00360 used++;
00361 }
00362 } else if(ProcessID::getID()==ProcessID::MainProcess) {
00363
00364 unsigned int used=0;
00365 for(unsigned int i=BinJointOffset; i<BinJointOffset+NumBinJoints; i++)
00366 if(open[i]) {
00367 OJointCommandValue3* jval = reinterpret_cast<OJointCommandValue3*>(cmdVecData->GetData(used)->value);
00368 for(unsigned int frame=0; frame<NumSlowFrames; frame++)
00369 jval[frame].value = (state->outputs[i]<.5?ojoint3_STATE1:ojoint3_STATE0);
00370 used++;
00371 }
00372 }
00373
00374
00375 subject[sbjMoveJoint]->SetData(rgn);
00376
00377
00378
00379
00380 static unsigned int initCount=1;
00381 if(initCount<NUM_COMMAND_VECTOR) {
00382 initCount++;
00383 ReadySendJoints(sysevent);
00384 } else
00385 subject[sbjMoveJoint]->NotifyObservers();
00386 }
00387
00388 void
00389 MMCombo::GotSensorFrame(const ONotifyEvent& event){
00390
00391
00392 if(isStopped) {
00393
00394 return;
00395 }
00396
00397 PROFSECTION("GotSensorFrame()",state->mainProfile);
00398 etrans.translateEvents();
00399
00400 OSensorFrameVectorData* rawsensor = reinterpret_cast<OSensorFrameVectorData*>(event.RCData(0)->Base());
00401 state->read(rawsensor[0],erouter);
00402 erouter->processTimers();
00403 static unsigned int throwaway=1;
00404 if(throwaway!=0) {
00405 throwaway--;
00406 if(throwaway==0)
00407 addRunLevel();
00408 }
00409 observer[obsSensorFrame]->AssertReady();
00410 if (state!=NULL && state->wsser!=NULL)
00411 state->wsser->serialize();
00412
00413
00414 }
00415
00416 void
00417 MMCombo::GotImage(const ONotifyEvent& event){
00418 if(isStopped) {
00419
00420 return;
00421 }
00422
00423 PROFSECTION("GotImage()",state->mainProfile);
00424 etrans.translateEvents();
00425
00426 if (vision!=NULL) {
00427 const OFbkImageVectorData *fbkImageVectorData=reinterpret_cast<const OFbkImageVectorData*>(event.Data(0));
00428 OFbkImageInfo* info = const_cast<OFbkImageVectorData*>(fbkImageVectorData)->GetInfo(vision->imageLayer);
00429 const byte* dat = const_cast<OFbkImageVectorData*>(fbkImageVectorData)->GetData(vision->imageLayer);
00430 const OFbkImage yimage(info, const_cast<byte*>(dat), ofbkimageBAND_Y);
00431 const OFbkImage uimage(info, const_cast<byte*>(dat), ofbkimageBAND_Cr);
00432 const OFbkImage vimage(info, const_cast<byte*>(dat), ofbkimageBAND_Cb);
00433
00434 const byte* bytes_y = yimage.Pointer();
00435 const byte* bytes_u = uimage.Pointer();
00436 const byte* bytes_v = vimage.Pointer();
00437
00438 int width = yimage.Width();
00439 int height = yimage.Height();
00440
00441 WMvari(int, frame_counter, 0);
00442 ++frame_counter;
00443 vision->processFrame(bytes_y, bytes_u, bytes_v, width, height, yimage.Skip());
00444 }
00445 erouter->processTimers();
00446
00447 observer[obsImage]->AssertReady();
00448 }
00449
00450 void
00451 MMCombo::GotPowerEvent(void * msg){
00452 if(isStopped) {
00453
00454 return;
00455 }
00456
00457
00458 PROFSECTION("PowerEvent()",state->mainProfile);
00459 etrans.translateEvents();
00460
00461 static bool first=true;
00462 if(first) {
00463 addRunLevel();
00464 first=false;
00465 }
00466 const OPowerStatus* result = &static_cast<OPowerStatusMessage*>(msg)->powerStatus;
00467 state->read(*result,erouter);
00468 erouter->processTimers();
00469
00470
00471
00472
00473 if(state->powerFlags[PowerSourceID::PauseSID]) {
00474 cout << "%%%%%%% Pause button was pushed! %%%%%%%" << endl;
00475 OBootCondition bc(0);
00476 OPENR::Shutdown(bc);
00477 }
00478
00479 }
00480
00481 void
00482 MMCombo::GotMotionMsg(const ONotifyEvent& event){
00483 if(isStopped) {
00484
00485 return;
00486 }
00487
00488
00489 if(motman!=NULL)
00490 motman->receivedMsg(event);
00491 else
00492 cout << "*** WARNING Main dropping MotionCommand (motman not ready) " << endl;
00493 observer[obsMotionManagerComm]->AssertReady();
00494
00495 }
00496
00497 void
00498 MMCombo::GotSoundManager(const ONotifyEvent& event) {
00499 cout << objectName << "-GOTSOUNDMANAGER..." << flush;
00500
00501 ASSERT(event.NumOfData()==1,"Too many SoundManagers");
00502 soundManagerMemRgn = event.RCData(0);
00503 soundManagerMemRgn->AddReference();
00504 sndman = reinterpret_cast<SoundManager*>(soundManagerMemRgn->Base());
00505 observer[obsReceiveSoundManager]->AssertReady();
00506 sndman->InitAccess(subject[sbjSoundManagerComm]);
00507 addRunLevel();
00508 cout << "done" << endl;
00509 }
00510
00511 void
00512 MMCombo::OpenPrimitives()
00513 {
00514 for(unsigned int i=0; i<NumOutputs; i++)
00515 if(open[i]) {
00516 OStatus result = OPENR::OpenPrimitive(PrimitiveName[i], &primIDs[i]);
00517 if (result != oSUCCESS)
00518 OSYSLOG1((osyslogERROR, "%s : %s %d","MMCombo::DoInit()","OPENR::OpenPrimitive() FAILED", result));
00519 }
00520 }
00521
00522 void
00523 MMCombo::SetupOutputs(const bool to_open[NumOutputs])
00524 {
00525 char robotDesignStr[orobotdesignNAME_MAX];
00526 memset(robotDesignStr, 0, sizeof(robotDesignStr));
00527 if (OPENR::GetRobotDesign(robotDesignStr) != oSUCCESS) {
00528 cout << objectName << "::SetupOutputs - OPENR::GetRobotDesign() failed." << endl;
00529 return;
00530 } else {
00531 if(strcmp(robotDesignStr,"ERS-210")==0) {
00532 for(unsigned int j=0; j<NumOutputs; j++)
00533 open[j]=to_open[j] && ERS210Info::IsRealERS210[j];
00534 } else if(strcmp(robotDesignStr,"ERS-220")==0) {
00535 for(unsigned int j=0; j<NumOutputs; j++)
00536 open[j]=to_open[j] && ERS220Info::IsRealERS220[j];
00537 } else {
00538 cout << "MMCombo::SetupOutputs - ERROR: Unrecognized model: "<<robotDesignStr<<"\nSorry..."<<endl;
00539 return;
00540 }
00541 }
00542
00543
00544 for(unsigned int j=0; j<NumOutputs; j++)
00545 if(open[j])
00546 num_open++;
00547
00548 if(num_open==0)
00549 return;
00550
00551 OpenPrimitives();
00552
00553 OStatus result;
00554 MemoryRegionID cmdVecDataID;
00555 OCommandVectorData* cmdVecData;
00556
00557
00558 for (unsigned int i = 0; i < NUM_COMMAND_VECTOR; i++) {
00559 result = OPENR::NewCommandVectorData(num_open,&cmdVecDataID,&cmdVecData);
00560 if (result != oSUCCESS)
00561 OSYSLOG1((osyslogERROR, "%s : %s %d","MMCombo::NewCommandVectorData()","OPENR::NewCommandVectorData() FAILED", result));
00562 region[i] = new RCRegion(cmdVecData->vectorInfo.memRegionID,cmdVecData->vectorInfo.offset,(void*)cmdVecData,cmdVecData->vectorInfo.totalSize);
00563 cmdVecData->SetNumData(num_open);
00564
00565
00566 unsigned int used=0;
00567 ASSERT(cmdVecData==reinterpret_cast<OCommandVectorData*>(region[i]->Base())," should be equal!?");
00568 for(unsigned int j=PIDJointOffset; j<PIDJointOffset+NumPIDJoints; j++)
00569 if(open[j]) {
00570 OCommandInfo* info = cmdVecData->GetInfo(used++);
00571 info->Set(odataJOINT_COMMAND2, primIDs[j], NumFrames);
00572 }
00573 for(unsigned int j=LEDOffset; j<LEDOffset+NumLEDs; j++)
00574 if(open[j]) {
00575 OCommandInfo* info = cmdVecData->GetInfo(used);
00576 info->Set(odataLED_COMMAND2, primIDs[j], NumFrames);
00577 OLEDCommandValue2* jval = reinterpret_cast<OLEDCommandValue2*>(cmdVecData->GetData(used)->value);
00578 for(unsigned int frame=0; frame<NumFrames; frame++)
00579 jval[frame].period = 1;
00580 used++;
00581 }
00582 for(unsigned int j=BinJointOffset; j<BinJointOffset+NumBinJoints; j++)
00583 if(open[j]) {
00584 OCommandInfo* info = cmdVecData->GetInfo(used++);
00585 info->Set(odataJOINT_COMMAND3, primIDs[j], NumSlowFrames);
00586 }
00587 }
00588 }
00589
00590
00591 RCRegion*
00592 MMCombo::InitRegion(unsigned int size) {
00593 unsigned int pagesize=4096;
00594 sError err=GetPageSize(&pagesize);
00595 ASSERT(err==sSUCCESS,"Error "<<err<<" getting page size");
00596 unsigned int pages=(size+pagesize-1)/pagesize;
00597 return new RCRegion(pages*pagesize);
00598 }
00599
00600 void
00601 MMCombo::addRunLevel() {
00602 runLevel++;
00603 if(runLevel==readyLevel) {
00604 cout << "START UP BEHAVIOR..." << flush;
00605 startupBehavior.DoStart();
00606 cout << "START UP BEHAVIOR-DONE" << endl;
00607 }
00608 }
00609
00610 void
00611 MMCombo::RPOPENR_notify(const ONotifyEvent& event) {
00612 const char *buf = (const char *)event.Data(0);
00613 observer[event.ObsIndex()]->AssertReady();
00614
00615
00616
00617
00618
00619
00620
00621
00622 erouter->postEvent(new TextMsgEvent(buf));
00623 }
00624
00625 int
00626 MMCombo::RPOPENR_send(char *buf, int bufsize) {
00627 if (RPOPENR_isready && bufsize>0) {
00628 RPOPENR_isready=false;
00629 subject[sbjRPOPENRSendString]->SetData(buf, bufsize);
00630 subject[sbjRPOPENRSendString]->NotifyObservers();
00631 return bufsize;
00632 }
00633 return 0;
00634 }
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647