/* * This function checks to see if the current YAML::Node contains only keys * that we care about. Unknown keys should cause PLFS to spit out an error * rather than being silently ignored. * This is a bit nasty as it drills through the entire tree recursively * but it will catch any unknowns in one pass * * Returns true if all keys are valid * * Returns false if unknown keys are found and sets bad_key to an error * message that points out what key is invalid */ bool is_valid_node(const YAML::Node node, string** bad_key) { set<string> key_list(Valid_Keys, Valid_Keys + (sizeof(Valid_Keys) / sizeof(Valid_Keys[0])) ); string key; string err = "\nBad key or value in plfsrc: "; if(node.IsMap()) { for(YAML::const_iterator it=node.begin();it!=node.end();it++) { if(!it->first.IsNull()) { key = it->first.as<string>(); if(!is_valid_node(node[key],bad_key)) // recurse return false; if(key_list.find(key) == key_list.end()) { err.append(key); *bad_key = new string (err); return false; // this is an unknown key } } } } else if (node.IsSequence()) { for(unsigned int i = 0; i < node.size(); i++) if(!is_valid_node(node[i],bad_key)) // recurse return false; } else if (node.IsScalar() && node.as<string>().find(" ") != string::npos) { err.append(node.as<string>()); *bad_key = new string (err); return false; // no spaces in values allowed } return true; // all keys are valid }
bool AreDetailsEqual(const YAML::Node& lhs, const YAML::Node& rhs) { //We want to check for plugin order and messages. if (lhs.IsSequence() && rhs.IsSequence()) { std::list<std::string> lhs_names, rhs_names; std::list<Message> lhs_messages, rhs_messages; for (YAML::const_iterator it = lhs.begin(); it != lhs.end(); ++it) { if ((*it)["name"]) lhs_names.push_back((*it)["name"].as<std::string>()); if ((*it)["messages"]) { std::list<Message> messages = (*it)["messages"].as< std::list<Message> >(); lhs_messages.insert(lhs_messages.end(), messages.begin(), messages.end()); } } for (YAML::const_iterator it = rhs.begin(); it != rhs.end(); ++it) { if ((*it)["name"]) rhs_names.push_back((*it)["name"].as<std::string>()); if ((*it)["messages"]) { std::list<Message> messages = (*it)["messages"].as< std::list<Message> >(); rhs_messages.insert(rhs_messages.end(), messages.begin(), messages.end()); } } return lhs_names == rhs_names && lhs_messages == rhs_messages; } else return false; }
bool KnobSerialization::checkForDefaultValueNode(const YAML::Node& node, const std::string& nodeType, bool dataTypeSet) { std::string defaultString("Default"); std::string defaultTypeName = defaultString + nodeType; if (!node[defaultTypeName]) { return false; } // If the _dataType member was set in checkForValueNode, ensure that the data type of the value is the same as // the default value. if (dataTypeSet) { SerializationValueVariantTypeEnum type = dataTypeFromString(nodeType); if (type != _dataType) { throw std::invalid_argument(_scriptName + ": Default value and value type differ!"); } } else { _dataType = dataTypeFromString(nodeType); } YAML::Node defNode = node[defaultTypeName]; int nDims = defNode.IsSequence() ? defNode.size() : 1; _defaultValues.resize(nDims); for (int i = 0; i < nDims; ++i) { _defaultValues[i].serializeDefaultValue = true; YAML::Node dimNode = defNode.IsSequence() ? defNode[i] : defNode; decodeValueFromNode(dimNode, _defaultValues[i].value, _dataType); } return true; }
bool YamlPath::get(YAML::Node root, YAML::Node& out) { size_t beginToken = 0, endToken = 0, pathSize = codedPath.size(); auto delimiter = MAP_DELIM; // First token must be a map key. while (endToken < pathSize) { if (!root.IsDefined()) { return false; // A node before the end of the path was mising, quit! } beginToken = endToken; endToken = pathSize; endToken = std::min(endToken, codedPath.find(SEQ_DELIM, beginToken)); endToken = std::min(endToken, codedPath.find(MAP_DELIM, beginToken)); if (delimiter == SEQ_DELIM) { int index = std::stoi(&codedPath[beginToken]); if (root.IsSequence()) { root.reset(root[index]); } else { return false; } } else if (delimiter == MAP_DELIM) { auto key = codedPath.substr(beginToken, endToken - beginToken); if (root.IsMap()) { root.reset(root[key]); } else { return false; } } else { return false; // Path is malformed, return null node. } delimiter = codedPath[endToken]; // Get next character as the delimiter. ++endToken; // Move past the delimiter. } // Success! Assign the result. out.reset(root); return true; }
// Incrementally load YAML static NEVER_INLINE void operator +=(YAML::Node& left, const YAML::Node& node) { if (node && !node.IsNull()) { if (node.IsMap()) { for (const auto& pair : node) { if (pair.first.IsScalar()) { auto&& lhs = left[pair.first.Scalar()]; lhs += pair.second; } else { // Exotic case (TODO: probably doesn't work) auto&& lhs = left[YAML::Clone(pair.first)]; lhs += pair.second; } } } else if (node.IsScalar() || node.IsSequence()) { // Scalars and sequences are replaced completely, but this may change in future. // This logic may be overwritten by custom demands of every specific cfg:: node. left = node; } } }
int GazeboRosPulson::ParseBeaconMapFile(std::string f) { ROS_INFO("Opening Beacon Map File: %s", f.c_str()); // open file std::fstream fs; fs.open(f.c_str()); if (!fs.is_open()) return -1; YAML::Node map = YAML::LoadFile(f.c_str()); assert(map.IsSequence()); num_beacons_ = map.size(); // read beacon locations for (int i = 0; i < num_beacons_; i++) { Beacon b; b.x = (double) map[i]["x"].as<double>(); b.y = (double) map[i]["y"].as<double>(); b.z = (double) map[i]["z"].as<double>(); b.id = (int) map[i]["id"].as<int>(); ROS_INFO("Beacon %d at : %f %f %f", b.id, b.x, b.y, b.z); beacons_.push_back(b); } // close file fs.close(); return 0; }
Vector from_yaml(type_t<Vector>, const YAML::Node& value) { if (!value.IsSequence()) throw deserialize_error{"type must be a sequence but is " + yaml_type_name(value)}; Vector ret{}; vector_reserve(ret, value.size(), has_reserve<Vector>{}); for (const auto& item : value) { try { ret.push_back(yaml::deserialize<typename Vector::value_type>(item)); } catch (deserialize_error& ex) { std::string msg = "error when deserializing element " + std::to_string(ret.size()); ex.add(msg.c_str()); throw; } } return ret; }
bool ParamManager::load_from_file(std::string filename) { try { YAML::Node root = YAML::LoadFile(filename); assert(root.IsSequence()); for (int i = 0; i < root.size(); i++) { if (root[i].IsMap() && root[i]["name"] && root[i]["type"] && root[i]["value"]) { if (is_param_id(root[i]["name"].as<std::string>())) { Param param = params_.find(root[i]["name"].as<std::string>())->second; if ((MAV_PARAM_TYPE) root[i]["type"].as<int>() == param.getType()) { set_param_value(root[i]["name"].as<std::string>(), root[i]["value"].as<double>()); } } } } return true; } catch (...) { return false; } }
std::tuple<Ts...> from_yaml(type_t<std::tuple<Ts...>>, const YAML::Node& value) { if (!value.IsSequence()) throw deserialize_error{"type must be a sequence but is " + yaml_type_name(value)}; return tuple_from_yaml<std::tuple<Ts...>>( value, make_index_sequence<sizeof...(Ts)>{}); }
void NonKeyParamsSerialization::decode(const YAML::Node& node) { if (!node.IsSequence() || node.size() != 3) { throw YAML::InvalidNode(); } dataTypeSize = node[0].as<std::size_t>(); nComps = node[1].as<int>(); bounds.decode(node[2]); }
int main(int argc, char **argv) { ros::init(argc, argv, "apriltag_ros"); ros::NodeHandle nh("~"); image_transport::ImageTransport it(nh); image_transport::CameraSubscriber camera_sub = it.subscribeCamera("image_raw", 1, cam_callback); pose_pub = nh.advertise<geometry_msgs::PoseStamped>("pose_cam", 1); // load YAML file with tag positions std::string yamlPath; if (!nh.hasParam("map_file")) { ROS_ERROR("Error: You must specify the map_file parameter."); return -1; } nh.getParam("map_file", yamlPath); try { YAML::Node mapNode = YAML::LoadFile(yamlPath); if (!mapNode.IsSequence()) { throw std::runtime_error("YAML file should be a sequence of tags"); } for (size_t i=0; i < mapNode.size(); i++) { apriltag_ros::Tag tag = mapNode[i].as<apriltag_ros::Tag>(); tagsWorld[tag.id] = tag; // add to map } if (tagsWorld.empty()) { throw std::runtime_error("No tags were loaded"); } else { ROS_INFO("Loaded %lu tags from the map file", tagsWorld.size()); } } catch(std::exception& e) { ROS_ERROR("Error: Failed to load map file: %s", yamlPath.c_str()); ROS_ERROR("Reason: %s", e.what()); return -1; } image_pub = nh.advertise<sensor_msgs::Image>("image", 1); tag_pub = nh.advertise<apriltag_ros::tags>("tags", 1); ros::Rate r(10.0); while(nh.ok()) { r.sleep(); ros::spinOnce(); } return 0; }
static void decodeBezierCPCurve(const YAML::Node& node, double* x, CurveSerialization* curve) { try { if (node.IsSequence()) { curve->decode(node); if (!curve->keys.empty()) { *x = curve->keys.front().value; } } else { *x = node.as<double>(); } } catch (const YAML::BadConversion& /*e*/) { assert(false); } }
void BezierCPSerialization::decode(const YAML::Node& node) { if (!node.IsSequence() || node.size() != 6) { throw YAML::InvalidNode(); } decodeBezierCPCurve(node[0], &x, &xCurve); decodeBezierCPCurve(node[1], &y, &yCurve); decodeBezierCPCurve(node[2], &leftX, &leftCurveX); decodeBezierCPCurve(node[3], &leftY, &leftCurveY); decodeBezierCPCurve(node[4], &rightX, &rightCurveX); decodeBezierCPCurve(node[5], &rightY, &rightCurveY); }
static bool decodeMat(const YAML::Node &node, kr::Mat<Scalar, Rows, Cols> &M) { static_assert(Rows != Eigen::Dynamic && Cols != Eigen::Dynamic, "Static matrices only"); if (!node.IsSequence() || node.size() != Rows*Cols) { return false; } for (int i = 0; i < Rows; i++) { for (int j = 0; j < Cols; j++) { M(i, j) = static_cast<Scalar>(node[i * Cols + j].as<double>()); } } return true; }
enum_flags<Enum> from_yaml(type_t<enum_flags<Enum>>, const YAML::Node& value) { if (!value.IsSequence()) throw deserialize_error{"type must be a sequnce but is " + yaml_type_name(value)}; enum_flags<Enum> ret{}; for (const auto& v : value) { const auto e = yaml::deserialize<Enum>(v); ret |= e; } return ret; }
void GameConfiguration::parseYAML(const string archivoAParsear){ //VERIFICA SI ARCHIVO ESTA CORRUPTO O TIENE FORMATO VALIDO DE YAML, EN ESE CASO PARSEA DIRECTAMENTE EL ARCHIVO POR DEFECTO this->loadFile(archivoAParsear); this->pantalla = PantallaConfig(this->nodoRaiz["pantalla"]); this->configuracion = ConfiguracionConfig(this->nodoRaiz["configuracion"]); YAML::Node nodoTipos = this->nodoRaiz["tipos"]; this->escenario = EscenarioConfig(this->nodoRaiz["escenario"]); if(!nodoTipos.IsSequence()){ Log().Get(TAG,logERROR) << "Nodo tipos tiene que ser una secuencia"; } else { for (std::size_t i=0;i < nodoTipos.size();i++) { TipoConfig* newNodo = new TipoConfig(nodoTipos[i]); tipos.push_back(*newNodo); } } }
YAML::Node expandDefaults(const YAML::Node& node) { YAML::Node result = YAML::Clone(node); if (node.IsMap() && node["DEFAULT"]) { const YAML::Node& default_node = result["DEFAULT"]; for (auto field = result.begin(); field != result.end(); ++field) { std::string fieldname = field->first.as<std::string>(); if (fieldname != "DEFAULT") { result[fieldname] = applyDefaults(result[fieldname], default_node); } } } if (result.IsMap() || result.IsSequence()) { for (auto child = result.begin(); child != result.end(); ++child) { std::string child_name = child->first.as<std::string>(); result[child_name] = expandDefaults(child->second); } } return result; }
inline bool checkVariableType(const YAML::Node& node, const YamlCppUtils::Type type) { switch (type) { case YamlCppUtils::TypeBoolean: try { node.as<bool>(); return true; } catch (const YAML::TypedBadConversion<bool>&) { return false; } case YamlCppUtils::TypeFloat: try { node.as<double>(); return true; } catch (const YAML::TypedBadConversion<double>&) { return false; } case YamlCppUtils::TypeInt: try { node.as<int>(); return true; } catch (const YAML::TypedBadConversion<int>&) { return false; } case YamlCppUtils::TypeSequence: return node.IsSequence(); case YamlCppUtils::TypeString: try { node.as<std::string>(); return true; } catch (const YAML::TypedBadConversion<std::string>&) { return false; } } return false; }
// Test conversion to and from yaml node TYPED_TEST(AllMatrixTests, YamlConvert) { typedef typename TestFixture::Matrix Matrix; typedef typename TestFixture::Scalar T; // This array has more elements than we will need. // The element type must match the matrix! const T inputArray[18] = { 0.01f, 1.02f, 2.03f, 3.04f, 4.05f, 5.06f, 6.07f, 7.08f, 8.09f, 9.10f, 10.11f, 11.12f, 12.13f, 13.14f, 14.15f, 15.16f, 16.17f, 17.18f }; Matrix matrix(inputArray); YAML::Node node; ASSERT_NO_THROW(node = matrix); EXPECT_TRUE(node.IsSequence()); EXPECT_EQ(matrix.rows(), node.size()); ASSERT_NO_THROW({Matrix expected = node.as<Matrix>();});
XmlRpc::XmlRpcValue YamlToXml( const YAML::Node& node ) { XmlRpc::XmlRpcValue xml; if( node.IsNull() ) { return xml; } else if( node.IsSequence() ) { std::vector< std::string > contents = node.as< std::vector< std::string > >(); xml.setSize( contents.size() ); for( unsigned int i = 0; i < contents.size(); i++ ) { xml[i] = contents[i]; } } else if( node.IsScalar() ) { xml = node.as< std::string >(); } else if( node.IsMap() ) { YAML::Node::const_iterator iter; for( iter = node.begin(); iter != node.end(); iter++ ) { std::string name = iter->first.as<std::string>(); xml[ name ] = YamlToXml( iter->second ); } } else { std::cerr << "Invalid YAML node type." << std::endl; } return xml; }
void cfg::decode(const YAML::Node& data, cfg::_base& rhs) { switch (rhs.get_type()) { case type::node: { if (data.IsScalar() || data.IsSequence()) { return; // ??? } for (const auto& pair : data) { if (!pair.first.IsScalar()) continue; // Find the key among existing nodes for (const auto& _pair : static_cast<node&>(rhs).get_nodes()) { if (_pair.first == pair.first.Scalar()) { decode(pair.second, *_pair.second); } } } break; } case type::set: { std::vector<std::string> values; if (YAML::convert<decltype(values)>::decode(data, values)) { rhs.from_list(std::move(values)); } break; } case type::log: { if (data.IsScalar() || data.IsSequence()) { return; // ??? } std::map<std::string, logs::level> values; for (const auto& pair : data) { if (!pair.first.IsScalar() || !pair.second.IsScalar()) continue; u64 value; if (cfg::try_to_enum_value(&value, &fmt_class_string<logs::level>::format, pair.second.Scalar())) { values.emplace(pair.first.Scalar(), static_cast<logs::level>(static_cast<int>(value))); } } static_cast<log_entry&>(rhs).set_map(std::move(values)); break; } default: { std::string value; if (YAML::convert<std::string>::decode(data, value)) { rhs.from_string(value); } break; // ??? } } }
Reflectable reflectable_from_yaml(const YAML::Node& value) { Reflectable refl{}; if (value.IsMap()) { ctti::reflect(refl, [&value](auto fi) { using field_type = typename decltype(fi)::type; try { const auto& query = value[fi.name()]; if (query) fi.get() = yaml::deserialize<field_type>(query); else fi.get() = yaml::deserialize<field_type>({}); } catch (deserialize_error& ex) { std::string msg = "error when deserializing field " + std::string(fi.name()); ex.add(msg.c_str()); throw; } }); } else if (value.IsSequence()) { if (value.size() > ctti::total_num_fields<Reflectable>()) { throw deserialize_error{"sequence size is greater than " "declared struct's field " "count"}; } ctti::reflect(refl, [&value, index = 0U](auto fi) mutable { using field_type = typename decltype(fi)::type; try { if (index < value.size()) fi.get() = yaml::deserialize<field_type>(value[index]); else fi.get() = yaml::deserialize<field_type>({}); ++index; } catch (deserialize_error& ex) { std::string msg = "error when deserializing element " + std::to_string(index); ex.add(msg.c_str()); throw; } }); } else { throw deserialize_error{"type must be a sequence or map but is " + yaml_type_name(value)}; } return refl; }
void KnobSerialization::decodeValueNode(const std::string& viewName, const YAML::Node& node) { int nDims = 1; bool isMainNodeSequence = node.IsSequence() && _dataType != eSerializationValueVariantTypeTable; if (isMainNodeSequence) { nDims = node.size(); } PerDimensionValueSerializationVec& dimVec = _values[viewName]; initValuesVec(this, &dimVec, nDims); for (int i = 0; i < nDims; ++i) { YAML::Node dimNode = isMainNodeSequence ? node[i] : node; if (!dimNode.IsMap()) { // This is a value decodeValueFromNode(dimNode, dimVec[i]._value, _dataType); dimVec[i]._serializeValue = true; } else { // !isMap // Always look for an animation curve if (dimNode["Curve"]) { // Curve dimVec[i]._animationCurve.decode(dimNode["Curve"]); } // Look for a link or expression if (dimNode["pyMultiExpr"]) { dimVec[i]._expression = dimNode["pyMultiExpr"].as<std::string>(); dimVec[i]._expresionHasReturnVariable = true; dimVec[i]._expressionLanguage = kKnobSerializationExpressionLanguagePython; } else if (dimNode["pyExpr"]) { dimVec[i]._expression = dimNode["pyExpr"].as<std::string>(); dimVec[i]._expressionLanguage = kKnobSerializationExpressionLanguagePython; } else if (dimNode["exprtk"]) { dimVec[i]._expression = dimNode["exprtk"].as<std::string>(); dimVec[i]._expressionLanguage = kKnobSerializationExpressionLanguageExprtk; } else { // This is most likely a regular slavr/master link bool gotLink = false; if (dimNode["N"]) { dimVec[i]._slaveMasterLink.masterNodeName = dimNode["N"].as<std::string>(); gotLink = true; } if (dimNode["T"]) { dimVec[i]._slaveMasterLink.masterTableItemName = dimNode["T"].as<std::string>(); gotLink = true; } if (dimNode["K"]) { dimVec[i]._slaveMasterLink.masterKnobName = dimNode["K"].as<std::string>(); gotLink = true; } if (dimNode["D"]) { dimVec[i]._slaveMasterLink.masterDimensionName = dimNode["D"].as<std::string>(); gotLink = true; } if (dimNode["V"]) { dimVec[i]._slaveMasterLink.masterViewName = dimNode["V"].as<std::string>(); gotLink = true; } dimVec[i]._slaveMasterLink.hasLink = gotLink; } } // isMap } } //decodeValueNode
void Config::parseWatcher(const YAML::Node& node) { size_t asterisk_count; if(node.size() >= 1 && node.IsMap()) for (YAML::const_iterator iter=node.begin();iter!=node.end();++iter) { std::string key = iter->first.as<std::string>(); YAML::Node value = iter->second; Util::lowercase(key); if(key == "filter") { if(!value.IsSequence()) std::cerr << "ERROR!\n"; for(YAML::const_iterator filter_iter=value.begin(); filter_iter!=value.end(); ++filter_iter) { asterisk_count = 0; std::string val = filter_iter->as<std::string>(); for(size_t i = 0; i < val.length(); i++) if(val[i] == '*') asterisk_count++; LOG(logger, DEBUG, "Filter: %s", val.c_str()); if(asterisk_count > 1) throw std::runtime_error("Could not open file"); mWatch.filters.push_back(val); } } else if(key == "include") { if(!value.IsSequence() && !value.IsScalar()) std::cerr << "ERROR!\n"; if(value.IsSequence()) { for(YAML::const_iterator filter_iter=value.begin(); filter_iter!=value.end(); ++filter_iter) { LOG(logger, DEBUG, "Include: %s", filter_iter->as<std::string>().c_str()); mWatch.include.push_back(filter_iter->as<std::string>()); } } else if(value.IsScalar()) { LOG(logger, DEBUG, "Include: %s", value.as<std::string>().c_str()); mWatch.include.push_back(value.as<std::string>()); } } else if(key == "exclude") { if(!value.IsSequence() && !value.IsScalar()) std::cerr << "ERROR!\n"; if(value.IsSequence()) { for(YAML::const_iterator filter_iter=value.begin(); filter_iter!=value.end(); ++filter_iter) { LOG(logger, DEBUG, "Exclude: %s", filter_iter->as<std::string>().c_str()); mWatch.exclude.push_back(filter_iter->as<std::string>()); } } else if(value.IsScalar()) { LOG(logger, DEBUG, "Exclude: %s", value.as<std::string>().c_str()); mWatch.exclude.push_back(value.as<std::string>()); } } else LOG(logger, DEBUG, "Value: %s\n", value.as<std::string>().c_str()); } }
void CurveSerialization::decode(const YAML::Node& node) { if (!node.IsSequence()) { return; } if (node.size() == 0) { return; } CurveDecodeStateEnum state = eCurveDecodeStateMayExpectInterpolation; std::string interpolation; KeyFrameSerialization keyframe; bool pushKeyFrame = false; for (std::size_t i = 0; i < node.size(); ++i) { YAML::Node keyNode = node[i]; switch (state) { case eCurveDecodeStateMayExpectInterpolation: if (pushKeyFrame) { keys.push_back(keyframe); // Reset keyframe keyframe.interpolation.clear(); keyframe.time = keyframe.value = keyframe.leftDerivative = keyframe.rightDerivative = 0.; } try { // First try to get a time. Conversion of a string to double always fails but string to double does not keyframe.time = keyNode.as<double>(); // OK we read a valid time, assume the interpolation is the same as the previous // No interpolation, use the interpolation set previously. // If interpolation is not set, set interpolation to linear if (interpolation.empty()) { interpolation = kKeyframeSerializationTypeLinear; } keyframe.interpolation = interpolation; state = eCurveDecodeStateExpectValue; } catch (const YAML::BadConversion& /*e*/) { // OK we read an interpolation and set the curve interpolation so far if needed keyframe.interpolation = keyNode.as<std::string>(); // No interpolation, use the interpolation set previously. // If interpolation is not set, set interpolation to linear if (interpolation.empty()) { interpolation = keyframe.interpolation; } state = eCurveDecodeStateExpectTime; } break; case eCurveDecodeStateExpectTime: keyframe.time = keyNode.as<double>(); state = eCurveDecodeStateExpectValue; break; case eCurveDecodeStateExpectValue: keyframe.value = keyNode.as<double>(); // Depending on interpolation we may expect derivatives if (keyframe.interpolation == kKeyframeSerializationTypeFree || keyframe.interpolation == kKeyframeSerializationTypeBroken) { state = eCurveDecodeStateMayExpectRightDerivative; } else { state = eCurveDecodeStateMayExpectInterpolation; } break; case eCurveDecodeStateMayExpectRightDerivative: keyframe.rightDerivative = keyNode.as<double>(); if (keyframe.interpolation == kKeyframeSerializationTypeBroken) { state = eCurveDecodeStateMayExpectLeftDerivative; } else { state = eCurveDecodeStateMayExpectInterpolation; } break; case eCurveDecodeStateMayExpectLeftDerivative: keyframe.leftDerivative = keyNode.as<double>(); state = eCurveDecodeStateMayExpectInterpolation; break; } pushKeyFrame = true; } if (pushKeyFrame) { keys.push_back(keyframe); } }
void MidiRouter::readFile(QString fileName) { clear(); QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { emit(mappingError("cannot open file: " + fileName)); return; } QTextStream in(&file); YAML::Node root = YAML::Load(in.readAll().toStdString()); if (!root.IsMap()) { emit(mappingError("mapping is not a map in " + fileName)); return; } for (auto kv: std::map<QString, int>({{"master", -1}, {"player0", 0}, {"player1", 1}})) { const QString key = kv.first; const int player = kv.second; if (!root[key]) continue; YAML::Node parent = root[key]; if (!parent.IsSequence()) emit(mappingError(key + " is not a sequence in " + fileName)); for (unsigned int i = 0; i < parent.size(); i++) { YAML::Node node = parent[i]; MidiMapPtr mmap = QSharedPointer<MidiMap>::create(); mmap->player_index = player; try { if (node["trigger"]) { mmap->signal_name = node["trigger"].as<QString>(); mmap->mapping_type = TRIGGER; try { if (!find_midi(node, mmap, yamls_trigger_map)) emit(mappingError(key + " could not find trigger mapping in element " + QString::number(i))); } catch (std::runtime_error& e) { emit(mappingError(key + QString::fromStdString(e.what()) + " in element " + QString::number(i))); } } else if (node["continuous"]) { mmap->signal_name = node["continuous"].as<QString>(); mmap->mapping_type = CONTINUOUS; try { if (!find_midi(node, mmap, yamls_cc_map)) emit(mappingError(key + " could not find cc mapping in element " + QString::number(i))); } catch (std::runtime_error& e) { emit(mappingError(key + QString::fromStdString(e.what()) + " in element " + QString::number(i))); } } else if (node["twos_complement"]) { mmap->signal_name = node["twos_complement"].as<QString>(); mmap->mapping_type = TWOS_COMPLEMENT; try { if (!find_midi(node, mmap, yamls_cc_map)) emit(mappingError(key + " could not find trigger mapping in element " + QString::number(i))); } catch (std::runtime_error& e) { emit(mappingError(key + QString::fromStdString(e.what()) + " in element " + QString::number(i))); } } else { emit(mappingError(key + " no supported mapping found in midi mapping element " + QString::number(i))); return; } if (node["mult"]) mmap->multiplier = node["mult"].as<double>(); if (node["offset"]) mmap->offset = node["offset"].as<double>(); //XXX search for conflicting maps and warn mMappings.push_back(mmap); } catch (YAML::Exception& e) { emit(mappingError(key + " exception processing midi mapping element " + QString::number(i) + " " + QString(e.what()))); return; } catch(...) { emit(mappingError(key + " exception processing midi mapping element " + QString::number(i))); return; } } } }