AREXPORT bool ArCameraCollection::addParameter(const char *cameraName, ArCameraParameterSource *source, const ArConfigArg ¶m) { lock(); CameraInfo *camInfo = findCameraInfo(cameraName); if ((camInfo == NULL) || (param.getName() == NULL)) { unlock(); return false; } ParamInfo *info = findParamInfo(cameraName, param.getName()); if (info != NULL) { unlock(); return false; } info = new ParamInfo(); info->mySource = source; info->myParam = param; camInfo->myParamToInfoMap[param.getName()] = info; unlock(); return true; } // end method addParameter
AREXPORT bool ArClientArg::isSendableParamType(const ArConfigArg &arg) { switch (arg.getType()) { case ArConfigArg::INT: case ArConfigArg::DOUBLE: case ArConfigArg::BOOL: case ArConfigArg::STRING: case ArConfigArg::SEPARATOR: return true; default: return false; } }
AREXPORT bool ArClientArg::isSendableParamType(const ArConfigArg &arg, bool isIncludeSeparator) { switch (arg.getType()) { case ArConfigArg::INT: case ArConfigArg::DOUBLE: case ArConfigArg::BOOL: case ArConfigArg::LIST: case ArConfigArg::STRING: return true; case ArConfigArg::SEPARATOR: return isIncludeSeparator; default: return false; } }
AREXPORT bool ArCameraCollection::setParameter(const char *cameraName, const ArConfigArg ¶m) { lock(); ParamInfo *info = findParamInfo(cameraName, param.getName()); if (info == NULL) { unlock(); return false; } info->myParam = param; if (info->mySource != NULL) { info->mySource->setParameter(param); } unlock(); return true; } // end method changeParameter
AREXPORT void ArClientHandlerConfig::handleGetConfigData(ArNetPacket *packet, bool isMultiplePackets) { char name[32000]; char comment[32000]; char type; std::string section; // The multiple packets method also sends display hints with the parameters; // the old single packet method does not. ArClientArg clientArg(isMultiplePackets, ArPriority::LAST_PRIORITY); bool isEmptyPacket = true; myDataMutex.lock(); while (packet->getDataReadLength() < packet->getDataLength()) { isEmptyPacket = false; type = packet->bufToByte(); if (type == 'S') { packet->bufToStr(name, sizeof(name)); packet->bufToStr(comment, sizeof(name)); //printf("%c %s %s\n", type, name, comment); ArLog::log(ArLog::Verbose, "%sReceiving config section %s...", myLogPrefix.c_str(), name); section = name; myConfig.setSectionComment(name, comment); } else if (type == 'P') { ArConfigArg configArg; bool isSuccess = clientArg.createArg(packet, configArg); if (isSuccess) { myConfig.addParam(configArg, section.c_str(), configArg.getConfigPriority(), configArg.getDisplayHint()); } else { ArLog::log(ArLog::Terse, "ArClientHandlerConfig unknown param type"); } } else // unrecognized header { ArLog::log(ArLog::Terse, "ArClientHandlerConfig unknown type"); } } // end while more to read if (!isMultiplePackets || isEmptyPacket) { ArLog::log(ArLog::Normal, "%sGot config from server.", myLogPrefix.c_str()); IFDEBUG(myConfig.log()); myHaveGottenConfig = true; } myDataMutex.unlock(); if (myHaveGottenConfig) { myCallbackMutex.lock(); for (std::list<ArFunctor *>::iterator it = myGotConfigCBList.begin(); it != myGotConfigCBList.end(); it++) { (*it)->invoke(); } myCallbackMutex.unlock(); } // end if config received } // end method handleGetConfigData
AREXPORT bool ArClientArg::createArg(ArNetPacket *packet, ArConfigArg &argOut, std::string *parentPathNameOut) { if (packet == NULL) { ArLog::log(ArLog::Verbose, "ArClientArg::createArg() cannot unpack NULL packet"); return false; } bool isSuccess = true; char name[32000]; char description[32000]; myDisplayBuffer[0] = '\0'; packet->bufToStr(name, sizeof(name)); packet->bufToStr(description, sizeof(description)); char priorityVal = packet->bufToByte(); ArPriority::Priority priority = myLastPriority; if ((priorityVal >= 0) && (priorityVal <= myLastPriority)) { priority = (ArPriority::Priority) priorityVal; } char argType = packet->bufToByte(); switch (argType) { case 'B': case 'b': // Lower case indicates display information contained in packet... { if ((argType == 'B') || (myIsDisplayHintParsed)) { bool boolVal = false; if (packet->bufToByte()) { boolVal = true; } //packet->bufToStr(myDisplayBuffer, BUFFER_LENGTH); argOut = ArConfigArg(name, boolVal, description); } else { isSuccess = false; } } break; case 'I': case 'i': // Lower case indicates display information contained in packet... { if ((argType == 'I') || (myIsDisplayHintParsed)) { int intVal = packet->bufToByte4(); int intMin = packet->bufToByte4(); int intMax = packet->bufToByte4(); argOut = ArConfigArg(name, intVal, description, intMin, intMax); } else { isSuccess = false; } } break; case 'D': case 'd': // Lower case indicates display information contained in packet... { if ((argType == 'D') || (myIsDisplayHintParsed)) { double doubleVal = packet->bufToDouble(); double doubleMin = packet->bufToDouble(); double doubleMax = packet->bufToDouble(); if (myVersion >= 2) { int precision = packet->bufToByte4(); argOut = ArConfigArg(name, doubleVal, description, doubleMin, doubleMax, precision); } else { argOut = ArConfigArg(name, doubleVal, description, doubleMin, doubleMax, -1); } } else { isSuccess = false; } } break; case 'S': case 's': // Lower case indicates display information contained in packet... { if ((argType == 'S') || (myIsDisplayHintParsed)) { packet->bufToStr(myBuffer, BUFFER_LENGTH); //packet->bufToStr(myDisplayBuffer, BUFFER_LENGTH); argOut = ArConfigArg(name, myBuffer, description, 0); } else { isSuccess = false; } } break; case 'L': case 'l': // Lower case indicates display information contained in packet... { if ((argType == 'L') || (myIsDisplayHintParsed)) { int childCount = packet->bufToByte4(); ArConfigArg listArg(ArConfigArg::LIST, name, description); ArConfigArg childArg; for (int i = 0; ((i < childCount) && (isSuccess)); i++) { isSuccess = createArg(packet, childArg); if (isSuccess) { listArg.addArg(childArg); } } if (isSuccess) { argOut = listArg; } } else { isSuccess = false; } } break; case '.': { //if (myIsDisplayHintParsed) { //packet->bufToStr(myDisplayBuffer, BUFFER_LENGTH); //} argOut = ArConfigArg(ArConfigArg::SEPARATOR); } break; default: isSuccess = false; ArLog::log(ArLog::Terse, "ArClientArg::createArg() unsupported param type '%c'", argType); } argOut.setConfigPriority(priority); if (myIsDisplayHintParsed) { if (isSuccess) { packet->bufToStr(myDisplayBuffer, BUFFER_LENGTH); } IFDEBUG( if (strlen(myDisplayBuffer) > 0) { ArLog::log(ArLog::Verbose, "ArClientArg::createArg() arg %s has displayHint = %s", argOut.getName(), myDisplayBuffer); } ); argOut.setDisplayHint(myDisplayBuffer); }
/** * @param client the ArServerClient * to which to send the config * @param packet the ArNetPacket * which accompanied the client's request * @param isMultiplePackets a bool set to true if the server should send a * packet for each config section followed by the empty packet; false if * the server should send the entire config in one packet (i.e. the old style) * @param lastPriority the last ArPriority::Priority that should be sent * to the client (this is the greatest numerical value and the least * semantic priority). **/ AREXPORT void ArServerHandlerConfig::handleGetConfig(ArServerClient *client, ArNetPacket *packet, bool isMultiplePackets, ArPriority::Priority lastPriority) { ArConfigArg param; // The multiple packets method also sends display hints with the parameters; // the old single packet method does not. ArClientArg clientArg(isMultiplePackets, lastPriority); std::set<std::string> sent; ArNetPacket sending; ArLog::log(ArLog::Normal, "Config requested."); std::list<ArConfigSection *> *sections = myConfig->getSections(); for (std::list<ArConfigSection *>::iterator sIt = sections->begin(); sIt != sections->end(); sIt++) { // Clear the packet... if (isMultiplePackets) { sending.empty(); } // clear out the sent list between sections sent.clear(); ArConfigSection *section = (*sIt); if (section == NULL) { continue; } sending.byteToBuf('S'); sending.strToBuf(section->getName()); sending.strToBuf(section->getComment()); ArLog::log(ArLog::Verbose, "Sending config section %s...", section->getName()); //printf("S %s %s\n", section->getName(), section->getComment()); std::list<ArConfigArg> *params = section->getParams(); for (std::list<ArConfigArg>::iterator pIt = params->begin(); pIt != params->end(); pIt++) { param = (*pIt); bool isCheckableName = (param.getType() != ArConfigArg::DESCRIPTION_HOLDER && param.getType() != ArConfigArg::SEPARATOR && param.getType() != ArConfigArg::STRING_HOLDER); // if we've already sent it don't send it again if (isCheckableName && sent.find(param.getName()) != sent.end()) { continue; } else if (isCheckableName) { sent.insert(param.getName()); } if (clientArg.isSendableParamType(param)) { sending.byteToBuf('P'); bool isSuccess = clientArg.createPacket(param, &sending); } } // end for each parameter if (!sending.isValid()) { ArLog::log(ArLog::Terse, "Config section %s cannot be sent; packet size exceeded", section->getName()); } // end if length exceeded... else if (isMultiplePackets) { client->sendPacketTcp(&sending); } // end else send in chunks... } // end for each section // If sending each section in individual packets, then send an empty packet // to indicate the end of the config data. if (isMultiplePackets) { sending.empty(); client->sendPacketTcp(&sending); } else { // send the entire config in one packet // If the config is too big to fit in the packet, then just send an empty // packet (to try to prevent an older client from crashing) // TODO: Is there any better way to notify the user of an error.... if (!sending.isValid()) { ArLog::log(ArLog::Terse, "Error sending config; packet size exceeded"); sending.empty(); } client->sendPacketTcp(&sending); } // end else send the entire packet } // end method getConfigBySections
/** @internal doesn't delete the old one, do that if you're going to call this yourself and make sure you lock around all that (okay, it deletes it now, but the stuff that calls it should still take care of it) **/ void ArServerHandlerConfig::createDefaultConfig(const char *defaultFileBaseDir) { if (myDefault != NULL) { delete myDefault; myDefault = NULL; } // copy that config (basedir will be NULL if we're not loading from // a file)... don't have the default save unknown values myDefault = new ArConfig(defaultFileBaseDir, false, false, false, false); std::list<ArConfigSection *>::iterator sectionIt; std::list<ArConfigArg>::iterator paramIt; ArConfigSection *section = NULL; std::list<ArConfigArg> *params = NULL; ArConfigArg param; for (sectionIt = myConfig->getSections()->begin(); sectionIt != myConfig->getSections()->end(); sectionIt++) { section = (*sectionIt); params = section->getParams(); for (paramIt = params->begin(); paramIt != params->end(); paramIt++) { param = (*paramIt); switch (param.getType()) { case ArConfigArg::INT: myDefault->addParam( ArConfigArg(param.getName(), param.getInt(), param.getDescription(), param.getMinInt(), param.getMaxInt()), section->getName(), param.getConfigPriority(), param.getDisplayHint()); break; case ArConfigArg::DOUBLE: myDefault->addParam( ArConfigArg(param.getName(), param.getDouble(), param.getDescription(), param.getMinDouble(), param.getMaxDouble()), section->getName(), param.getConfigPriority(), param.getDisplayHint()); break; case ArConfigArg::BOOL: myDefault->addParam( ArConfigArg(param.getName(), param.getBool(), param.getDescription()), section->getName(), param.getConfigPriority(), param.getDisplayHint()); break; case ArConfigArg::STRING: myDefault->addParam( ArConfigArg(param.getName(), (char *)param.getString(), param.getDescription(), 0), section->getName(), param.getConfigPriority(), param.getDisplayHint()); break; case ArConfigArg::SEPARATOR: myDefault->addParam( ArConfigArg(ArConfigArg::SEPARATOR), section->getName(), param.getConfigPriority(), param.getDisplayHint()); break; default: break; } // end switch param type } // end for each param } // end for each section }
int main(int argc, char **argv) { Aria::init(); ArArgumentParser argParser(&argc, argv); argParser.loadDefaultArguments(); if (argc < 2 || !Aria::parseArgs() || argParser.checkArgument("-help")) { ArLog::log(ArLog::Terse, "configExample usage: configExample <config file>.\nFor example, \"configExample examples/configExample.cfg\"."); Aria::logOptions(); Aria::shutdown(); return 1; } // Object containing config parameters, and responding to changes: ConfigExample configExample; // Load a config file given on the command line into the global // ArConfig object kept by Aria. Normally ArConfig expects config // files to be in the main ARIA directory (i.e. /usr/local/Aria or // a directory specified by the $ARIA environment variable). char error[512]; const char* filename = argParser.getArg(1); ArConfig* config = Aria::getConfig(); ArLog::log(ArLog::Normal, "configExample: loading configuration file \"%s\"...", filename); if (! config->parseFile(filename, true, false, error, 512) ) { ArLog::log(ArLog::Terse, "configExample: Error loading configuration file \"%s\" %s. Try \"examples/configExample.cfg\".", filename, error); Aria::shutdown(); return -1; } ArLog::log(ArLog::Normal, "configExample: Loaded configuration file \"%s\".", filename); // After changing a config value, you should invoke the callbacks: ArConfigSection* section = config->findSection("Example Section"); if (section) { ArConfigArg* arg = section->findParam("ExampleBoolParameter"); if (arg) { arg->setBool(!arg->getBool()); if (! config->callProcessFileCallBacks(false, error, 512) ) { ArLog::log(ArLog::Terse, "configExample: Error processing modified config: %s.", error); } else { ArLog::log(ArLog::Normal, "configExample: Successfully modified config and invoked callbacks."); } } } // You can save the configuration as well: ArLog::log(ArLog::Normal, "configExample: Saving configuration..."); if(!config->writeFile(filename)) { ArLog::log(ArLog::Terse, "configExample: Error saving configuration to file \"%s\"!", filename); } // end of program. ArLog::log(ArLog::Normal, "configExample: end of program."); Aria::shutdown(); return 0; }
AREXPORT void ArServerHandlerCameraCollection::setParams(ArServerClient *client, ArNetPacket *packet) { if ((packet == NULL) || (myCameraCollection == NULL)) { return; } char buffer[512]; packet->bufToStr(buffer, sizeof(buffer)); std::string cameraName = buffer; ArNetPacket paramUpdatedPacket; paramUpdatedPacket.strToBuf(cameraName.c_str()); ArConfigArg arg; ArClientArg clientArg; bool isSuccess = true; bool isParamUpdated = false; bool isDone = false; while (!isDone) { packet->bufToStr(buffer, sizeof(buffer)); std::string paramName = buffer; if (paramName.empty()) { isDone = true; break; } isSuccess = myCameraCollection->getParameter(cameraName.c_str(), paramName.c_str(), arg); if (!isSuccess) { ArLog::log(ArLog::Verbose, "ArServerHandlerCameraCollection::setParams() could not find camera %s, param %s", cameraName.c_str(), paramName.c_str()); continue; } isSuccess = clientArg.bufToArgValue(packet, arg); if (!isSuccess) { continue; } isSuccess = myCameraCollection->setParameter(cameraName.c_str(), arg); if (!isSuccess) { continue; } paramUpdatedPacket.strToBuf(arg.getName()); clientArg.argValueToBuf(arg, ¶mUpdatedPacket); isParamUpdated = true; } // end for each param // TODO Send a confirmation back, or just use the broadcast packet? (If a, then add // client to broadcast) // Add an empty string to indicate the last parameter... paramUpdatedPacket.strToBuf(""); // Haven't quite decided whether to send the update packet, or a success/error notice... client->sendPacketTcp(¶mUpdatedPacket); if (isParamUpdated) { // NOT_EXCLUDING this used to not send it to the client, but no // longer has that behavior since it causes problems with the // central server myServer->broadcastPacketTcp(¶mUpdatedPacket, PARAMS_UPDATED_PACKET_NAME); } /** // TODO: Add error message? ArNetPacket retPacket; retPacket->strToBuf(""); client->sendPacketTcp(&retPacket); **/ } // end method setParams