A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 365 lines 12 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2012 by Amaury Pouly 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include "soc_desc_v1.hpp" 22#include <stdio.h> 23#include <stdlib.h> 24#include <map> 25#include <cstring> 26 27using namespace soc_desc_v1; 28 29template< typename T > 30bool build_map(const char *type, const std::vector< T >& vec, 31 std::map< std::string, size_t >& map) 32{ 33 for(size_t i = 0; i < vec.size(); i++) 34 { 35 if(map.find(vec[i].name) != map.end()) 36 { 37 printf("soc has duplicate %s '%s'\n", type, vec[i].name.c_str()); 38 return false; 39 } 40 map[vec[i].name] = i; 41 } 42 return true; 43} 44 45template< typename T > 46bool build_map(const char *type, const std::vector< T >& a, const std::vector< T >& b, 47 std::vector< std::pair< size_t, size_t > >& m) 48{ 49 std::map< std::string, size_t > ma, mb; 50 if(!build_map(type, a, ma) || !build_map(type, b, mb)) 51 return false; 52 std::map< std::string, size_t >::iterator it; 53 for(it = ma.begin(); it != ma.end(); ++it) 54 { 55 if(mb.find(it->first) == mb.end()) 56 { 57 printf("%s '%s' exists in only one file\n", type, it->first.c_str()); 58 return false; 59 } 60 m.push_back(std::make_pair(it->second, mb[it->first])); 61 } 62 for(it = mb.begin(); it != mb.end(); ++it) 63 { 64 if(ma.find(it->first) == ma.end()) 65 { 66 printf("%s '%s' exists in only one file\n", type, it->first.c_str()); 67 return false; 68 } 69 } 70 return true; 71} 72 73bool compare_value(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg, 74 const soc_reg_field_t& field, const soc_reg_field_value_t& a, const soc_reg_field_value_t& b) 75{ 76 if(a.value != b.value) 77 { 78 printf("register field value '%s.%s.%s.%s.%s' have different values\n", soc.name.c_str(), 79 dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str()); 80 return false; 81 } 82 if(a.desc != b.desc) 83 { 84 printf("register field value '%s.%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(), 85 dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str()); 86 return false; 87 } 88 return true; 89} 90 91bool compare_field(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg, 92 const soc_reg_field_t& a, const soc_reg_field_t& b) 93{ 94 if(a.first_bit != b.first_bit || a.last_bit != b.last_bit) 95 { 96 printf("register address '%s.%s.%s.%s' have different bit ranges\n", soc.name.c_str(), 97 dev.name.c_str(), reg.name.c_str(), a.name.c_str()); 98 return false; 99 } 100 if(a.desc != b.desc) 101 { 102 printf("register address '%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(), 103 dev.name.c_str(), reg.name.c_str(), a.name.c_str()); 104 return false; 105 } 106 /* values */ 107 std::vector< std::pair< size_t, size_t > > map; 108 if(!build_map("field value", a.value, b.value, map)) 109 return false; 110 for(size_t i = 0; i < map.size(); i++) 111 if(!compare_value(soc, dev, reg, a, a.value[map[i].first], b.value[map[i].second])) 112 return false; 113 return true; 114} 115 116bool compare_reg_addr(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg, 117 const soc_reg_addr_t& a, const soc_reg_addr_t& b) 118{ 119 if(a.addr != b.addr) 120 { 121 printf("register address '%s.%s.%s.%s' have different values\n", soc.name.c_str(), 122 dev.name.c_str(), reg.name.c_str(), a.name.c_str()); 123 return false; 124 } 125 else 126 return true; 127} 128 129bool compare_reg(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& a, 130 const soc_reg_t& b) 131{ 132 if(a.desc != b.desc) 133 { 134 printf("register '%s.%s.%s' have different descriptions\n", soc.name.c_str(), 135 dev.name.c_str(), a.name.c_str()); 136 return false; 137 } 138 if(a.flags != b.flags) 139 { 140 printf("device '%s.%s.%s' have different flags\n", soc.name.c_str(), 141 dev.name.c_str(), a.name.c_str()); 142 return false; 143 } 144 if(a.formula.type != b.formula.type) 145 { 146 printf("device '%s.%s.%s' have different formula types\n", soc.name.c_str(), 147 dev.name.c_str(), a.name.c_str()); 148 return false; 149 } 150 if(a.formula.string != b.formula.string) 151 { 152 printf("device '%s.%s.%s' have different formula string\n", soc.name.c_str(), 153 dev.name.c_str(), a.name.c_str()); 154 return false; 155 } 156 /* addresses */ 157 std::vector< std::pair< size_t, size_t > > map; 158 if(!build_map("register address", a.addr, b.addr, map)) 159 return false; 160 for(size_t i = 0; i < map.size(); i++) 161 if(!compare_reg_addr(soc, dev, a, a.addr[map[i].first], b.addr[map[i].second])) 162 return false; 163 /* field */ 164 map.clear(); 165 if(!build_map("field", a.field, b.field, map)) 166 return false; 167 for(size_t i = 0; i < map.size(); i++) 168 if(!compare_field(soc, dev, a, a.field[map[i].first], b.field[map[i].second])) 169 return false; 170 return true; 171} 172 173bool compare_dev_addr(const soc_t& soc, const soc_dev_t& dev, const soc_dev_addr_t& a, 174 const soc_dev_addr_t& b) 175{ 176 if(a.addr != b.addr) 177 { 178 printf("device address '%s.%s.%s' have different values\n", soc.name.c_str(), 179 dev.name.c_str(), a.name.c_str()); 180 return false; 181 } 182 else 183 return true; 184} 185 186bool compare_dev(const soc_t& soc, const soc_dev_t& a, const soc_dev_t& b) 187{ 188 if(a.long_name != b.long_name) 189 { 190 printf("device '%s.%s' have different long names\n", soc.name.c_str(), 191 a.name.c_str()); 192 return false; 193 } 194 if(a.desc != b.desc) 195 { 196 printf("device '%s.%s' have different descriptions\n", soc.name.c_str(), 197 a.name.c_str()); 198 return false; 199 } 200 if(a.version != b.version) 201 { 202 printf("device '%s.%s' have different versions\n", soc.name.c_str(), 203 a.name.c_str()); 204 return false; 205 } 206 /* addresses */ 207 std::vector< std::pair< size_t, size_t > > map; 208 if(!build_map("device address", a.addr, b.addr, map)) 209 return false; 210 for(size_t i = 0; i < map.size(); i++) 211 if(!compare_dev_addr(soc, a, a.addr[map[i].first], b.addr[map[i].second])) 212 return false; 213 /* reg */ 214 map.clear(); 215 if(!build_map("register", a.reg, b.reg, map)) 216 return false; 217 for(size_t i = 0; i < map.size(); i++) 218 if(!compare_reg(soc, a, a.reg[map[i].first], b.reg[map[i].second])) 219 return false; 220 return true; 221} 222 223bool compare_soc(const soc_t& a, const soc_t& b) 224{ 225 if(a.name != b.name) 226 { 227 return printf("soc have different names\n"); 228 return false; 229 } 230 if(a.desc != b.desc) 231 { 232 printf("soc '%s' have different descriptions\n", a.name.c_str()); 233 return false; 234 } 235 std::vector< std::pair< size_t, size_t > > map; 236 if(!build_map("device", a.dev, b.dev, map)) 237 return false; 238 for(size_t i = 0; i< map.size(); i++) 239 if(!compare_dev(a, a.dev[map[i].first], b.dev[map[i].second])) 240 return false; 241 return true; 242} 243 244int do_compare(int argc, char **argv) 245{ 246 if(argc != 2) 247 return printf("compare mode expects two arguments\n"); 248 soc_t soc[2]; 249 if(!parse_xml(argv[0], soc[0])) 250 return printf("cannot read file '%s'\n", argv[0]); 251 if(!parse_xml(argv[1], soc[1])) 252 return printf("cannot read file '%s'\n", argv[1]); 253 if(compare_soc(soc[0], soc[1])) 254 printf("Files are identical.\n"); 255 return 0; 256} 257 258int do_write(int argc, char **argv) 259{ 260 if(argc != 2) 261 return printf("write mode expects two arguments\n"); 262 soc_t soc; 263 if(!parse_xml(argv[0], soc)) 264 return printf("cannot read file '%s'\n", argv[0]); 265 if(!produce_xml(argv[1], soc)) 266 return printf("cannot write file '%s'\n", argv[1]); 267 return 0; 268} 269 270int do_check(int argc, char **argv) 271{ 272 for(int i = 0; i < argc; i++) 273 { 274 soc_t soc; 275 if(!parse_xml(argv[i], soc)) 276 { 277 printf("cannot read file '%s'\n", argv[i]); 278 continue; 279 } 280 printf("[%s]\n", argv[i]); 281 std::vector< soc_error_t > errs = soc.errors(true); 282 for(size_t i = 0; i < errs.size(); i++) 283 { 284 const soc_error_t& e = errs[i]; 285 switch(e.level) 286 { 287 case SOC_ERROR_WARNING: printf("[WARN ] "); break; 288 case SOC_ERROR_FATAL: printf("[FATAL] "); break; 289 default: printf("[ UNK ] "); break; 290 } 291 printf("%s: %s\n", e.location.c_str(), e.message.c_str()); 292 } 293 } 294 return 0; 295} 296 297int do_eval(int argc, char **argv) 298{ 299 std::map< std::string, soc_word_t > map; 300 for(int i = 0; i < argc; i++) 301 { 302 std::string error; 303 std::string formula(argv[i]); 304 soc_word_t result; 305 if(strcmp(argv[i], "--var") == 0) 306 { 307 if(i + 1 >= argc) 308 break; 309 i++; 310 std::string str(argv[i]); 311 size_t pos = str.find('='); 312 if(pos == std::string::npos) 313 { 314 printf("invalid variable string '%s'\n", str.c_str()); 315 continue; 316 } 317 std::string name = str.substr(0, pos); 318 std::string val = str.substr(pos + 1); 319 char *end; 320 soc_word_t v = strtoul(val.c_str(), &end, 0); 321 if(*end) 322 { 323 printf("invalid variable string '%s'\n", str.c_str()); 324 continue; 325 } 326 printf("%s = %#lx\n", name.c_str(), (unsigned long)v); 327 map[name] = v; 328 continue; 329 } 330 if(!evaluate_formula(formula, map, result, error)) 331 printf("error: %s\n", error.c_str()); 332 else 333 printf("result: %lu (%#lx)\n", (unsigned long)result, (unsigned long)result); 334 } 335 return 0; 336} 337 338void usage() 339{ 340 printf("usage: tester <mode> [options]\n"); 341 printf("modes:\n"); 342 printf(" compare <desc file> <desc file>\n"); 343 printf(" write <read file> <write file>\n"); 344 printf(" check <files...>\n"); 345 printf(" eval [<formula>|--var <name>=<val>]...\n"); 346 exit(1); 347} 348 349int main(int argc, char **argv) 350{ 351 if(argc < 2) 352 usage(); 353 std::string mode = argv[1]; 354 if(mode == "compare") 355 return do_compare(argc - 2, argv + 2); 356 else if(mode == "write") 357 return do_write(argc - 2, argv + 2); 358 else if(mode == "check") 359 return do_check(argc - 2, argv + 2); 360 else if(mode == "eval") 361 return do_eval(argc - 2, argv + 2); 362 else 363 usage(); 364 return 0; 365}