From 86bbd12c3889db3290e22ff61934ca1a218ce114 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 27 Apr 2018 21:42:05 -0400 Subject: New config system --- include/libsurvive/survive.h | 21 +--- src/poser_general_optimizer.c | 13 +- src/poser_sba.c | 23 ++-- src/survive.c | 92 +++++++++++---- src/survive_cal.c | 7 +- src/survive_config.c | 267 +++++++++++++++++++++++++++++++++--------- src/survive_config.h | 17 ++- src/survive_driver_dummy.c | 5 +- src/survive_playback.c | 12 +- src/survive_vive.c | 1 + 10 files changed, 343 insertions(+), 115 deletions(-) diff --git a/include/libsurvive/survive.h b/include/libsurvive/survive.h index 831113d..d6b43ef 100644 --- a/include/libsurvive/survive.h +++ b/include/libsurvive/survive.h @@ -234,10 +234,6 @@ struct SurviveContext { struct config_group *global_config_values; struct config_group *lh_config; // lighthouse configs struct config_group *temporary_config_values; // Set per-session, from command-line. Not saved but override global_config_values - - //shorthand configs for the non-function-call syntax config variables. - //It helps with self-documentation, too. Indexes into this are determined by `static_configs` - union { int i; FLT f; const char * s; } shorthand_configs[MAX_SHORTHAND_CONFIGS]; }; SURVIVE_EXPORT void survive_verify_FLT_size( @@ -290,19 +286,12 @@ SURVIVE_EXPORT int survive_send_magic(SurviveContext *ctx, int magic_code, void SURVIVE_EXPORT FLT survive_configf(SurviveContext *ctx, const char *tag, char flags, FLT def); SURVIVE_EXPORT uint32_t survive_configi(SurviveContext *ctx, const char *tag, char flags, uint32_t def); SURVIVE_EXPORT const char *survive_configs(SurviveContext *ctx, const char *tag, char flags, const char *def); +SURVIVE_EXPORT void survive_attach_config(SurviveContext *ctx, const char *tag, void * var, char type ); +SURVIVE_EXPORT void survive_detach_config(SurviveContext *ctx, const char *tag, void * var ); -#define STATIC_CONFIG_ITEM_I( variable, name, description, default_value ) static int variable; \ - SURVIVE_EXPORT_CONSTRUCTOR void REGISTER##variable() { survive_config_bind_variable( 'i', &variable, name, description, default_value ); } -#define GCONFIGI( variable ) (ctx->shorthand_configs[variable].i) - -#define STATIC_CONFIG_ITEM_F( variable, name, description, default_value ) static int variable; \ - SURVIVE_EXPORT_CONSTRUCTOR void REGISTER##variable() { survive_config_bind_variable( 'f', &variable, name, description, default_value ); } -#define GCONFIGF( variable ) (ctx->shorthand_configs[variable].f) - -#define STATIC_CONFIG_ITEM_S( variable, name, description, default_value ) static int variable; \ - SURVIVE_EXPORT_CONSTRUCTOR void REGISTER##variable() { survive_config_bind_variable( 's', &variable, name, description, default_value ); } -#define GCONFIGS( variable ) (ctx->shorthand_configs[variable].s) - +#define STATIC_CONFIG_ITEM( variable, name, type, description, default_value ) \ + SURVIVE_EXPORT_CONSTRUCTOR void REGISTER##variable() { survive_config_bind_variable( type, name, description, default_value ); } + void survive_config_bind_variable( char vt, const char * name, const char * description, ... ); //Only used at boot. // Install the calibrator. SURVIVE_EXPORT void survive_cal_install(SurviveContext *ctx); // XXX This will be removed if not already done so. diff --git a/src/poser_general_optimizer.c b/src/poser_general_optimizer.c index 057ac3d..186b359 100644 --- a/src/poser_general_optimizer.c +++ b/src/poser_general_optimizer.c @@ -5,6 +5,11 @@ #include #include +STATIC_CONFIG_ITEM( CONFIG_MAX_ERROR, "max-error", 'f', "Maximum error permitted by poser_general_optimizer", .0001 ); +STATIC_CONFIG_ITEM( CONFIG_FAIL_TO_RESET, "failures-to-reset", 'i', "Failures needed before seed poser is re-run", 1 ); +STATIC_CONFIG_ITEM( CONFIG_SUC_TO_RESET, "successes-to-reset", 'i', "[TODO: I don't know what this does]", -1 ); +STATIC_CONFIG_ITEM( CONFIG_SEED_POSER, "seed-poser", 's', "Poser to be used to seed optimizer", "PoserEPNP" ); + void *GetDriver(const char *name); void general_optimizer_data_init(GeneralOptimizerData *d, SurviveObject *so) { memset(d, 0, sizeof(*d)); @@ -12,11 +17,11 @@ void general_optimizer_data_init(GeneralOptimizerData *d, SurviveObject *so) { SurviveContext *ctx = so->ctx; - d->failures_to_reset = survive_configi(ctx, "failures-to-reset", SC_GET, 1); - d->successes_to_reset = survive_configi(ctx, "successes-to-reset", SC_GET, -1); - d->max_error = survive_configf(ctx, "max-error", SC_GET, .0001); + survive_attach_config( ctx, "failures-to-reset", &d->failures_to_reset, 'i' ); + survive_attach_config( ctx, "successes-to-reset", &d->successes_to_reset, 'i' ); + survive_attach_config( ctx, "max-error", &d->max_error, 'f' ); - const char *subposer = survive_configs(ctx, "seed-poser", SC_GET, "PoserEPNP"); + const char *subposer = survive_configs(ctx, "seed-poser", SC_GET, 0 ); d->seed_poser = (PoserCB)GetDriver(subposer); SV_INFO("Initializing general optimizer:"); diff --git a/src/poser_sba.c b/src/poser_sba.c index ed19c1d..21dd74f 100644 --- a/src/poser_sba.c +++ b/src/poser_sba.c @@ -20,6 +20,14 @@ #include "survive_kalman.h" #include "survive_reproject.h" + +STATIC_CONFIG_ITEM( SBA_USE_IMU, "sba-use-imu", 'i', "[TODO: I don't know what this does]", 1 ); +STATIC_CONFIG_ITEM( SBA_REQUIRED_MEAS, "sba-required-meas", 'i', "[TODO: I don't know what this does]", 8 ); +STATIC_CONFIG_ITEM( SBA_TIME_WINDOW, "sba-time-window", 'i', "[TODO: I don't know what this does]", (int)SurviveSensorActivations_default_tolerance ); +STATIC_CONFIG_ITEM( SBA_SENSOR_VARIANCE_PER_SEC, "sba-sensor-variance-per-sec", 'f', "[TODO: I don't know what this does]", 10.0 ); +STATIC_CONFIG_ITEM( SBA_SENSOR_VARIANCE, "sba-sensor-variance", 'f', "[TODO: I don't know what this does]", 1.0 ); +STATIC_CONFIG_ITEM( SBA_USE_JACOBIAN_FUNCTION, "sba-use-jacobian-function", 'i', "Poser to be used to seed optimizer", 1); + typedef struct { PoserData *pdfs; SurviveObject *so; @@ -343,14 +351,13 @@ int PoserSBA(SurviveObject *so, PoserData *pd) { SBAData *d = so->PoserData; general_optimizer_data_init(&d->opt, so); - d->useIMU = survive_configi(ctx, "sba-use-imu", SC_GET, 1); - d->required_meas = survive_configi(ctx, "sba-required-meas", SC_GET, 8); - - d->sensor_time_window = - survive_configi(ctx, "sba-time-window", SC_GET, SurviveSensorActivations_default_tolerance * 2); - d->sensor_variance_per_second = survive_configf(ctx, "sba-sensor-variance-per-sec", SC_GET, 10.0); - d->sensor_variance = survive_configf(ctx, "sba-sensor-variance", SC_GET, 1.0); - d->use_jacobian_function = survive_configi(ctx, "sba-use-jacobian-function", SC_GET, 1.0); + + survive_attach_config( ctx, "sba-use-imu", &d->useIMU, 'i' ); + survive_attach_config( ctx, "sba-required-meas", &d->required_meas, 'i' ); + survive_attach_config( ctx, "sba-time-window", &d->sensor_time_window, 'i' ); + survive_attach_config( ctx, "sba-sensor-variance-per-sec", &d->sensor_variance_per_second, 'f' ); + survive_attach_config( ctx, "sba-sensor-variance", &d->sensor_variance, 'f' ); + survive_attach_config( ctx, "sba-use-jacobian-function", &d->use_jacobian_function, 'i' ); SV_INFO("Initializing SBA:"); SV_INFO("\tsba-required-meas: %d", d->required_meas); diff --git a/src/survive.c b/src/survive.c index 20a2a1b..2bdefca 100644 --- a/src/survive.c +++ b/src/survive.c @@ -16,6 +16,10 @@ #define z_const const #endif +STATIC_CONFIG_ITEM( CONFIG_FILE, "configfile", 's', "Default configuration file", "config.json" ); +STATIC_CONFIG_ITEM( CONFIG_D_CALI, "disable-calibrate", 'i', "Enables or disables calibration", 0 ); +STATIC_CONFIG_ITEM( CONFIG_F_CALI, "force-calibrate", 'i', "Forces calibration even if one exists.", 0 ); + #ifdef RUNTIME_SYMNUM #include static int did_runtime_symnum; @@ -93,6 +97,20 @@ void survive_verify_FLT_size(uint32_t user_size) { } } +static void PrintMatchingDrivers( const char * prefix, const char * matchingparam ) +{ + int i = 0; + char stringmatch[128]; + snprintf( stringmatch, 127, "%s%s", prefix, matchingparam?matchingparam:"" ); + const char * DriverName; + while ((DriverName = GetDriverNameMatching(stringmatch, i++))) + { + printf( "%s ", DriverName+strlen(prefix) ); + } +} + + + SurviveContext *survive_init_internal(int argc, char *const *argv) { int i; @@ -133,8 +151,6 @@ SurviveContext *survive_init_internal(int argc, char *const *argv) { ctx->state = SURVIVE_STOPPED; - survive_config_populate_ctx( ctx ); - ctx->global_config_values = malloc(sizeof(config_group)); ctx->temporary_config_values = malloc(sizeof(config_group)); ctx->lh_config = malloc(sizeof(config_group) * NUM_LIGHTHOUSES); @@ -148,6 +164,8 @@ SurviveContext *survive_init_internal(int argc, char *const *argv) { // Process command-line parameters. char *const *av = argv + 1; char *const *argvend = argv + argc; + int list_for_autocomplete = 0; + const char * autocomplete_match[3] = { 0, 0, 0}; int showhelp = 0; for (; av < argvend; av++) { if ((*av)[0] != '-') @@ -168,6 +186,13 @@ SurviveContext *survive_init_internal(int argc, char *const *argv) { case 'l': vartoupdate = "lighthousecount"; break; + case 'm': + if( av + 1 < argvend ) autocomplete_match[0] = *(av+1); + if( av + 2 < argvend ) autocomplete_match[1] = *(av+2); + if( av + 3 < argvend ) autocomplete_match[2] = *(av+3); + list_for_autocomplete = 1; + av = argvend; //Eject immediately after processing -m + break; case 'c': vartoupdate = "configfile"; break; @@ -196,33 +221,54 @@ SurviveContext *survive_init_internal(int argc, char *const *argv) { } } } - if (showhelp) { - // Can't use SV_ERROR here since we don't have a context to send to yet. - fprintf(stderr, "libsurvive - usage:\n"); - fprintf(stderr, " --[parameter] [value] - sets parameter\n"); - fprintf(stderr, " -h - shows help.\n"); - fprintf(stderr, " -p [poser] - use a specific defaultposer.\n"); - fprintf(stderr, " -l [lighthouse count] - use a specific number of lighthoses.\n"); - fprintf(stderr, " -c [config file] - set config file\n"); - fprintf(stderr, " --record [log file] - Write all events to the given record file.\n"); - fprintf(stderr, " --playback [log file] - Read events from the given file instead of USB devices.\n"); - fprintf(stderr, " --playback-factor [f] - Time factor of playback -- 1 is run at the same timing as " - "original, 0 is run as fast as possible.\n"); - } - config_read(ctx, survive_configs(ctx, "configfile", SC_GET, "config.json")); ctx->activeLighthouses = survive_configi(ctx, "lighthousecount", SC_SETCONFIG, 2); config_read_lighthouse(ctx->lh_config, &(ctx->bsd[0]), 0); config_read_lighthouse(ctx->lh_config, &(ctx->bsd[1]), 1); + ctx->faultfunction = survivefault; + ctx->notefunction = survivenote; + + if( list_for_autocomplete ) + { + const char * lastparam = (autocomplete_match[2]==0)?autocomplete_match[1]:autocomplete_match[2]; + const char * matchingparam = (autocomplete_match[2]==0)?0:autocomplete_match[1]; + //First see if any of the parameters perfectly match a config item, if so print some help. + //fprintf( stderr, "!!! %s !!! %s !!!\n", lastparam, matchingparam ); + + const char * checkconfig = matchingparam; + if( matchingparam == 0 ) checkconfig = lastparam; + + if( checkconfig && strlen( checkconfig ) > 2 && survive_print_help_for_parameter( checkconfig+2 ) ) + { + exit(0); + } + + if( strstr( lastparam, "poser" ) ) PrintMatchingDrivers( "Poser", matchingparam ); + else if( strstr( lastparam, "disambiguator" ) ) PrintMatchingDrivers( "Disambiguator", matchingparam ); + else + { + printf( "-h -m -p -l -c " ); + survive_print_known_configs( ctx, 0 ); + } + printf( "\n" ); + exit( 0 ); + } + if( showhelp ) { - survive_print_known_configs( ctx ); + // Can't use SV_ERROR here since we don't have a context to send to yet. + fprintf(stderr, "libsurvive - usage:\n"); + fprintf(stderr, " -h - shows help.\n"); + fprintf(stderr, " -m - list parameters, for autocomplete." ); + fprintf(stderr, " -p [poser] - use a specific defaultposer.\n"); + fprintf(stderr, " -l [lighthouse count] - use a specific number of lighthoses.\n"); + fprintf(stderr, " -c [config file] - set config file\n"); + fprintf(stderr, "Additional --[parameter] [value] - sets generic parameters...\n"); + survive_print_known_configs( ctx, 1 ); return 0; } - ctx->faultfunction = survivefault; - ctx->notefunction = survivenote; ctx->lightproc = survive_default_light_process; ctx->imuproc = survive_default_imu_process; ctx->angleproc = survive_default_angle_process; @@ -319,10 +365,10 @@ int survive_startup(SurviveContext *ctx) { ctx->state = SURVIVE_RUNNING; - int calibrateMandatory = survive_configi(ctx, "calibrate", SC_GET, 0); - int calibrateForbidden = survive_configi(ctx, "calibrate", SC_GET, 1) == 0; + int calibrateMandatory = survive_configi(ctx, "force-calibrate", SC_GET, 0); + int calibrateForbidden = survive_configi(ctx, "disable-calibrate", SC_GET, 1) == 0; if (calibrateMandatory && calibrateForbidden) { - SV_INFO("Contradictory settings --calibrate and --no-calibrate specified. Switching to normal behavior."); + SV_INFO("Contradictory settings --force-calibrate and --disable-calibrate specified. Switching to normal behavior."); calibrateMandatory = calibrateForbidden = 0; } @@ -334,7 +380,7 @@ int survive_startup(SurviveContext *ctx) { if (!isCalibrated) { SV_INFO("Uncalibrated configuration detected. Attaching calibration. Please don't move tracked objects for " - "the duration of calibration. Pass '--no-calibrate' to skip calibration"); + "the duration of calibration. Pass '--disable-calibrate' to skip calibration"); } else { SV_INFO("Calibration requested. Previous calibration will be overwritten."); } diff --git a/src/survive_cal.c b/src/survive_cal.c index ad62d22..cf65166 100755 --- a/src/survive_cal.c +++ b/src/survive_cal.c @@ -27,6 +27,11 @@ int mkdir(const char *); #endif + +STATIC_CONFIG_ITEM( REQ_TRACK_FOR_CAL, "requiredtrackersforcal", 's', "Which devices will be used, i.e. HMD,WM0,WM1", "" ); +STATIC_CONFIG_ITEM( ALLOW_TRACK_FOR_CAL, "allowalltrackersforcal", 'i', "Allow use of additional connected devices for calibration", 0 ); +STATIC_CONFIG_ITEM( CONFIG_POSER, "configposer", 's', "Poser used for calibration step", "SBA" ); + #define PTS_BEFORE_COMMON 32 #define NEEDED_COMMON_POINTS 10 #define MIN_SENSORS_VISIBLE_PER_LH_FOR_CAL 4 @@ -145,7 +150,7 @@ void survive_cal_install( struct SurviveContext * ctx ) // basically, libsurvive will detect whatever they have plugged in and start using that. // const char * RequiredTrackersForCal = config_read_str(ctx->global_config_values, "RequiredTrackersForCal", "HMD,WM0,WM1"); const char *RequiredTrackersForCal = survive_configs(ctx, "requiredtrackersforcal", SC_SETCONFIG, ""); - const uint32_t AllowAllTrackersForCal = survive_configi(ctx, "allowalltrackersforcal", SC_SETCONFIG, 1); + const uint32_t AllowAllTrackersForCal = survive_configi(ctx, "allowalltrackersforcal", SC_SETCONFIG, 0); size_t requiredTrackersFound = 0; for (int j=0; j < ctx->objs_ct; j++) diff --git a/src/survive_config.c b/src/survive_config.c index 92c0125..23433c4 100644 --- a/src/survive_config.c +++ b/src/survive_config.c @@ -28,28 +28,32 @@ struct static_conf_t }; static struct static_conf_t static_configs[MAX_SHORTHAND_CONFIGS]; +int nr_static_configs; -void survive_config_bind_variable( char vt, int * variable, const char * name, const char * description, ... ) +void survive_config_bind_variable( char vt, const char * name, const char * description, ... ) { va_list ap; va_start(ap, description); int i; struct static_conf_t * config; - for( i = 0; i < MAX_SHORTHAND_CONFIGS; i++ ) + for( i = 0; i < nr_static_configs; i++ ) { config = &static_configs[i]; - if( !config->name || strcmp( config->name, name ) == 0 ) break; + if( strcmp( config->name, name ) == 0 ) break; } + config = &static_configs[i]; if( i == MAX_SHORTHAND_CONFIGS ) { fprintf( stderr, "Fatal: Too many static configuration items. Please recompile with a higher MAX_STATIC_CONFIGS\n" ); exit( -1 ); } + if( i == nr_static_configs ) nr_static_configs++; + if( !config->description ) config->description = description; if( !config->name ) config->name = name; if( config->type && config->type != vt ) { - fprintf( stderr, "Fatal: Internal error on variable %s. Types disagree.\n", name ); + fprintf( stderr, "Fatal: Internal error on variable %s. Types disagree [%c/%c].\n", name, config->type, vt ); exit( -2 ); } config->type = vt; @@ -61,50 +65,113 @@ void survive_config_bind_variable( char vt, int * variable, const char * name, c default: fprintf( stderr, "Fatal: Internal error on variable %s. Unknown type %c\n", name, vt ); } - *variable = i; } -void survive_config_populate_ctx( SurviveContext * ctx ) +int survive_print_help_for_parameter( const char * tomap ) { int i; - struct static_conf_t * config; - for( i = 0; i < MAX_SHORTHAND_CONFIGS; i++ ) + for( i = 0; i < nr_static_configs; i++ ) { - config = &static_configs[i]; - switch( config->type ) + struct static_conf_t * sc = &static_configs[i]; + if( strcmp( sc->name, tomap ) == 0 ) { - case 'i': ctx->shorthand_configs[i].i = config->data_default.i; - case 'f': ctx->shorthand_configs[i].f = config->data_default.f; - case 's': ctx->shorthand_configs[i].s = config->data_default.s; + char sthelp[160]; + snprintf( sthelp, 159, " %s: %s [%c]", sc->name, sc->description, sc->type ); + fprintf( stderr, "\0337\033[1A\033[1000D%s\0338", sthelp, strlen( sthelp )); + return 1; } } + return 0; } -void survive_print_known_configs( SurviveContext * ctx ) +static void PrintConfigGroup(config_group * grp, const char ** chkval, int * cvs, int verbose ) { - int i; - struct static_conf_t * config; - for( i = 0; i < MAX_SHORTHAND_CONFIGS; i++ ) + int i, j; + for( i = 0; i < grp->used_entries; i++ ) { - config = &static_configs[i]; - if( !config->name ) break; - switch( config->type ) + config_entry * ce = &grp->config_entries[i]; + for( j = 0; j < *cvs; j++ ) + { + if( strcmp( chkval[j], ce->tag ) == 0 ) break; + } + if( j == *cvs ) { - case 'i': printf( "%10d %20s %s\n", config->data_default.i, config->name, config->description ); break; - case 'f': printf( "%10f %20s %s\n", config->data_default.f, config->name, config->description ); break; - case 's': printf( "%10s %20s %s\n", config->data_default.s, config->name, config->description ); break; + if( verbose ) + { + char stobuf[128]; + switch( ce->type ) + { + case CONFIG_UINT32: snprintf( stobuf, 127, " --%s %d", ce->tag, ce->numeric.i ); break; + case CONFIG_FLOAT: snprintf( stobuf, 127, " --%s %f", ce->tag, ce->numeric.f ); break; + case CONFIG_STRING: snprintf( stobuf, 127, " --%s %s", ce->tag, ce->data ); break; + case CONFIG_FLOAT_ARRAY: printf( "[FA] %20s", ce->tag ); break; + } + + int namepad = 40 - strlen( stobuf ); + printf( "%s%*c", stobuf, namepad, (ce->type==CONFIG_FLOAT)?'f':(ce->type==CONFIG_UINT32)?'i':(ce->type==CONFIG_STRING)?'s':'.' ); + + //Try to get description from the static tags. + for( j = 0; j < nr_static_configs; j++ ) + { + if( strcmp( static_configs[j].name, ce->tag ) == 0 ) + { + printf( " %s", static_configs[j].description ); + } + } + printf( "\n" ); + } + else + { + printf( "--%s ", ce->tag ); + } + chkval[*cvs] = ce->tag; + (*cvs)++; } } - - //XXX TODO: Maybe this should print out the actual config values after being updated from the rest of the config system? - //struct config_group *global_config_values; - //struct config_group *temporary_config_values; // Set per-session, from command-line. Not saved but override global_config_values } +void survive_print_known_configs( SurviveContext * ctx, int verbose ) +{ + int i; - - - + const char * checked_values[256]; + int cvs = 0; + memset( checked_values, 0, sizeof( checked_values ) ); + PrintConfigGroup( ctx->temporary_config_values, checked_values, &cvs, verbose ); + PrintConfigGroup( ctx->global_config_values, checked_values, &cvs, verbose ); + int j; + for( j = 0; j < nr_static_configs; j++ ) + { + for( i = 0; i < cvs; i++ ) + { + if( strcmp( static_configs[j].name, checked_values[i] ) == 0 ) + break; + } + if( i == cvs ) + { + struct static_conf_t * config = &static_configs[j]; + const char * name = config->name; + + if( verbose ) + { + char stobuf[128]; + switch( config->type ) + { + case 'i': snprintf( stobuf, 127, " --%s %d", name, config->data_default.i ); break; + case 'f': snprintf( stobuf, 127, " --%s %f", name, config->data_default.f ); break; + case 's': snprintf( stobuf, 127, " --%s %s", name, config->data_default.s ); break; + case 'a': snprintf( stobuf, 127, "[FA] %25s %s\n", config->name, config->description ); break; + } + int namepad = 40 - strlen( stobuf ); + printf( "%s%*c %s\n", stobuf, namepad, config->type, config->description ); + } + else + { + printf( "--%s ", name ); + } + } + } +} const FLT *config_set_float_a(config_group *cg, const char *tag, const FLT *values, uint8_t count); @@ -113,7 +180,7 @@ void init_config_entry(config_entry *ce) { ce->tag = NULL; ce->type = CONFIG_UNKNOWN; ce->elements = 0; - ce->shorthand_place = -1; + ce->update_list = 0; } void destroy_config_entry(config_entry *ce) { @@ -313,20 +380,6 @@ config_entry *next_unused_entry(config_group *cg, const char * tag) { cg->used_entries++; - - int i; - struct static_conf_t * config; - for( i = 0; i < MAX_SHORTHAND_CONFIGS; i++ ) - { - config = &static_configs[i]; - if( !config->name ) break; - if( strcmp( config->name, tag ) == 0 ) - { - cv->shorthand_place = i; - break; - } - } - return cv; } @@ -344,7 +397,8 @@ const char *config_set_str(config_group *cg, const char *tag, const char *value) } cv->type = CONFIG_STRING; - if( cv->shorthand_place >= 0 ) cg->ctx->shorthand_configs[cv->shorthand_place].s = value; + update_list_t * t = cv->update_list; + while( t ) { *((const char **)t->value) = value; t = t->next; } return value; } @@ -358,7 +412,8 @@ const uint32_t config_set_uint32(config_group *cg, const char *tag, const uint32 cv->numeric.i = value; cv->type = CONFIG_UINT32; - if( cv->shorthand_place >= 0 ) cg->ctx->shorthand_configs[cv->shorthand_place].i = value; + update_list_t * t = cv->update_list; + while( t ) { *((uint32_t*)t->value) = value; t = t->next; } return value; } @@ -372,7 +427,9 @@ const FLT config_set_float(config_group *cg, const char *tag, const FLT value) { cv->numeric.f = value; cv->type = CONFIG_FLOAT; - if( cv->shorthand_place >= 0 ) cg->ctx->shorthand_configs[cv->shorthand_place].f = value; + + update_list_t * t = cv->update_list; + while( t ) { *((FLT*)t->value) = value; t = t->next; } return value; } @@ -610,6 +667,21 @@ FLT survive_configf(SurviveContext *ctx, const char *tag, char flags, FLT def) { } } + + int i; + if( !(flags & SC_OVERRIDE) ) + { + for( i = 0; i < nr_static_configs; i++ ) + { + struct static_conf_t * sc = &static_configs[i]; + if( strcmp( tag, sc->name ) == 0 ) + { + def = sc->data_default.f; + } + } + } + + // If override is flagged, or, we can't find the variable, ,continue on. if (flags & SC_SETCONFIG) { config_set_float(ctx->temporary_config_values, tag, def); @@ -629,6 +701,21 @@ uint32_t survive_configi(SurviveContext *ctx, const char *tag, char flags, uint3 } } + uint32_t statictimedef = def; + int i; + if( !(flags & SC_OVERRIDE) ) + { + for( i = 0; i < nr_static_configs; i++ ) + { + struct static_conf_t * sc = &static_configs[i]; + if( strcmp( tag, sc->name ) == 0 ) + { + def = sc->data_default.i; + } + } + } + + // If override is flagged, or, we can't find the variable, ,continue on. if (flags & SC_SETCONFIG) { config_set_uint32(ctx->temporary_config_values, tag, def); @@ -647,15 +734,87 @@ const char *survive_configs(SurviveContext *ctx, const char *tag, char flags, co return cv->data; } - // If override is flagged, or, we can't find the variable, ,continue on. - if (flags & SC_SETCONFIG) { - config_set_str(ctx->temporary_config_values, tag, def); - config_set_str(ctx->global_config_values, tag, def); - } else if (flags & SC_SET) { - config_set_str(ctx->temporary_config_values, tag, def); + int i; + char foundtype = 0; + const char * founddata = def; + for( i = 0; i < nr_static_configs; i++ ) + { + struct static_conf_t * sc = &static_configs[i]; + if( !sc ) break; + if( strcmp( tag, sc->name ) == 0 ) + { + founddata = sc->data_default.s; + foundtype = sc->type; + if( !(flags & SC_OVERRIDE) ) + { + def = founddata; + } + } + } + + if( !foundtype || foundtype == 's' ) + { + // If override is flagged, or, we can't find the variable, ,continue on. + if (flags & SC_SETCONFIG) { + config_set_str(ctx->temporary_config_values, tag, def); + config_set_str(ctx->global_config_values, tag, def); + } else if (flags & SC_SET) { + config_set_str(ctx->temporary_config_values, tag, def); + } else { + return founddata; + } + } + else if( foundtype == 'i' ) + { + survive_configi( ctx, tag, flags, atoi( def ) ); + } + else if( foundtype == 'f' ) + { + survive_configf( ctx, tag, flags, atof( def ) ); } return def; } +SURVIVE_EXPORT void survive_attach_config(SurviveContext *ctx, const char *tag, void * var, char type ) +{ + config_entry *cv = sc_search(ctx, tag); + if( !cv ) + { + SV_ERROR( "Configuration item %s not initialized.\n", tag ); + return; + } + update_list_t ** ul = &cv->update_list; + while( *ul ) + { + if( (*ul)->value == var ) return; + ul = &((*ul)->next); + } + update_list_t * t = *ul = malloc( sizeof( update_list_t ) ); + t->next = 0; + t->value = var; +} + +SURVIVE_EXPORT void survive_detach_config(SurviveContext *ctx, const char *tag, void * var ) +{ + config_entry *cv = sc_search(ctx, tag); + if( !cv ) + { + SV_ERROR( "Configuration item %s not initialized.\n", tag ); + return; + } + + update_list_t ** ul = &cv->update_list; + while( *ul ) + { + if( (*ul)->value == var ) + { + update_list_t * v = *ul; + *ul = (*ul)->next; + free( v ); + } + ul = &((*ul)->next); + } +} + diff --git a/src/survive_config.h b/src/survive_config.h index 37e904c..3f823b0 100644 --- a/src/survive_config.h +++ b/src/survive_config.h @@ -16,6 +16,14 @@ typedef enum { CONFIG_FLOAT_ARRAY = 4, } cval_type; +struct update_list_t_s +{ + void * value; + struct update_list_t_s * next; +}; + +typedef struct update_list_t_s update_list_t; + typedef struct { char *tag; @@ -26,7 +34,8 @@ typedef struct { } numeric; char *data; uint32_t elements; - int shorthand_place; + + update_list_t * update_list; } config_entry; typedef struct config_group { @@ -63,8 +72,10 @@ uint32_t config_read_uint32(config_group *cg, const char *tag, const uint32_t de const char* config_read_str(config_group *cg, const char *tag, const char *def); //These are for the internal non-function configuration system. -void survive_config_bind_variable( char vt, int * variable, const char * name, const char * description, ... ); -void survive_print_known_configs(); +void survive_config_bind_variable( char vt, const char * name, const char * description, ... ); +void survive_print_known_configs( SurviveContext * ctx, int verbose ); void survive_config_populate_ctx( SurviveContext * ctx ); +int survive_print_help_for_parameter( const char * tomap ); + #endif diff --git a/src/survive_driver_dummy.c b/src/survive_driver_dummy.c index 01d0482..e305b33 100644 --- a/src/survive_driver_dummy.c +++ b/src/survive_driver_dummy.c @@ -8,7 +8,7 @@ #include "survive_config.h" #include "os_generic.h" -STATIC_CONFIG_ITEM_I( DUMMY_DRIVER_ENABLE, "dummy-driver-enable", "Load a dummy driver for testing.", 0 ); +STATIC_CONFIG_ITEM( DUMMY_DRIVER_ENABLE, "dummy-driver-enable", 'i', "Load a dummy driver for testing.", 0 ); struct SurviveDriverDummy { SurviveContext * ctx; @@ -55,7 +55,8 @@ int dummy_haptic( SurviveObject * so, uint8_t reserved, uint16_t pulseHigh, uint int DriverRegDummy(SurviveContext *ctx) { - if( !GCONFIGI(DUMMY_DRIVER_ENABLE) ) return 0; + int enable = survive_configi( ctx, "dummy-driver-enable", SC_GET, 9 ); + if( !enable ) return 0; SurviveDriverDummy *sp = calloc(1, sizeof(SurviveDriverDummy)); sp->ctx = ctx; diff --git a/src/survive_playback.c b/src/survive_playback.c index a5c4519..df922e2 100644 --- a/src/survive_playback.c +++ b/src/survive_playback.c @@ -21,8 +21,9 @@ ssize_t getdelim(char **lineptr, size_t *n, int delimiter, FILE *stream); ssize_t getline(char **lineptr, size_t *n, FILE *stream); #endif - -STATIC_CONFIG_ITEM_F( PLAYBACK_FACTOR, "playback-factor", "Time factor of playback -- 1 is run at the same timing as original, 0 is run as fast as possible.", 1.0f ); +STATIC_CONFIG_ITEM( RECORD, "record", 's', "File to record to if you wish to make a recording.", "" ); +STATIC_CONFIG_ITEM( PLAYBACK, "playback", 's', "File to be used for playback if playing a recording.", "" ); +STATIC_CONFIG_ITEM( PLAYBACK_FACTOR, "playback-factor", 'f', "Time factor of playback -- 1 is run at the same timing as original, 0 is run as fast as possible.", 1.0f ); typedef struct SurviveRecordingData { @@ -177,6 +178,7 @@ struct SurvivePlaybackData { int lineno; double next_time_us; + FLT playback_factor; bool hasRawLight; }; typedef struct SurvivePlaybackData SurvivePlaybackData; @@ -295,7 +297,7 @@ static int playback_poll(struct SurviveContext *ctx, void *_driver) { line = 0; } - if (driver->next_time_us * GCONFIGF( PLAYBACK_FACTOR ) > timestamp_in_us()) + if (driver->next_time_us * driver->playback_factor > timestamp_in_us()) return 0; driver->next_time_us = 0; @@ -394,7 +396,9 @@ int DriverRegPlayback(SurviveContext *ctx) { return -1; } - SV_INFO("Using playback file '%s' with timefactor of %f", playback_file, GCONFIGF( PLAYBACK_FACTOR ) ); + survive_attach_config( ctx, "playback-factor", &sp->playback_factor, 'f' ); + + SV_INFO("Using playback file '%s' with timefactor of %f", playback_file, sp->playback_factor ); SurviveObject *hmd = survive_create_hmd(ctx, "Playback", sp); SurviveObject *wm0 = survive_create_wm0(ctx, "Playback", sp, 0); SurviveObject *wm1 = survive_create_wm1(ctx, "Playback", sp, 0); diff --git a/src/survive_vive.c b/src/survive_vive.c index 493215a..37bec7e 100755 --- a/src/survive_vive.c +++ b/src/survive_vive.c @@ -40,6 +40,7 @@ #endif #endif + struct SurviveViveData; const short vidpids[] = { -- cgit v1.2.3